{"entities.ent":"<!-- ********************************************************************* -->\n<!-- Copyright 2016                                                        -->\n<!-- Robert A. Beezer                                                      -->\n<!--                                                                       -->\n<!-- This file is part of PreTeXt.                                    -->\n<!--                                                                       -->\n<!-- PreTeXt is free software: you can redistribute it and/or modify  -->\n<!-- it under the terms of the GNU General Public License as published by  -->\n<!-- the Free Software Foundation, either version 2 or version 3 of the    -->\n<!-- License (at your option).                                             -->\n<!--                                                                       -->\n<!-- PreTeXt is distributed in the hope that it will be useful,       -->\n<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of        -->\n<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         -->\n<!-- GNU General Public License for more details.                          -->\n<!--                                                                       -->\n<!-- You should have received a copy of the GNU General Public License     -->\n<!-- along with PreTeXt.  If not, see <http://www.gnu.org/licenses/>. -->\n<!-- ********************************************************************* -->\n\n<!-- XSLT Cookbook, 2nd Edition                                     -->\n<!-- Copyright 2006, O'Reilly Media, Inc.                           -->\n<!-- Declaration and entity definition format from Recipe 2.8       -->\n<!-- Unicode strings from http://stackoverflow.com/questions/586231 -->\n<!ENTITY UPPERCASE \"'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ'\">\n<!ENTITY LOWERCASE \"'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ'\">\n\n<!-- Some more of our own design -->\n<!ENTITY DIGIT \"'0123456789'\">\n<!ENTITY ALPHABET \"'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'\">\n<!ENTITY SIMPLECHAR \"concat(&DIGIT;,&ALPHABET;)\">\n\n<!-- for match/select -->\n<!ENTITY STRUCTURAL \"book|article|slideshow|letter|memo|frontmatter|part|chapter|appendix|index|preface|acknowledgement|biography|foreword|dedication|colophon|section|subsection|subsubsection|slide|exercises|worksheet|handout|reading-questions|solutions|references|glossary|backmatter\">\n\n<!ENTITY TRADITIONAL-DIVISION \"book|article|part|chapter|section|subsection|subsubsection|appendix\">\n\n<!ENTITY SPECIALIZED-DIVISION \"exercises|worksheet|handout|reading-questions|references|glossary|solutions\">\n\n<!-- A \"printout\" is a specialized division whose content is laid out  -->\n<!-- for printing, with workspace for a reader to write.  A collection -->\n<!-- of nothing but printouts is a \"workbook\".                         -->\n<!ENTITY PRINTOUT \"worksheet|handout\">\n\n<!-- \"Division companions\" are the non-structural companions of a      -->\n<!-- structured traditional division: they may earn their own page    -->\n<!-- (and links) when their parent is realized as a summary page in   -->\n<!-- a chunked conversion (HTML and derivatives).  The schema only    -->\n<!-- allows these four elements, division-flavored, in the parents    -->\n<!-- listed.  The filter form presumes context has qualified parents. -->\n<!ENTITY DIVISION-COMPANION \"introduction[parent::article or parent::chapter or parent::appendix or parent::section or parent::subsection]|conclusion[parent::article or parent::chapter or parent::appendix or parent::section or parent::subsection]|objectives[parent::article or parent::chapter or parent::appendix or parent::section or parent::subsection]|outcomes[parent::article or parent::chapter or parent::appendix or parent::section or parent::subsection]\">\n\n<!-- for filtering nodes, eg *[&STRUCTURAL-FILTER;], *[not(&STRUCTURAL-FILTER;)] -->\n<!ENTITY STRUCTURAL-FILTER \"self::book or self::article or self::slideshow or self::letter or self::memo or self::frontmatter or self::part or self::chapter or self::appendix or self::index or self::preface or self::acknowledgement or self::biography or self::foreword or self::dedication or self::colophon or self::section or self::subsection or self::subsubsection or self::slide or self::exercises or self::worksheet or self::handout or self::reading-questions or self::solutions or self::references or self::glossary or self::backmatter\">\n\n<!ENTITY TRADITIONAL-DIVISION-FILTER \"self::book or self::article or self::part or self::chapter or self::section or self::subsection or self::subsubsection or self::appendix\">\n\n<!ENTITY SPECIALIZED-DIVISION-FILTER \"self::exercises or self::worksheet or self::handout or self::reading-questions or self::references or self::glossary or self::solutions\">\n\n<!ENTITY PRINTOUT-FILTER \"self::worksheet or self::handout\">\n\n<!ENTITY DIVISION-COMPANION-FILTER \"self::introduction or self::conclusion or self::objectives or self::outcomes\">\n\n<!-- NB: (2019-06-12)  Only the two metadata \"filters\" seem to          -->\n<!-- be in use, so only those are being maintained.  grep'ing on        -->\n<!-- METADATA v. METADATA-FILTER, and applying \"wc\" makes this evident. -->\n<!-- (Include this comment in count!)                                   -->\n\n<!-- typical items in blocks that get special treatment -->\n<!ENTITY METADATA \"title|subtitle|caption|idx|index\">\n<!ENTITY METADATA-FILTER \"self::title or self::subtitle or self::caption or self::idx or self::index[not(index-list)]\">\n\n<!-- Subdivisions and runs of paragraphs (like in a proof)  -->\n<!-- contain \"invisible\" items that get killed  and then    -->\n<!-- used/accessed other ways.  To see if something  is     -->\n<!--first, last, preceded, or followed by other significant -->\n<!-- items requires filtering out these items in forming a  -->\n<!-- node-set (so as to not be confused by their presence)  -->\n<!-- A super-lightweight \"article\" might have \"frontmatter\" -->\n<!-- and \"backmatter\" as peers of content elements, and in  -->\n<!-- other cases it should not be a problem                 -->\n<!-- Typical use:  *[not(&SUBDIVISION-METADATA-FILTER;)]    -->\n<!ENTITY SUBDIVISION-METADATA \"title|subtitle|index|notation|todo|frontmatter|backmatter\">\n<!ENTITY SUBDIVISION-METADATA-FILTER \"self::title or self::subtitle or self::idx or self::index[not(index-list)] or self::notation or self::todo or self::frontmatter or self::backmatter\">\n\n<!-- To implement a new category of blocks, search on    -->\n<!-- \"PROJECT-\" (case-sensitive) since we will mark      -->\n<!-- non-obvious locations with the string PROJECT-LIKE  -->\n<!-- as we immplement this on 2016-07-17, other entities -->\n<!-- below will also match this short form               -->\n\n<!-- definition, just a plain statement, but logically distinct -->\n<!ENTITY DEFINITION-LIKE \"definition\">\n<!ENTITY DEFINITION-FILTER \"self::definition\">\n\n<!-- statement + proof -->\n<!ENTITY THEOREM-LIKE \"theorem|corollary|lemma|algorithm|proposition|claim|fact|identity\">\n<!ENTITY THEOREM-FILTER \"self::theorem or self::corollary or self::lemma or self::algorithm or self::proposition or self::claim or self::fact or self::identity\">\n\n<!-- varieties of proofs -->\n<!ENTITY PROOF-LIKE \"proof|argument|justification|reasoning|explanation\">\n<!ENTITY PROOF-FILTER \"self::proof or self::argument or self::justification or self::reasoning or self::explanation\">\n\n<!-- three types of PROOF-LIKE -->\n<!-- in THEOREM-LIKE, detached/standalone, in solutions                                  -->\n<!-- INNER-PROOF-FILTER only used where heading levels are controlled                    -->\n<!-- SOLUTION-PROOF-FILTER used extensively to control LaTeX environments/macros/styling -->\n<!-- standalone/detached is just everything else (in division, or paragraphs, or...)     -->\n<!ENTITY INNER-PROOF-FILTER \"(&PROOF-FILTER;) and (parent::theorem or parent::corollary or parent::lemma or parent::algorithm or parent::proposition or parent::claim or parent::fact or parent::identity)\">\n<!ENTITY SOLUTION-PROOF-FILTER \"(&PROOF-FILTER;) and (ancestor::hint or ancestor::answer or ancestor::solution)\">\n\n<!-- a mathematical statement, but never with a proof -->\n<!ENTITY AXIOM-LIKE \"axiom|conjecture|principle|heuristic|hypothesis|assumption\">\n<!ENTITY AXIOM-FILTER \"self::axiom or self::conjecture or self::principle or self::heuristic or self::hypothesis or self::assumption\">\n\n<!-- narrative, set off for structure, reference -->\n<!ENTITY REMARK-LIKE \"remark|convention|note|observation|warning|insight\">\n<!ENTITY REMARK-FILTER \"self::remark or self::convention or self::note or self::observation or self::warning or self::insight\">\n\n<!-- about computations or technology -->\n<!ENTITY COMPUTATION-LIKE \"computation|technology|data\">\n<!ENTITY COMPUTATION-FILTER \"self::computation or self::technology or self::data\">\n\n<!-- incidental, skippable, lightweight -->\n<!ENTITY ASIDE-LIKE \"aside|biographical|historical\">\n<!ENTITY ASIDE-FILTER \"self::aside or self::biographical or self::historical\">\n\n<!-- blocks, or statement + solution -->\n<!ENTITY EXAMPLE-LIKE \"example|question|problem\">\n<!ENTITY EXAMPLE-FILTER \"self::example or self::question or self::problem\">\n\n<!-- blocks, or statement + solution -->\n<!-- save off lab, laboratory, experiment for science -->\n<!-- NB: update comprehensive list in the Guide with any additions -->\n<!ENTITY PROJECT-LIKE \"project|activity|exploration|investigation\">\n<!ENTITY PROJECT-FILTER \"self::project or self::activity or self::exploration or self::investigation\">\n\n<!-- blocks with meta-information in lists -->\n<!-- TODO: add in \"standards\", \"goals\"     -->\n<!-- NB: update comprehensive list in the Guide with any additions -->\n<!ENTITY GOAL-LIKE \"objectives|outcomes\">\n<!ENTITY GOAL-FILTER \"self::objectives or self::outcomes\">\n\n<!-- Open = research question/problem/conjecture -->\n<!ENTITY OPENPROBLEM-LIKE \"openproblem|openquestion|openconjecture\">\n<!ENTITY OPENPROBLEM-FILTER \"self::openproblem or self::openquestion or self::openconjecture\">\n\n<!-- displays with captions -->\n<!ENTITY FIGURE-LIKE \"figure|table|listing|list\">\n<!ENTITY FIGURE-FILTER \"self::figure or self::table or self::listing or self::list\">\n\n<!-- Composite filters for the numbering \"serial-stamp\" pass.  The      -->\n<!-- \"fundamental\" blocks always share the overall blocks counter; a    -->\n<!-- \"top\" figure-like is a captioned display that earns a number (a    -->\n<!-- panel inside a captioned side-by-side earns a letter instead).     -->\n<!ENTITY FUNDAMENTAL-BLOCK-FILTER \"(&DEFINITION-FILTER;) or (&THEOREM-FILTER;) or (&AXIOM-FILTER;) or (&REMARK-FILTER;) or (&COMPUTATION-FILTER;) or (&EXAMPLE-FILTER;)\">\n<!ENTITY TOP-FIGURE-FILTER \"(&FIGURE-FILTER;) and not(parent::sidebyside/parent::figure or parent::sidebyside/parent::sbsgroup/parent::figure)\">\n\n<!-- Panels of a \"sidebyside\", and content of a \"stack\" panel.  The   -->\n<!-- lists mirror the schema, plus grandfathered items the code still -->\n<!-- tolerates: \"audio\", \"video\", \"interactive\" (precluded            -->\n<!-- 2026-07-22, may someday be removed).  An \"exercise\" panel        -->\n<!-- (worksheet or handout only) and a \"slate\" panel (within an       -->\n<!-- \"interactive\" only) are policed by the validation-plus           -->\n<!-- stylesheet.                                                      -->\n<!ENTITY SBSPANEL \"p|pre|ol|ul|dl|program|console|poem|audio|video|interactive|slate|exercise|image|figure|table|listing|list|tabular|stack\">\n<!ENTITY STACKABLE \"tabular|image|p|pre|ol|ul|dl|audio|video|interactive|slate|program|console\">\n\n<!-- appendages of examples, exercises, tasks -->\n<!ENTITY SOLUTION-LIKE \"hint|answer|solution\">\n<!ENTITY SOLUTION-FILTER \"self::hint or self::answer or self::solution\">\n\n<!-- appendages of OPENPROBLEM-LIKE -->\n<!ENTITY DISCUSSION-LIKE \"context|discussion|opinion|status|suggestion\">\n<!ENTITY DISCUSSION-FILTER \"self::context or self::discussion or self::opinion or self::status or self::suggestion\">\n\n<!-- Elements the schema gives text-only content: no PreTeXt markup is   -->\n<!-- permitted inside them, whether because they are verbatim (code, a   -->\n<!-- graphics language, a LaTeX fragment) or because the element is a    -->\n<!-- plain string (a \"shortdescription\", a bibliography field).  Advice  -->\n<!-- to replace a stray character with an element cannot be followed in  -->\n<!-- these, so the validation-plus stylesheet withholds it there.        -->\n<!-- Every name below is text-only in EVERY declaration in the schema.   -->\n<!-- Deliberately absent: \"author\", \"editor\", \"page\" and \"year\", each of -->\n<!-- which is text in one context and markup in another.                 -->\n<!ENTITY TEXT-ONLY-FILTER \"self::DOI or self::ISBN or self::ISSN or self::URL or self::asymptote or self::asymptote-preamble or self::attr or self::blurb or self::c or self::cd or self::cline or self::code or self::document-id or self::dropping-particle or self::edition or self::email or self::family or self::genre or self::genus or self::given or self::holder or self::initialism or self::input or self::issue or self::kbd or self::latex-image or self::latex-image-preamble or self::literal or self::macro-file or self::macros or self::mag or self::mermaid or self::non-dropping-particle or self::number or self::number-of-pages or self::output or self::page-first or self::pages or self::pf or self::pg-code or self::plaintitle or self::postamble or self::pre or self::preamble or self::publisher or self::rename or self::sageplot or self::series or self::shortdescription or self::species or self::static-ordering or self::stdin or self::suffix or self::tag or self::tage or self::volume\">\n\n<!-- When context is an inline \"exercise\", then this condition is      -->\n<!-- true. We are positive, so as new locations of \"exercise\"          -->\n<!-- are added, then this need not change                              -->\n<!-- Typical use: self::exercise and boolean(&INLINE-EXERCISE-FILTER;) -->\n<!ENTITY INLINE-EXERCISE-FILTER \"parent::article|parent::paragraphs|parent::chapter|parent::appendix|parent::section|parent::subsection|parent::subsubsection|parent::handout\">\n","html-symbols.xsl":"<?xml version='1.0'?> <!-- As XML file -->\n\n<!-- Contains an xsl list of symbols provided by the Material Symbols font -->\n<!-- Used by the insert-symbol template in pretext-html                    -->\n\n<!-- http://pimpmyxslt.com/articles/entity-tricks-part2/ -->\n<!DOCTYPE xsl:stylesheet [\n    <!ENTITY % entities SYSTEM \"entities.ent\">\n    %entities;\n]>\n\n<!-- Identify as a stylesheet -->\n<!-- We choose to not include a default namespace       -->\n<!-- (in particular  http://www.w3.org/1999/xhtml),     -->\n<!-- even if this complicates adding namespaces onto    -->\n<!-- derivatives, such as HTML destined for EPUB output -->\n<!-- xmlns=\"http://www.w3.org/1999/xhtml\"               -->\n<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n\n<!-- From Material Symbols: https://github.com/google/material-design-icons/blob/master -->\n<!-- License: Apache 2.0 https://github.com/google/material-design-icons/blob/master/LICENSE -->\n\n<xsl:variable name=\"available-symbols-list\">\n    <symbolinfo name=\"10k\" entity=\"e951\"/>\n    <symbolinfo name=\"10mp\" entity=\"e952\"/>\n    <symbolinfo name=\"11mp\" entity=\"e953\"/>\n    <symbolinfo name=\"123\" entity=\"eb8d\"/>\n    <symbolinfo name=\"12mp\" entity=\"e954\"/>\n    <symbolinfo name=\"13mp\" entity=\"e955\"/>\n    <symbolinfo name=\"14mp\" entity=\"e956\"/>\n    <symbolinfo name=\"15mp\" entity=\"e957\"/>\n    <symbolinfo name=\"16mp\" entity=\"e958\"/>\n    <symbolinfo name=\"17mp\" entity=\"e959\"/>\n    <symbolinfo name=\"18_up_rating\" entity=\"f8fd\"/>\n    <symbolinfo name=\"18mp\" entity=\"e95a\"/>\n    <symbolinfo name=\"19mp\" entity=\"e95b\"/>\n    <symbolinfo name=\"1k\" entity=\"e95c\"/>\n    <symbolinfo name=\"1k_plus\" entity=\"e95d\"/>\n    <symbolinfo name=\"1x_mobiledata\" entity=\"efcd\"/>\n    <symbolinfo name=\"1x_mobiledata_badge\" entity=\"f7f1\"/>\n    <symbolinfo name=\"20mp\" entity=\"e95e\"/>\n    <symbolinfo name=\"21mp\" entity=\"e95f\"/>\n    <symbolinfo name=\"22mp\" entity=\"e960\"/>\n    <symbolinfo name=\"23mp\" entity=\"e961\"/>\n    <symbolinfo name=\"24mp\" entity=\"e962\"/>\n    <symbolinfo name=\"2d\" entity=\"ef37\"/>\n    <symbolinfo name=\"2k\" entity=\"e963\"/>\n    <symbolinfo name=\"2k_plus\" entity=\"e964\"/>\n    <symbolinfo name=\"2mp\" entity=\"e965\"/>\n    <symbolinfo name=\"30fps\" entity=\"efce\"/>\n    <symbolinfo name=\"30fps_select\" entity=\"efcf\"/>\n    <symbolinfo name=\"360\" entity=\"e577\"/>\n    <symbolinfo name=\"3d_rotation\" entity=\"e84d\"/>\n    <symbolinfo name=\"3g_mobiledata\" entity=\"efd0\"/>\n    <symbolinfo name=\"3g_mobiledata_badge\" entity=\"f7f0\"/>\n    <symbolinfo name=\"3k\" entity=\"e966\"/>\n    <symbolinfo name=\"3k_plus\" entity=\"e967\"/>\n    <symbolinfo name=\"3mp\" entity=\"e968\"/>\n    <symbolinfo name=\"3p\" entity=\"efd1\"/>\n    <symbolinfo name=\"4g_mobiledata\" entity=\"efd2\"/>\n    <symbolinfo name=\"4g_mobiledata_badge\" entity=\"f7ef\"/>\n    <symbolinfo name=\"4g_plus_mobiledata\" entity=\"efd3\"/>\n    <symbolinfo name=\"4k\" entity=\"e072\"/>\n    <symbolinfo name=\"4k_plus\" entity=\"e969\"/>\n    <symbolinfo name=\"4mp\" entity=\"e96a\"/>\n    <symbolinfo name=\"50mp\" entity=\"f6f3\"/>\n    <symbolinfo name=\"5g\" entity=\"ef38\"/>\n    <symbolinfo name=\"5g_mobiledata_badge\" entity=\"f7ee\"/>\n    <symbolinfo name=\"5k\" entity=\"e96b\"/>\n    <symbolinfo name=\"5k_plus\" entity=\"e96c\"/>\n    <symbolinfo name=\"5mp\" entity=\"e96d\"/>\n    <symbolinfo name=\"60fps\" entity=\"efd4\"/>\n    <symbolinfo name=\"60fps_select\" entity=\"efd5\"/>\n    <symbolinfo name=\"6_ft_apart\" entity=\"f21e\"/>\n    <symbolinfo name=\"6k\" entity=\"e96e\"/>\n    <symbolinfo name=\"6k_plus\" entity=\"e96f\"/>\n    <symbolinfo name=\"6mp\" entity=\"e970\"/>\n    <symbolinfo name=\"7k\" entity=\"e971\"/>\n    <symbolinfo name=\"7k_plus\" entity=\"e972\"/>\n    <symbolinfo name=\"7mp\" entity=\"e973\"/>\n    <symbolinfo name=\"8k\" entity=\"e974\"/>\n    <symbolinfo name=\"8k_plus\" entity=\"e975\"/>\n    <symbolinfo name=\"8mp\" entity=\"e976\"/>\n    <symbolinfo name=\"9k\" entity=\"e977\"/>\n    <symbolinfo name=\"9k_plus\" entity=\"e978\"/>\n    <symbolinfo name=\"9mp\" entity=\"e979\"/>\n    <symbolinfo name=\"abc\" entity=\"eb94\"/>\n    <symbolinfo name=\"ac_unit\" entity=\"eb3b\"/>\n    <symbolinfo name=\"access_alarm\" entity=\"e855\"/>\n    <symbolinfo name=\"access_alarms\" entity=\"e855\"/>\n    <symbolinfo name=\"access_time\" entity=\"efd6\"/>\n    <symbolinfo name=\"access_time_filled\" entity=\"efd6\"/>\n    <symbolinfo name=\"accessibility\" entity=\"e84e\"/>\n    <symbolinfo name=\"accessibility_new\" entity=\"e92c\"/>\n    <symbolinfo name=\"accessible\" entity=\"e914\"/>\n    <symbolinfo name=\"accessible_forward\" entity=\"e934\"/>\n    <symbolinfo name=\"account_balance\" entity=\"e84f\"/>\n    <symbolinfo name=\"account_balance_wallet\" entity=\"e850\"/>\n    <symbolinfo name=\"account_box\" entity=\"e851\"/>\n    <symbolinfo name=\"account_circle\" entity=\"f20b\"/>\n    <symbolinfo name=\"account_circle_filled\" entity=\"f20b\"/>\n    <symbolinfo name=\"account_circle_off\" entity=\"f7b3\"/>\n    <symbolinfo name=\"account_tree\" entity=\"e97a\"/>\n    <symbolinfo name=\"activity_zone\" entity=\"e1e6\"/>\n    <symbolinfo name=\"acute\" entity=\"e4cb\"/>\n    <symbolinfo name=\"ad\" entity=\"e65a\"/>\n    <symbolinfo name=\"ad_group\" entity=\"e65b\"/>\n    <symbolinfo name=\"ad_group_off\" entity=\"eae5\"/>\n    <symbolinfo name=\"ad_off\" entity=\"f7b2\"/>\n    <symbolinfo name=\"ad_units\" entity=\"ef39\"/>\n    <symbolinfo name=\"adb\" entity=\"e60e\"/>\n    <symbolinfo name=\"add\" entity=\"e145\"/>\n    <symbolinfo name=\"add_a_photo\" entity=\"e439\"/>\n    <symbolinfo name=\"add_ad\" entity=\"e72a\"/>\n    <symbolinfo name=\"add_alarm\" entity=\"e856\"/>\n    <symbolinfo name=\"add_alert\" entity=\"e003\"/>\n    <symbolinfo name=\"add_box\" entity=\"e146\"/>\n    <symbolinfo name=\"add_business\" entity=\"e729\"/>\n    <symbolinfo name=\"add_call\" entity=\"f0b7\"/>\n    <symbolinfo name=\"add_card\" entity=\"eb86\"/>\n    <symbolinfo name=\"add_chart\" entity=\"ef3c\"/>\n    <symbolinfo name=\"add_circle\" entity=\"e3ba\"/>\n    <symbolinfo name=\"add_circle_outline\" entity=\"e3ba\"/>\n    <symbolinfo name=\"add_comment\" entity=\"e266\"/>\n    <symbolinfo name=\"add_home\" entity=\"f8eb\"/>\n    <symbolinfo name=\"add_home_work\" entity=\"f8ed\"/>\n    <symbolinfo name=\"add_ic_call\" entity=\"f0b7\"/>\n    <symbolinfo name=\"add_link\" entity=\"e178\"/>\n    <symbolinfo name=\"add_location\" entity=\"e567\"/>\n    <symbolinfo name=\"add_location_alt\" entity=\"ef3a\"/>\n    <symbolinfo name=\"add_moderator\" entity=\"e97d\"/>\n    <symbolinfo name=\"add_notes\" entity=\"e091\"/>\n    <symbolinfo name=\"add_photo_alternate\" entity=\"e43e\"/>\n    <symbolinfo name=\"add_reaction\" entity=\"e1d3\"/>\n    <symbolinfo name=\"add_road\" entity=\"ef3b\"/>\n    <symbolinfo name=\"add_shopping_cart\" entity=\"e854\"/>\n    <symbolinfo name=\"add_task\" entity=\"f23a\"/>\n    <symbolinfo name=\"add_to_drive\" entity=\"e65c\"/>\n    <symbolinfo name=\"add_to_home_screen\" entity=\"e1fe\"/>\n    <symbolinfo name=\"add_to_photos\" entity=\"e39d\"/>\n    <symbolinfo name=\"add_to_queue\" entity=\"e05c\"/>\n    <symbolinfo name=\"addchart\" entity=\"ef3c\"/>\n    <symbolinfo name=\"adf_scanner\" entity=\"eada\"/>\n    <symbolinfo name=\"adjust\" entity=\"e39e\"/>\n    <symbolinfo name=\"admin_meds\" entity=\"e48d\"/>\n    <symbolinfo name=\"admin_panel_settings\" entity=\"ef3d\"/>\n    <symbolinfo name=\"ads_click\" entity=\"e762\"/>\n    <symbolinfo name=\"agender\" entity=\"f888\"/>\n    <symbolinfo name=\"agriculture\" entity=\"ea79\"/>\n    <symbolinfo name=\"air\" entity=\"efd8\"/>\n    <symbolinfo name=\"air_freshener\" entity=\"e2ca\"/>\n    <symbolinfo name=\"air_purifier_gen\" entity=\"e829\"/>\n    <symbolinfo name=\"airline_seat_flat\" entity=\"e630\"/>\n    <symbolinfo name=\"airline_seat_flat_angled\" entity=\"e631\"/>\n    <symbolinfo name=\"airline_seat_individual_suite\" entity=\"e632\"/>\n    <symbolinfo name=\"airline_seat_legroom_extra\" entity=\"e633\"/>\n    <symbolinfo name=\"airline_seat_legroom_normal\" entity=\"e634\"/>\n    <symbolinfo name=\"airline_seat_legroom_reduced\" entity=\"e635\"/>\n    <symbolinfo name=\"airline_seat_recline_extra\" entity=\"e636\"/>\n    <symbolinfo name=\"airline_seat_recline_normal\" entity=\"e637\"/>\n    <symbolinfo name=\"airline_stops\" entity=\"e7d0\"/>\n    <symbolinfo name=\"airlines\" entity=\"e7ca\"/>\n    <symbolinfo name=\"airplane_ticket\" entity=\"efd9\"/>\n    <symbolinfo name=\"airplanemode_active\" entity=\"e53d\"/>\n    <symbolinfo name=\"airplanemode_inactive\" entity=\"e194\"/>\n    <symbolinfo name=\"airplay\" entity=\"e055\"/>\n    <symbolinfo name=\"airport_shuttle\" entity=\"eb3c\"/>\n    <symbolinfo name=\"airware\" entity=\"f154\"/>\n    <symbolinfo name=\"airwave\" entity=\"f154\"/>\n    <symbolinfo name=\"alarm\" entity=\"e855\"/>\n    <symbolinfo name=\"alarm_add\" entity=\"e856\"/>\n    <symbolinfo name=\"alarm_off\" entity=\"e857\"/>\n    <symbolinfo name=\"alarm_on\" entity=\"e858\"/>\n    <symbolinfo name=\"alarm_smart_wake\" entity=\"f6b0\"/>\n    <symbolinfo name=\"album\" entity=\"e019\"/>\n    <symbolinfo name=\"align_center\" entity=\"e356\"/>\n    <symbolinfo name=\"align_end\" entity=\"f797\"/>\n    <symbolinfo name=\"align_flex_center\" entity=\"f796\"/>\n    <symbolinfo name=\"align_flex_end\" entity=\"f795\"/>\n    <symbolinfo name=\"align_flex_start\" entity=\"f794\"/>\n    <symbolinfo name=\"align_horizontal_center\" entity=\"e00f\"/>\n    <symbolinfo name=\"align_horizontal_left\" entity=\"e00d\"/>\n    <symbolinfo name=\"align_horizontal_right\" entity=\"e010\"/>\n    <symbolinfo name=\"align_items_stretch\" entity=\"f793\"/>\n    <symbolinfo name=\"align_justify_center\" entity=\"f792\"/>\n    <symbolinfo name=\"align_justify_flex_end\" entity=\"f791\"/>\n    <symbolinfo name=\"align_justify_flex_start\" entity=\"f790\"/>\n    <symbolinfo name=\"align_justify_space_around\" entity=\"f78f\"/>\n    <symbolinfo name=\"align_justify_space_between\" entity=\"f78e\"/>\n    <symbolinfo name=\"align_justify_space_even\" entity=\"f78d\"/>\n    <symbolinfo name=\"align_justify_stretch\" entity=\"f78c\"/>\n    <symbolinfo name=\"align_self_stretch\" entity=\"f78b\"/>\n    <symbolinfo name=\"align_space_around\" entity=\"f78a\"/>\n    <symbolinfo name=\"align_space_between\" entity=\"f789\"/>\n    <symbolinfo name=\"align_space_even\" entity=\"f788\"/>\n    <symbolinfo name=\"align_start\" entity=\"f787\"/>\n    <symbolinfo name=\"align_stretch\" entity=\"f786\"/>\n    <symbolinfo name=\"align_vertical_bottom\" entity=\"e015\"/>\n    <symbolinfo name=\"align_vertical_center\" entity=\"e011\"/>\n    <symbolinfo name=\"align_vertical_top\" entity=\"e00c\"/>\n    <symbolinfo name=\"all_inbox\" entity=\"e97f\"/>\n    <symbolinfo name=\"all_inclusive\" entity=\"eb3d\"/>\n    <symbolinfo name=\"all_match\" entity=\"e093\"/>\n    <symbolinfo name=\"all_out\" entity=\"e90b\"/>\n    <symbolinfo name=\"allergies\" entity=\"e094\"/>\n    <symbolinfo name=\"allergy\" entity=\"e64e\"/>\n    <symbolinfo name=\"alt_route\" entity=\"f184\"/>\n    <symbolinfo name=\"alternate_email\" entity=\"e0e6\"/>\n    <symbolinfo name=\"altitude\" entity=\"f873\"/>\n    <symbolinfo name=\"ambient_screen\" entity=\"f6c4\"/>\n    <symbolinfo name=\"ambulance\" entity=\"f803\"/>\n    <symbolinfo name=\"amend\" entity=\"f802\"/>\n    <symbolinfo name=\"amp_stories\" entity=\"ea13\"/>\n    <symbolinfo name=\"analytics\" entity=\"ef3e\"/>\n    <symbolinfo name=\"anchor\" entity=\"f1cd\"/>\n    <symbolinfo name=\"android\" entity=\"e859\"/>\n    <symbolinfo name=\"animation\" entity=\"e71c\"/>\n    <symbolinfo name=\"announcement\" entity=\"e87f\"/>\n    <symbolinfo name=\"aod\" entity=\"efda\"/>\n    <symbolinfo name=\"aod_tablet\" entity=\"f89f\"/>\n    <symbolinfo name=\"aod_watch\" entity=\"f6ac\"/>\n    <symbolinfo name=\"apartment\" entity=\"ea40\"/>\n    <symbolinfo name=\"api\" entity=\"f1b7\"/>\n    <symbolinfo name=\"apk_document\" entity=\"f88e\"/>\n    <symbolinfo name=\"apk_install\" entity=\"f88f\"/>\n    <symbolinfo name=\"app_badging\" entity=\"f72f\"/>\n    <symbolinfo name=\"app_blocking\" entity=\"ef3f\"/>\n    <symbolinfo name=\"app_promo\" entity=\"e981\"/>\n    <symbolinfo name=\"app_registration\" entity=\"ef40\"/>\n    <symbolinfo name=\"app_settings_alt\" entity=\"ef41\"/>\n    <symbolinfo name=\"app_shortcut\" entity=\"eae4\"/>\n    <symbolinfo name=\"approval\" entity=\"e982\"/>\n    <symbolinfo name=\"approval_delegation\" entity=\"f84a\"/>\n    <symbolinfo name=\"apps\" entity=\"e5c3\"/>\n    <symbolinfo name=\"apps_outage\" entity=\"e7cc\"/>\n    <symbolinfo name=\"aq\" entity=\"f55a\"/>\n    <symbolinfo name=\"aq_indoor\" entity=\"f55b\"/>\n    <symbolinfo name=\"ar_on_you\" entity=\"ef7c\"/>\n    <symbolinfo name=\"architecture\" entity=\"ea3b\"/>\n    <symbolinfo name=\"archive\" entity=\"e149\"/>\n    <symbolinfo name=\"area_chart\" entity=\"e770\"/>\n    <symbolinfo name=\"arming_countdown\" entity=\"e78a\"/>\n    <symbolinfo name=\"arrow_and_edge\" entity=\"f5d7\"/>\n    <symbolinfo name=\"arrow_back\" entity=\"e5c4\"/>\n    <symbolinfo name=\"arrow_back_ios\" entity=\"e5e0\"/>\n    <symbolinfo name=\"arrow_back_ios_new\" entity=\"e2ea\"/>\n    <symbolinfo name=\"arrow_circle_down\" entity=\"f181\"/>\n    <symbolinfo name=\"arrow_circle_left\" entity=\"eaa7\"/>\n    <symbolinfo name=\"arrow_circle_right\" entity=\"eaaa\"/>\n    <symbolinfo name=\"arrow_circle_up\" entity=\"f182\"/>\n    <symbolinfo name=\"arrow_downward\" entity=\"e5db\"/>\n    <symbolinfo name=\"arrow_downward_alt\" entity=\"e984\"/>\n    <symbolinfo name=\"arrow_drop_down\" entity=\"e5c5\"/>\n    <symbolinfo name=\"arrow_drop_down_circle\" entity=\"e5c6\"/>\n    <symbolinfo name=\"arrow_drop_up\" entity=\"e5c7\"/>\n    <symbolinfo name=\"arrow_forward\" entity=\"e5c8\"/>\n    <symbolinfo name=\"arrow_forward_ios\" entity=\"e5e1\"/>\n    <symbolinfo name=\"arrow_insert\" entity=\"f837\"/>\n    <symbolinfo name=\"arrow_left\" entity=\"e5de\"/>\n    <symbolinfo name=\"arrow_left_alt\" entity=\"ef7d\"/>\n    <symbolinfo name=\"arrow_or_edge\" entity=\"f5d6\"/>\n    <symbolinfo name=\"arrow_outward\" entity=\"f8ce\"/>\n    <symbolinfo name=\"arrow_range\" entity=\"f69b\"/>\n    <symbolinfo name=\"arrow_right\" entity=\"e5df\"/>\n    <symbolinfo name=\"arrow_right_alt\" entity=\"e941\"/>\n    <symbolinfo name=\"arrow_selector_tool\" entity=\"f82f\"/>\n    <symbolinfo name=\"arrow_split\" entity=\"ea04\"/>\n    <symbolinfo name=\"arrow_top_left\" entity=\"f72e\"/>\n    <symbolinfo name=\"arrow_top_right\" entity=\"f72d\"/>\n    <symbolinfo name=\"arrow_upward\" entity=\"e5d8\"/>\n    <symbolinfo name=\"arrow_upward_alt\" entity=\"e986\"/>\n    <symbolinfo name=\"arrows_more_down\" entity=\"f8ab\"/>\n    <symbolinfo name=\"arrows_more_up\" entity=\"f8ac\"/>\n    <symbolinfo name=\"arrows_outward\" entity=\"f72c\"/>\n    <symbolinfo name=\"art_track\" entity=\"e060\"/>\n    <symbolinfo name=\"article\" entity=\"ef42\"/>\n    <symbolinfo name=\"article_shortcut\" entity=\"f587\"/>\n    <symbolinfo name=\"aspect_ratio\" entity=\"e85b\"/>\n    <symbolinfo name=\"assessment\" entity=\"f0cc\"/>\n    <symbolinfo name=\"assignment\" entity=\"e85d\"/>\n    <symbolinfo name=\"assignment_add\" entity=\"f848\"/>\n    <symbolinfo name=\"assignment_ind\" entity=\"e85e\"/>\n    <symbolinfo name=\"assignment_late\" entity=\"e85f\"/>\n    <symbolinfo name=\"assignment_return\" entity=\"e860\"/>\n    <symbolinfo name=\"assignment_returned\" entity=\"e861\"/>\n    <symbolinfo name=\"assignment_turned_in\" entity=\"e862\"/>\n    <symbolinfo name=\"assist_walker\" entity=\"f8d5\"/>\n    <symbolinfo name=\"assistant\" entity=\"e39f\"/>\n    <symbolinfo name=\"assistant_direction\" entity=\"e988\"/>\n    <symbolinfo name=\"assistant_navigation\" entity=\"e989\"/>\n    <symbolinfo name=\"assistant_on_hub\" entity=\"f6c1\"/>\n    <symbolinfo name=\"assistant_photo\" entity=\"f0c6\"/>\n    <symbolinfo name=\"assured_workload\" entity=\"eb6f\"/>\n    <symbolinfo name=\"astrophotography_auto\" entity=\"f1d9\"/>\n    <symbolinfo name=\"astrophotography_off\" entity=\"f1da\"/>\n    <symbolinfo name=\"atm\" entity=\"e573\"/>\n    <symbolinfo name=\"atr\" entity=\"ebc7\"/>\n    <symbolinfo name=\"attach_email\" entity=\"ea5e\"/>\n    <symbolinfo name=\"attach_file\" entity=\"e226\"/>\n    <symbolinfo name=\"attach_file_add\" entity=\"f841\"/>\n    <symbolinfo name=\"attach_money\" entity=\"e227\"/>\n    <symbolinfo name=\"attachment\" entity=\"e2bc\"/>\n    <symbolinfo name=\"attractions\" entity=\"ea52\"/>\n    <symbolinfo name=\"attribution\" entity=\"efdb\"/>\n    <symbolinfo name=\"audio_description\" entity=\"f58c\"/>\n    <symbolinfo name=\"audio_file\" entity=\"eb82\"/>\n    <symbolinfo name=\"audio_video_receiver\" entity=\"f5d3\"/>\n    <symbolinfo name=\"audiotrack\" entity=\"e405\"/>\n    <symbolinfo name=\"auto_activity_zone\" entity=\"f8ad\"/>\n    <symbolinfo name=\"auto_awesome\" entity=\"e65f\"/>\n    <symbolinfo name=\"auto_awesome_mosaic\" entity=\"e660\"/>\n    <symbolinfo name=\"auto_awesome_motion\" entity=\"e661\"/>\n    <symbolinfo name=\"auto_delete\" entity=\"ea4c\"/>\n    <symbolinfo name=\"auto_detect_voice\" entity=\"f83e\"/>\n    <symbolinfo name=\"auto_fix\" entity=\"e663\"/>\n    <symbolinfo name=\"auto_fix_high\" entity=\"e663\"/>\n    <symbolinfo name=\"auto_fix_normal\" entity=\"e664\"/>\n    <symbolinfo name=\"auto_fix_off\" entity=\"e665\"/>\n    <symbolinfo name=\"auto_graph\" entity=\"e4fb\"/>\n    <symbolinfo name=\"auto_label\" entity=\"f6be\"/>\n    <symbolinfo name=\"auto_meeting_room\" entity=\"f6bf\"/>\n    <symbolinfo name=\"auto_mode\" entity=\"ec20\"/>\n    <symbolinfo name=\"auto_read_pause\" entity=\"f219\"/>\n    <symbolinfo name=\"auto_read_play\" entity=\"f216\"/>\n    <symbolinfo name=\"auto_schedule\" entity=\"e214\"/>\n    <symbolinfo name=\"auto_stories\" entity=\"e666\"/>\n    <symbolinfo name=\"auto_timer\" entity=\"ef7f\"/>\n    <symbolinfo name=\"auto_videocam\" entity=\"f6c0\"/>\n    <symbolinfo name=\"autofps_select\" entity=\"efdc\"/>\n    <symbolinfo name=\"autopause\" entity=\"f6b6\"/>\n    <symbolinfo name=\"autopay\" entity=\"f84b\"/>\n    <symbolinfo name=\"autoplay\" entity=\"f6b5\"/>\n    <symbolinfo name=\"autorenew\" entity=\"e863\"/>\n    <symbolinfo name=\"autostop\" entity=\"f682\"/>\n    <symbolinfo name=\"av_timer\" entity=\"e01b\"/>\n    <symbolinfo name=\"avg_pace\" entity=\"f6bb\"/>\n    <symbolinfo name=\"avg_time\" entity=\"f813\"/>\n    <symbolinfo name=\"award_star\" entity=\"f612\"/>\n    <symbolinfo name=\"azm\" entity=\"f6ec\"/>\n    <symbolinfo name=\"baby_changing_station\" entity=\"f19b\"/>\n    <symbolinfo name=\"back_hand\" entity=\"e764\"/>\n    <symbolinfo name=\"back_to_tab\" entity=\"f72b\"/>\n    <symbolinfo name=\"background_dot_large\" entity=\"f79e\"/>\n    <symbolinfo name=\"background_grid_small\" entity=\"f79d\"/>\n    <symbolinfo name=\"background_replace\" entity=\"f20a\"/>\n    <symbolinfo name=\"backlight_high\" entity=\"f7ed\"/>\n    <symbolinfo name=\"backlight_low\" entity=\"f7ec\"/>\n    <symbolinfo name=\"backpack\" entity=\"f19c\"/>\n    <symbolinfo name=\"backspace\" entity=\"e14a\"/>\n    <symbolinfo name=\"backup\" entity=\"e864\"/>\n    <symbolinfo name=\"backup_table\" entity=\"ef43\"/>\n    <symbolinfo name=\"badge\" entity=\"ea67\"/>\n    <symbolinfo name=\"badge_critical_battery\" entity=\"f156\"/>\n    <symbolinfo name=\"bakery_dining\" entity=\"ea53\"/>\n    <symbolinfo name=\"balance\" entity=\"eaf6\"/>\n    <symbolinfo name=\"balcony\" entity=\"e58f\"/>\n    <symbolinfo name=\"ballot\" entity=\"e172\"/>\n    <symbolinfo name=\"bar_chart\" entity=\"e26b\"/>\n    <symbolinfo name=\"bar_chart_4_bars\" entity=\"f681\"/>\n    <symbolinfo name=\"barcode\" entity=\"e70b\"/>\n    <symbolinfo name=\"barcode_reader\" entity=\"f85c\"/>\n    <symbolinfo name=\"barcode_scanner\" entity=\"e70c\"/>\n    <symbolinfo name=\"barefoot\" entity=\"f871\"/>\n    <symbolinfo name=\"batch_prediction\" entity=\"f0f5\"/>\n    <symbolinfo name=\"bath_outdoor\" entity=\"f6fb\"/>\n    <symbolinfo name=\"bath_private\" entity=\"f6fa\"/>\n    <symbolinfo name=\"bath_public_large\" entity=\"f6f9\"/>\n    <symbolinfo name=\"bathroom\" entity=\"efdd\"/>\n    <symbolinfo name=\"bathtub\" entity=\"ea41\"/>\n    <symbolinfo name=\"battery_0_bar\" entity=\"ebdc\"/>\n    <symbolinfo name=\"battery_1_bar\" entity=\"f09c\"/>\n    <symbolinfo name=\"battery_20\" entity=\"f09c\"/>\n    <symbolinfo name=\"battery_2_bar\" entity=\"f09d\"/>\n    <symbolinfo name=\"battery_30\" entity=\"f09d\"/>\n    <symbolinfo name=\"battery_3_bar\" entity=\"f09e\"/>\n    <symbolinfo name=\"battery_4_bar\" entity=\"f09f\"/>\n    <symbolinfo name=\"battery_50\" entity=\"f09e\"/>\n    <symbolinfo name=\"battery_5_bar\" entity=\"f0a0\"/>\n    <symbolinfo name=\"battery_60\" entity=\"f09f\"/>\n    <symbolinfo name=\"battery_6_bar\" entity=\"f0a1\"/>\n    <symbolinfo name=\"battery_80\" entity=\"f0a0\"/>\n    <symbolinfo name=\"battery_90\" entity=\"f0a1\"/>\n    <symbolinfo name=\"battery_alert\" entity=\"e19c\"/>\n    <symbolinfo name=\"battery_change\" entity=\"f7eb\"/>\n    <symbolinfo name=\"battery_charging_20\" entity=\"f0a2\"/>\n    <symbolinfo name=\"battery_charging_30\" entity=\"f0a3\"/>\n    <symbolinfo name=\"battery_charging_50\" entity=\"f0a4\"/>\n    <symbolinfo name=\"battery_charging_60\" entity=\"f0a5\"/>\n    <symbolinfo name=\"battery_charging_80\" entity=\"f0a6\"/>\n    <symbolinfo name=\"battery_charging_90\" entity=\"f0a7\"/>\n    <symbolinfo name=\"battery_charging_full\" entity=\"e1a3\"/>\n    <symbolinfo name=\"battery_error\" entity=\"f7ea\"/>\n    <symbolinfo name=\"battery_full\" entity=\"e1a5\"/>\n    <symbolinfo name=\"battery_full_alt\" entity=\"f13b\"/>\n    <symbolinfo name=\"battery_horiz_000\" entity=\"f8ae\"/>\n    <symbolinfo name=\"battery_horiz_050\" entity=\"f8af\"/>\n    <symbolinfo name=\"battery_horiz_075\" entity=\"f8b0\"/>\n    <symbolinfo name=\"battery_low\" entity=\"f155\"/>\n    <symbolinfo name=\"battery_plus\" entity=\"f7e9\"/>\n    <symbolinfo name=\"battery_profile\" entity=\"e206\"/>\n    <symbolinfo name=\"battery_saver\" entity=\"efde\"/>\n    <symbolinfo name=\"battery_share\" entity=\"f67e\"/>\n    <symbolinfo name=\"battery_status_good\" entity=\"f67d\"/>\n    <symbolinfo name=\"battery_std\" entity=\"e1a5\"/>\n    <symbolinfo name=\"battery_unknown\" entity=\"e1a6\"/>\n    <symbolinfo name=\"battery_vert_005\" entity=\"f8b1\"/>\n    <symbolinfo name=\"battery_vert_020\" entity=\"f8b2\"/>\n    <symbolinfo name=\"battery_vert_050\" entity=\"f8b3\"/>\n    <symbolinfo name=\"battery_very_low\" entity=\"f156\"/>\n    <symbolinfo name=\"beach_access\" entity=\"eb3e\"/>\n    <symbolinfo name=\"bed\" entity=\"efdf\"/>\n    <symbolinfo name=\"bedroom_baby\" entity=\"efe0\"/>\n    <symbolinfo name=\"bedroom_child\" entity=\"efe1\"/>\n    <symbolinfo name=\"bedroom_parent\" entity=\"efe2\"/>\n    <symbolinfo name=\"bedtime\" entity=\"ef44\"/>\n    <symbolinfo name=\"bedtime_off\" entity=\"eb76\"/>\n    <symbolinfo name=\"beenhere\" entity=\"e52d\"/>\n    <symbolinfo name=\"bento\" entity=\"f1f4\"/>\n    <symbolinfo name=\"bia\" entity=\"f6eb\"/>\n    <symbolinfo name=\"bid_landscape\" entity=\"e678\"/>\n    <symbolinfo name=\"bid_landscape_disabled\" entity=\"ef81\"/>\n    <symbolinfo name=\"bike_scooter\" entity=\"ef45\"/>\n    <symbolinfo name=\"biotech\" entity=\"ea3a\"/>\n    <symbolinfo name=\"blanket\" entity=\"e828\"/>\n    <symbolinfo name=\"blender\" entity=\"efe3\"/>\n    <symbolinfo name=\"blind\" entity=\"f8d6\"/>\n    <symbolinfo name=\"blinds\" entity=\"e286\"/>\n    <symbolinfo name=\"blinds_closed\" entity=\"ec1f\"/>\n    <symbolinfo name=\"block\" entity=\"f08c\"/>\n    <symbolinfo name=\"blood_pressure\" entity=\"e097\"/>\n    <symbolinfo name=\"bloodtype\" entity=\"efe4\"/>\n    <symbolinfo name=\"bluetooth\" entity=\"e1a7\"/>\n    <symbolinfo name=\"bluetooth_audio\" entity=\"e60f\"/>\n    <symbolinfo name=\"bluetooth_connected\" entity=\"e1a8\"/>\n    <symbolinfo name=\"bluetooth_disabled\" entity=\"e1a9\"/>\n    <symbolinfo name=\"bluetooth_drive\" entity=\"efe5\"/>\n    <symbolinfo name=\"bluetooth_searching\" entity=\"e60f\"/>\n    <symbolinfo name=\"blur_circular\" entity=\"e3a2\"/>\n    <symbolinfo name=\"blur_linear\" entity=\"e3a3\"/>\n    <symbolinfo name=\"blur_medium\" entity=\"e84c\"/>\n    <symbolinfo name=\"blur_off\" entity=\"e3a4\"/>\n    <symbolinfo name=\"blur_on\" entity=\"e3a5\"/>\n    <symbolinfo name=\"blur_short\" entity=\"e8cf\"/>\n    <symbolinfo name=\"body_fat\" entity=\"e098\"/>\n    <symbolinfo name=\"body_system\" entity=\"e099\"/>\n    <symbolinfo name=\"bolt\" entity=\"ea0b\"/>\n    <symbolinfo name=\"bomb\" entity=\"f568\"/>\n    <symbolinfo name=\"book\" entity=\"e86e\"/>\n    <symbolinfo name=\"book_online\" entity=\"f217\"/>\n    <symbolinfo name=\"bookmark\" entity=\"e8e7\"/>\n    <symbolinfo name=\"bookmark_add\" entity=\"e598\"/>\n    <symbolinfo name=\"bookmark_added\" entity=\"e599\"/>\n    <symbolinfo name=\"bookmark_border\" entity=\"e8e7\"/>\n    <symbolinfo name=\"bookmark_manager\" entity=\"f7b1\"/>\n    <symbolinfo name=\"bookmark_remove\" entity=\"e59a\"/>\n    <symbolinfo name=\"bookmarks\" entity=\"e98b\"/>\n    <symbolinfo name=\"border_all\" entity=\"e228\"/>\n    <symbolinfo name=\"border_bottom\" entity=\"e229\"/>\n    <symbolinfo name=\"border_clear\" entity=\"e22a\"/>\n    <symbolinfo name=\"border_color\" entity=\"e22b\"/>\n    <symbolinfo name=\"border_horizontal\" entity=\"e22c\"/>\n    <symbolinfo name=\"border_inner\" entity=\"e22d\"/>\n    <symbolinfo name=\"border_left\" entity=\"e22e\"/>\n    <symbolinfo name=\"border_outer\" entity=\"e22f\"/>\n    <symbolinfo name=\"border_right\" entity=\"e230\"/>\n    <symbolinfo name=\"border_style\" entity=\"e231\"/>\n    <symbolinfo name=\"border_top\" entity=\"e232\"/>\n    <symbolinfo name=\"border_vertical\" entity=\"e233\"/>\n    <symbolinfo name=\"bottom_app_bar\" entity=\"e730\"/>\n    <symbolinfo name=\"bottom_drawer\" entity=\"e72d\"/>\n    <symbolinfo name=\"bottom_navigation\" entity=\"e98c\"/>\n    <symbolinfo name=\"bottom_panel_close\" entity=\"f72a\"/>\n    <symbolinfo name=\"bottom_panel_open\" entity=\"f729\"/>\n    <symbolinfo name=\"bottom_right_click\" entity=\"f684\"/>\n    <symbolinfo name=\"bottom_sheets\" entity=\"e98d\"/>\n    <symbolinfo name=\"box\" entity=\"f5a4\"/>\n    <symbolinfo name=\"box_add\" entity=\"f5a5\"/>\n    <symbolinfo name=\"box_edit\" entity=\"f5a6\"/>\n    <symbolinfo name=\"boy\" entity=\"eb67\"/>\n    <symbolinfo name=\"brand_awareness\" entity=\"e98e\"/>\n    <symbolinfo name=\"branding_watermark\" entity=\"e06b\"/>\n    <symbolinfo name=\"breakfast_dining\" entity=\"ea54\"/>\n    <symbolinfo name=\"breaking_news\" entity=\"ea08\"/>\n    <symbolinfo name=\"breaking_news_alt_1\" entity=\"f0ba\"/>\n    <symbolinfo name=\"breastfeeding\" entity=\"f856\"/>\n    <symbolinfo name=\"brightness_1\" entity=\"e3fa\"/>\n    <symbolinfo name=\"brightness_2\" entity=\"f036\"/>\n    <symbolinfo name=\"brightness_3\" entity=\"e3a8\"/>\n    <symbolinfo name=\"brightness_4\" entity=\"e3a9\"/>\n    <symbolinfo name=\"brightness_5\" entity=\"e3aa\"/>\n    <symbolinfo name=\"brightness_6\" entity=\"e3ab\"/>\n    <symbolinfo name=\"brightness_7\" entity=\"e3ac\"/>\n    <symbolinfo name=\"brightness_alert\" entity=\"f5cf\"/>\n    <symbolinfo name=\"brightness_auto\" entity=\"e1ab\"/>\n    <symbolinfo name=\"brightness_empty\" entity=\"f7e8\"/>\n    <symbolinfo name=\"brightness_high\" entity=\"e1ac\"/>\n    <symbolinfo name=\"brightness_low\" entity=\"e1ad\"/>\n    <symbolinfo name=\"brightness_medium\" entity=\"e1ae\"/>\n    <symbolinfo name=\"bring_your_own_ip\" entity=\"e016\"/>\n    <symbolinfo name=\"broadcast_on_home\" entity=\"f8f8\"/>\n    <symbolinfo name=\"broadcast_on_personal\" entity=\"f8f9\"/>\n    <symbolinfo name=\"broken_image\" entity=\"e3ad\"/>\n    <symbolinfo name=\"browse\" entity=\"eb13\"/>\n    <symbolinfo name=\"browse_activity\" entity=\"f8a5\"/>\n    <symbolinfo name=\"browse_gallery\" entity=\"ebd1\"/>\n    <symbolinfo name=\"browser_not_supported\" entity=\"ef47\"/>\n    <symbolinfo name=\"browser_updated\" entity=\"e7cf\"/>\n    <symbolinfo name=\"brunch_dining\" entity=\"ea73\"/>\n    <symbolinfo name=\"brush\" entity=\"e3ae\"/>\n    <symbolinfo name=\"bubble\" entity=\"ef83\"/>\n    <symbolinfo name=\"bubble_chart\" entity=\"e6dd\"/>\n    <symbolinfo name=\"bubbles\" entity=\"f64e\"/>\n    <symbolinfo name=\"bug_report\" entity=\"e868\"/>\n    <symbolinfo name=\"build\" entity=\"f8cd\"/>\n    <symbolinfo name=\"build_circle\" entity=\"ef48\"/>\n    <symbolinfo name=\"bungalow\" entity=\"e591\"/>\n    <symbolinfo name=\"burst_mode\" entity=\"e43c\"/>\n    <symbolinfo name=\"bus_alert\" entity=\"e98f\"/>\n    <symbolinfo name=\"business\" entity=\"e7ee\"/>\n    <symbolinfo name=\"business_center\" entity=\"eb3f\"/>\n    <symbolinfo name=\"business_chip\" entity=\"f84c\"/>\n    <symbolinfo name=\"business_messages\" entity=\"ef84\"/>\n    <symbolinfo name=\"buttons_alt\" entity=\"e72f\"/>\n    <symbolinfo name=\"cabin\" entity=\"e589\"/>\n    <symbolinfo name=\"cable\" entity=\"efe6\"/>\n    <symbolinfo name=\"cached\" entity=\"e86a\"/>\n    <symbolinfo name=\"cake\" entity=\"e7e9\"/>\n    <symbolinfo name=\"cake_add\" entity=\"f85b\"/>\n    <symbolinfo name=\"calculate\" entity=\"ea5f\"/>\n    <symbolinfo name=\"calendar_add_on\" entity=\"ef85\"/>\n    <symbolinfo name=\"calendar_apps_script\" entity=\"f0bb\"/>\n    <symbolinfo name=\"calendar_month\" entity=\"ebcc\"/>\n    <symbolinfo name=\"calendar_today\" entity=\"e935\"/>\n    <symbolinfo name=\"calendar_view_day\" entity=\"e936\"/>\n    <symbolinfo name=\"calendar_view_month\" entity=\"efe7\"/>\n    <symbolinfo name=\"calendar_view_week\" entity=\"efe8\"/>\n    <symbolinfo name=\"call\" entity=\"f0d4\"/>\n    <symbolinfo name=\"call_end\" entity=\"f0bc\"/>\n    <symbolinfo name=\"call_end_alt\" entity=\"f0bc\"/>\n    <symbolinfo name=\"call_log\" entity=\"e08e\"/>\n    <symbolinfo name=\"call_made\" entity=\"e0b2\"/>\n    <symbolinfo name=\"call_merge\" entity=\"e0b3\"/>\n    <symbolinfo name=\"call_missed\" entity=\"e0b4\"/>\n    <symbolinfo name=\"call_missed_outgoing\" entity=\"e0e4\"/>\n    <symbolinfo name=\"call_quality\" entity=\"f652\"/>\n    <symbolinfo name=\"call_received\" entity=\"e0b5\"/>\n    <symbolinfo name=\"call_split\" entity=\"e0b6\"/>\n    <symbolinfo name=\"call_to_action\" entity=\"e06c\"/>\n    <symbolinfo name=\"camera\" entity=\"e3af\"/>\n    <symbolinfo name=\"camera_alt\" entity=\"e412\"/>\n    <symbolinfo name=\"camera_enhance\" entity=\"e8fc\"/>\n    <symbolinfo name=\"camera_front\" entity=\"e3b1\"/>\n    <symbolinfo name=\"camera_indoor\" entity=\"efe9\"/>\n    <symbolinfo name=\"camera_outdoor\" entity=\"efea\"/>\n    <symbolinfo name=\"camera_rear\" entity=\"e3b2\"/>\n    <symbolinfo name=\"camera_roll\" entity=\"e3b3\"/>\n    <symbolinfo name=\"camera_video\" entity=\"f7a6\"/>\n    <symbolinfo name=\"cameraswitch\" entity=\"efeb\"/>\n    <symbolinfo name=\"campaign\" entity=\"ef49\"/>\n    <symbolinfo name=\"camping\" entity=\"f8a2\"/>\n    <symbolinfo name=\"cancel\" entity=\"e888\"/>\n    <symbolinfo name=\"cancel_presentation\" entity=\"e0e9\"/>\n    <symbolinfo name=\"cancel_schedule_send\" entity=\"ea39\"/>\n    <symbolinfo name=\"candle\" entity=\"f588\"/>\n    <symbolinfo name=\"candlestick_chart\" entity=\"ead4\"/>\n    <symbolinfo name=\"captive_portal\" entity=\"f728\"/>\n    <symbolinfo name=\"capture\" entity=\"f727\"/>\n    <symbolinfo name=\"car_crash\" entity=\"ebf2\"/>\n    <symbolinfo name=\"car_rental\" entity=\"ea55\"/>\n    <symbolinfo name=\"car_repair\" entity=\"ea56\"/>\n    <symbolinfo name=\"card_giftcard\" entity=\"e8f6\"/>\n    <symbolinfo name=\"card_membership\" entity=\"e8f7\"/>\n    <symbolinfo name=\"card_travel\" entity=\"e8f8\"/>\n    <symbolinfo name=\"cardiology\" entity=\"e09c\"/>\n    <symbolinfo name=\"cards\" entity=\"e991\"/>\n    <symbolinfo name=\"carpenter\" entity=\"f1f8\"/>\n    <symbolinfo name=\"cases\" entity=\"e992\"/>\n    <symbolinfo name=\"casino\" entity=\"eb40\"/>\n    <symbolinfo name=\"cast\" entity=\"e307\"/>\n    <symbolinfo name=\"cast_connected\" entity=\"e308\"/>\n    <symbolinfo name=\"cast_for_education\" entity=\"efec\"/>\n    <symbolinfo name=\"cast_pause\" entity=\"f5f0\"/>\n    <symbolinfo name=\"cast_warning\" entity=\"f5ef\"/>\n    <symbolinfo name=\"castle\" entity=\"eab1\"/>\n    <symbolinfo name=\"category\" entity=\"e574\"/>\n    <symbolinfo name=\"celebration\" entity=\"ea65\"/>\n    <symbolinfo name=\"cell_merge\" entity=\"f82e\"/>\n    <symbolinfo name=\"cell_tower\" entity=\"ebba\"/>\n    <symbolinfo name=\"cell_wifi\" entity=\"e0ec\"/>\n    <symbolinfo name=\"center_focus_strong\" entity=\"e3b4\"/>\n    <symbolinfo name=\"center_focus_weak\" entity=\"e3b5\"/>\n    <symbolinfo name=\"chair\" entity=\"efed\"/>\n    <symbolinfo name=\"chair_alt\" entity=\"efee\"/>\n    <symbolinfo name=\"chalet\" entity=\"e585\"/>\n    <symbolinfo name=\"change_circle\" entity=\"e2e7\"/>\n    <symbolinfo name=\"change_history\" entity=\"e86b\"/>\n    <symbolinfo name=\"charger\" entity=\"e2ae\"/>\n    <symbolinfo name=\"charging_station\" entity=\"f19d\"/>\n    <symbolinfo name=\"chart_data\" entity=\"e473\"/>\n    <symbolinfo name=\"chat\" entity=\"e0c9\"/>\n    <symbolinfo name=\"chat_add_on\" entity=\"f0f3\"/>\n    <symbolinfo name=\"chat_apps_script\" entity=\"f0bd\"/>\n    <symbolinfo name=\"chat_bubble\" entity=\"e0cb\"/>\n    <symbolinfo name=\"chat_bubble_outline\" entity=\"e0cb\"/>\n    <symbolinfo name=\"chat_error\" entity=\"f7ac\"/>\n    <symbolinfo name=\"chat_paste_go\" entity=\"f6bd\"/>\n    <symbolinfo name=\"check\" entity=\"e5ca\"/>\n    <symbolinfo name=\"check_box\" entity=\"e834\"/>\n    <symbolinfo name=\"check_box_outline_blank\" entity=\"e835\"/>\n    <symbolinfo name=\"check_circle\" entity=\"f0be\"/>\n    <symbolinfo name=\"check_circle_filled\" entity=\"f0be\"/>\n    <symbolinfo name=\"check_circle_outline\" entity=\"f0be\"/>\n    <symbolinfo name=\"check_in_out\" entity=\"f6f6\"/>\n    <symbolinfo name=\"check_indeterminate_small\" entity=\"f88a\"/>\n    <symbolinfo name=\"check_small\" entity=\"f88b\"/>\n    <symbolinfo name=\"checklist\" entity=\"e6b1\"/>\n    <symbolinfo name=\"checklist_rtl\" entity=\"e6b3\"/>\n    <symbolinfo name=\"checkroom\" entity=\"f19e\"/>\n    <symbolinfo name=\"cheer\" entity=\"f6a8\"/>\n    <symbolinfo name=\"chess\" entity=\"f5e7\"/>\n    <symbolinfo name=\"chevron_left\" entity=\"e5cb\"/>\n    <symbolinfo name=\"chevron_right\" entity=\"e5cc\"/>\n    <symbolinfo name=\"child_care\" entity=\"eb41\"/>\n    <symbolinfo name=\"child_friendly\" entity=\"eb42\"/>\n    <symbolinfo name=\"chip_extraction\" entity=\"f821\"/>\n    <symbolinfo name=\"chips\" entity=\"e993\"/>\n    <symbolinfo name=\"chrome_reader_mode\" entity=\"e86d\"/>\n    <symbolinfo name=\"chromecast_2\" entity=\"f17b\"/>\n    <symbolinfo name=\"chromecast_device\" entity=\"e83c\"/>\n    <symbolinfo name=\"chronic\" entity=\"ebb2\"/>\n    <symbolinfo name=\"church\" entity=\"eaae\"/>\n    <symbolinfo name=\"cinematic_blur\" entity=\"f853\"/>\n    <symbolinfo name=\"circle\" entity=\"ef4a\"/>\n    <symbolinfo name=\"circle_notifications\" entity=\"e994\"/>\n    <symbolinfo name=\"circles\" entity=\"e7ea\"/>\n    <symbolinfo name=\"circles_ext\" entity=\"e7ec\"/>\n    <symbolinfo name=\"clarify\" entity=\"f0bf\"/>\n    <symbolinfo name=\"class\" entity=\"e86e\"/>\n    <symbolinfo name=\"clean_hands\" entity=\"f21f\"/>\n    <symbolinfo name=\"cleaning_bucket\" entity=\"f8b4\"/>\n    <symbolinfo name=\"cleaning_services\" entity=\"f0ff\"/>\n    <symbolinfo name=\"clear\" entity=\"e5cd\"/>\n    <symbolinfo name=\"clear_all\" entity=\"e0b8\"/>\n    <symbolinfo name=\"clear_day\" entity=\"f157\"/>\n    <symbolinfo name=\"clear_night\" entity=\"f159\"/>\n    <symbolinfo name=\"climate_mini_split\" entity=\"f8b5\"/>\n    <symbolinfo name=\"clinical_notes\" entity=\"e09e\"/>\n    <symbolinfo name=\"clock_loader_10\" entity=\"f726\"/>\n    <symbolinfo name=\"clock_loader_20\" entity=\"f725\"/>\n    <symbolinfo name=\"clock_loader_40\" entity=\"f724\"/>\n    <symbolinfo name=\"clock_loader_60\" entity=\"f723\"/>\n    <symbolinfo name=\"clock_loader_80\" entity=\"f722\"/>\n    <symbolinfo name=\"clock_loader_90\" entity=\"f721\"/>\n    <symbolinfo name=\"close\" entity=\"e5cd\"/>\n    <symbolinfo name=\"close_fullscreen\" entity=\"f1cf\"/>\n    <symbolinfo name=\"closed_caption\" entity=\"e996\"/>\n    <symbolinfo name=\"closed_caption_disabled\" entity=\"f1dc\"/>\n    <symbolinfo name=\"closed_caption_off\" entity=\"e996\"/>\n    <symbolinfo name=\"cloud\" entity=\"f15c\"/>\n    <symbolinfo name=\"cloud_circle\" entity=\"e2be\"/>\n    <symbolinfo name=\"cloud_done\" entity=\"e2bf\"/>\n    <symbolinfo name=\"cloud_download\" entity=\"e2c0\"/>\n    <symbolinfo name=\"cloud_off\" entity=\"e2c1\"/>\n    <symbolinfo name=\"cloud_queue\" entity=\"f15c\"/>\n    <symbolinfo name=\"cloud_sync\" entity=\"eb5a\"/>\n    <symbolinfo name=\"cloud_upload\" entity=\"e2c3\"/>\n    <symbolinfo name=\"cloudy\" entity=\"f15c\"/>\n    <symbolinfo name=\"cloudy_filled\" entity=\"f15c\"/>\n    <symbolinfo name=\"cloudy_snowing\" entity=\"e810\"/>\n    <symbolinfo name=\"co2\" entity=\"e7b0\"/>\n    <symbolinfo name=\"co_present\" entity=\"eaf0\"/>\n    <symbolinfo name=\"code\" entity=\"e86f\"/>\n    <symbolinfo name=\"code_blocks\" entity=\"f84d\"/>\n    <symbolinfo name=\"code_off\" entity=\"e4f3\"/>\n    <symbolinfo name=\"coffee\" entity=\"efef\"/>\n    <symbolinfo name=\"coffee_maker\" entity=\"eff0\"/>\n    <symbolinfo name=\"cognition\" entity=\"e09f\"/>\n    <symbolinfo name=\"collapse_all\" entity=\"e944\"/>\n    <symbolinfo name=\"collections\" entity=\"e3d3\"/>\n    <symbolinfo name=\"collections_bookmark\" entity=\"e431\"/>\n    <symbolinfo name=\"color_lens\" entity=\"e40a\"/>\n    <symbolinfo name=\"colorize\" entity=\"e3b8\"/>\n    <symbolinfo name=\"colors\" entity=\"e997\"/>\n    <symbolinfo name=\"comic_bubble\" entity=\"f5dd\"/>\n    <symbolinfo name=\"comment\" entity=\"e24c\"/>\n    <symbolinfo name=\"comment_bank\" entity=\"ea4e\"/>\n    <symbolinfo name=\"comments_disabled\" entity=\"e7a2\"/>\n    <symbolinfo name=\"commit\" entity=\"eaf5\"/>\n    <symbolinfo name=\"communication\" entity=\"e27c\"/>\n    <symbolinfo name=\"communities\" entity=\"eb16\"/>\n    <symbolinfo name=\"communities_filled\" entity=\"eb16\"/>\n    <symbolinfo name=\"commute\" entity=\"e940\"/>\n    <symbolinfo name=\"compare\" entity=\"e3b9\"/>\n    <symbolinfo name=\"compare_arrows\" entity=\"e915\"/>\n    <symbolinfo name=\"compass_calibration\" entity=\"e57c\"/>\n    <symbolinfo name=\"component_exchange\" entity=\"f1e7\"/>\n    <symbolinfo name=\"compost\" entity=\"e761\"/>\n    <symbolinfo name=\"compress\" entity=\"e94d\"/>\n    <symbolinfo name=\"computer\" entity=\"e31e\"/>\n    <symbolinfo name=\"concierge\" entity=\"f561\"/>\n    <symbolinfo name=\"conditions\" entity=\"e0a0\"/>\n    <symbolinfo name=\"confirmation_number\" entity=\"e638\"/>\n    <symbolinfo name=\"congenital\" entity=\"e0a1\"/>\n    <symbolinfo name=\"connect_without_contact\" entity=\"f223\"/>\n    <symbolinfo name=\"connected_tv\" entity=\"e998\"/>\n    <symbolinfo name=\"connecting_airports\" entity=\"e7c9\"/>\n    <symbolinfo name=\"construction\" entity=\"ea3c\"/>\n    <symbolinfo name=\"contact_emergency\" entity=\"f8d1\"/>\n    <symbolinfo name=\"contact_mail\" entity=\"e0d0\"/>\n    <symbolinfo name=\"contact_page\" entity=\"f22e\"/>\n    <symbolinfo name=\"contact_phone\" entity=\"f0c0\"/>\n    <symbolinfo name=\"contact_phone_filled\" entity=\"f0c0\"/>\n    <symbolinfo name=\"contact_support\" entity=\"e94c\"/>\n    <symbolinfo name=\"contactless\" entity=\"ea71\"/>\n    <symbolinfo name=\"contactless_off\" entity=\"f858\"/>\n    <symbolinfo name=\"contacts\" entity=\"e0ba\"/>\n    <symbolinfo name=\"content_copy\" entity=\"e14d\"/>\n    <symbolinfo name=\"content_cut\" entity=\"e14e\"/>\n    <symbolinfo name=\"content_paste\" entity=\"e14f\"/>\n    <symbolinfo name=\"content_paste_go\" entity=\"ea8e\"/>\n    <symbolinfo name=\"content_paste_off\" entity=\"e4f8\"/>\n    <symbolinfo name=\"content_paste_search\" entity=\"ea9b\"/>\n    <symbolinfo name=\"contract\" entity=\"f5a0\"/>\n    <symbolinfo name=\"contract_delete\" entity=\"f5a2\"/>\n    <symbolinfo name=\"contract_edit\" entity=\"f5a1\"/>\n    <symbolinfo name=\"contrast\" entity=\"eb37\"/>\n    <symbolinfo name=\"contrast_rtl_off\" entity=\"ec72\"/>\n    <symbolinfo name=\"control_camera\" entity=\"e074\"/>\n    <symbolinfo name=\"control_point\" entity=\"e3ba\"/>\n    <symbolinfo name=\"control_point_duplicate\" entity=\"e3bb\"/>\n    <symbolinfo name=\"controller_gen\" entity=\"e83d\"/>\n    <symbolinfo name=\"conversion_path\" entity=\"f0c1\"/>\n    <symbolinfo name=\"conversion_path_off\" entity=\"f7b4\"/>\n    <symbolinfo name=\"conveyor_belt\" entity=\"f867\"/>\n    <symbolinfo name=\"cookie\" entity=\"eaac\"/>\n    <symbolinfo name=\"cookie_off\" entity=\"f79a\"/>\n    <symbolinfo name=\"cooking\" entity=\"e2b6\"/>\n    <symbolinfo name=\"cool_to_dry\" entity=\"e276\"/>\n    <symbolinfo name=\"copy_all\" entity=\"e2ec\"/>\n    <symbolinfo name=\"copyright\" entity=\"e90c\"/>\n    <symbolinfo name=\"coronavirus\" entity=\"f221\"/>\n    <symbolinfo name=\"corporate_fare\" entity=\"f1d0\"/>\n    <symbolinfo name=\"cottage\" entity=\"e587\"/>\n    <symbolinfo name=\"counter_0\" entity=\"f785\"/>\n    <symbolinfo name=\"counter_1\" entity=\"f784\"/>\n    <symbolinfo name=\"counter_2\" entity=\"f783\"/>\n    <symbolinfo name=\"counter_3\" entity=\"f782\"/>\n    <symbolinfo name=\"counter_4\" entity=\"f781\"/>\n    <symbolinfo name=\"counter_5\" entity=\"f780\"/>\n    <symbolinfo name=\"counter_6\" entity=\"f77f\"/>\n    <symbolinfo name=\"counter_7\" entity=\"f77e\"/>\n    <symbolinfo name=\"counter_8\" entity=\"f77d\"/>\n    <symbolinfo name=\"counter_9\" entity=\"f77c\"/>\n    <symbolinfo name=\"countertops\" entity=\"f1f7\"/>\n    <symbolinfo name=\"create\" entity=\"f097\"/>\n    <symbolinfo name=\"create_new_folder\" entity=\"e2cc\"/>\n    <symbolinfo name=\"credit_card\" entity=\"e8a1\"/>\n    <symbolinfo name=\"credit_card_off\" entity=\"e4f4\"/>\n    <symbolinfo name=\"credit_score\" entity=\"eff1\"/>\n    <symbolinfo name=\"crib\" entity=\"e588\"/>\n    <symbolinfo name=\"crisis_alert\" entity=\"ebe9\"/>\n    <symbolinfo name=\"crop\" entity=\"e3be\"/>\n    <symbolinfo name=\"crop_16_9\" entity=\"e3bc\"/>\n    <symbolinfo name=\"crop_3_2\" entity=\"e3bd\"/>\n    <symbolinfo name=\"crop_5_4\" entity=\"e3bf\"/>\n    <symbolinfo name=\"crop_7_5\" entity=\"e3c0\"/>\n    <symbolinfo name=\"crop_9_16\" entity=\"f549\"/>\n    <symbolinfo name=\"crop_din\" entity=\"e3c6\"/>\n    <symbolinfo name=\"crop_free\" entity=\"e3c2\"/>\n    <symbolinfo name=\"crop_landscape\" entity=\"e3c3\"/>\n    <symbolinfo name=\"crop_original\" entity=\"e3f4\"/>\n    <symbolinfo name=\"crop_portrait\" entity=\"e3c5\"/>\n    <symbolinfo name=\"crop_rotate\" entity=\"e437\"/>\n    <symbolinfo name=\"crop_square\" entity=\"e3c6\"/>\n    <symbolinfo name=\"crossword\" entity=\"f5e5\"/>\n    <symbolinfo name=\"crowdsource\" entity=\"eb18\"/>\n    <symbolinfo name=\"cruelty_free\" entity=\"e799\"/>\n    <symbolinfo name=\"css\" entity=\"eb93\"/>\n    <symbolinfo name=\"csv\" entity=\"e6cf\"/>\n    <symbolinfo name=\"currency_bitcoin\" entity=\"ebc5\"/>\n    <symbolinfo name=\"currency_exchange\" entity=\"eb70\"/>\n    <symbolinfo name=\"currency_franc\" entity=\"eafa\"/>\n    <symbolinfo name=\"currency_lira\" entity=\"eaef\"/>\n    <symbolinfo name=\"currency_pound\" entity=\"eaf1\"/>\n    <symbolinfo name=\"currency_ruble\" entity=\"eaec\"/>\n    <symbolinfo name=\"currency_rupee\" entity=\"eaf7\"/>\n    <symbolinfo name=\"currency_yen\" entity=\"eafb\"/>\n    <symbolinfo name=\"currency_yuan\" entity=\"eaf9\"/>\n    <symbolinfo name=\"curtains\" entity=\"ec1e\"/>\n    <symbolinfo name=\"curtains_closed\" entity=\"ec1d\"/>\n    <symbolinfo name=\"custom_typography\" entity=\"e732\"/>\n    <symbolinfo name=\"cut\" entity=\"f08b\"/>\n    <symbolinfo name=\"cycle\" entity=\"f854\"/>\n    <symbolinfo name=\"cyclone\" entity=\"ebd5\"/>\n    <symbolinfo name=\"dangerous\" entity=\"e99a\"/>\n    <symbolinfo name=\"dark_mode\" entity=\"e51c\"/>\n    <symbolinfo name=\"dashboard\" entity=\"e871\"/>\n    <symbolinfo name=\"dashboard_customize\" entity=\"e99b\"/>\n    <symbolinfo name=\"data_alert\" entity=\"f7f6\"/>\n    <symbolinfo name=\"data_array\" entity=\"ead1\"/>\n    <symbolinfo name=\"data_check\" entity=\"f7f2\"/>\n    <symbolinfo name=\"data_exploration\" entity=\"e76f\"/>\n    <symbolinfo name=\"data_info_alert\" entity=\"f7f5\"/>\n    <symbolinfo name=\"data_loss_prevention\" entity=\"e2dc\"/>\n    <symbolinfo name=\"data_object\" entity=\"ead3\"/>\n    <symbolinfo name=\"data_saver_off\" entity=\"eff2\"/>\n    <symbolinfo name=\"data_saver_on\" entity=\"eff3\"/>\n    <symbolinfo name=\"data_table\" entity=\"e99c\"/>\n    <symbolinfo name=\"data_thresholding\" entity=\"eb9f\"/>\n    <symbolinfo name=\"data_usage\" entity=\"eff2\"/>\n    <symbolinfo name=\"database\" entity=\"f20e\"/>\n    <symbolinfo name=\"dataset\" entity=\"f8ee\"/>\n    <symbolinfo name=\"dataset_linked\" entity=\"f8ef\"/>\n    <symbolinfo name=\"date_range\" entity=\"e916\"/>\n    <symbolinfo name=\"deblur\" entity=\"eb77\"/>\n    <symbolinfo name=\"deceased\" entity=\"e0a5\"/>\n    <symbolinfo name=\"decimal_decrease\" entity=\"f82d\"/>\n    <symbolinfo name=\"decimal_increase\" entity=\"f82c\"/>\n    <symbolinfo name=\"deck\" entity=\"ea42\"/>\n    <symbolinfo name=\"dehaze\" entity=\"e3c7\"/>\n    <symbolinfo name=\"delete\" entity=\"e92e\"/>\n    <symbolinfo name=\"delete_forever\" entity=\"e92b\"/>\n    <symbolinfo name=\"delete_outline\" entity=\"e92e\"/>\n    <symbolinfo name=\"delete_sweep\" entity=\"e16c\"/>\n    <symbolinfo name=\"demography\" entity=\"e489\"/>\n    <symbolinfo name=\"density_large\" entity=\"eba9\"/>\n    <symbolinfo name=\"density_medium\" entity=\"eb9e\"/>\n    <symbolinfo name=\"density_small\" entity=\"eba8\"/>\n    <symbolinfo name=\"dentistry\" entity=\"e0a6\"/>\n    <symbolinfo name=\"departure_board\" entity=\"e576\"/>\n    <symbolinfo name=\"deployed_code\" entity=\"f720\"/>\n    <symbolinfo name=\"deployed_code_alert\" entity=\"f5f2\"/>\n    <symbolinfo name=\"deployed_code_history\" entity=\"f5f3\"/>\n    <symbolinfo name=\"deployed_code_update\" entity=\"f5f4\"/>\n    <symbolinfo name=\"dermatology\" entity=\"e0a7\"/>\n    <symbolinfo name=\"description\" entity=\"e873\"/>\n    <symbolinfo name=\"deselect\" entity=\"ebb6\"/>\n    <symbolinfo name=\"design_services\" entity=\"f10a\"/>\n    <symbolinfo name=\"desk\" entity=\"f8f4\"/>\n    <symbolinfo name=\"deskphone\" entity=\"f7fa\"/>\n    <symbolinfo name=\"desktop_access_disabled\" entity=\"e99d\"/>\n    <symbolinfo name=\"desktop_mac\" entity=\"e30b\"/>\n    <symbolinfo name=\"desktop_windows\" entity=\"e30c\"/>\n    <symbolinfo name=\"destruction\" entity=\"f585\"/>\n    <symbolinfo name=\"details\" entity=\"e3c8\"/>\n    <symbolinfo name=\"detection_and_zone\" entity=\"e29f\"/>\n    <symbolinfo name=\"detector\" entity=\"e282\"/>\n    <symbolinfo name=\"detector_alarm\" entity=\"e1f7\"/>\n    <symbolinfo name=\"detector_battery\" entity=\"e204\"/>\n    <symbolinfo name=\"detector_co\" entity=\"e2af\"/>\n    <symbolinfo name=\"detector_offline\" entity=\"e223\"/>\n    <symbolinfo name=\"detector_smoke\" entity=\"e285\"/>\n    <symbolinfo name=\"detector_status\" entity=\"e1e8\"/>\n    <symbolinfo name=\"developer_board\" entity=\"e30d\"/>\n    <symbolinfo name=\"developer_board_off\" entity=\"e4ff\"/>\n    <symbolinfo name=\"developer_guide\" entity=\"e99e\"/>\n    <symbolinfo name=\"developer_mode\" entity=\"e1b0\"/>\n    <symbolinfo name=\"developer_mode_tv\" entity=\"e874\"/>\n    <symbolinfo name=\"device_hub\" entity=\"e335\"/>\n    <symbolinfo name=\"device_reset\" entity=\"e8b3\"/>\n    <symbolinfo name=\"device_thermostat\" entity=\"e1ff\"/>\n    <symbolinfo name=\"device_unknown\" entity=\"e339\"/>\n    <symbolinfo name=\"devices\" entity=\"e326\"/>\n    <symbolinfo name=\"devices_fold\" entity=\"ebde\"/>\n    <symbolinfo name=\"devices_off\" entity=\"f7a5\"/>\n    <symbolinfo name=\"devices_other\" entity=\"e337\"/>\n    <symbolinfo name=\"devices_wearables\" entity=\"f6ab\"/>\n    <symbolinfo name=\"dew_point\" entity=\"f879\"/>\n    <symbolinfo name=\"diagnosis\" entity=\"e0a8\"/>\n    <symbolinfo name=\"dialer_sip\" entity=\"e0bb\"/>\n    <symbolinfo name=\"dialogs\" entity=\"e99f\"/>\n    <symbolinfo name=\"dialpad\" entity=\"e0bc\"/>\n    <symbolinfo name=\"diamond\" entity=\"ead5\"/>\n    <symbolinfo name=\"difference\" entity=\"eb7d\"/>\n    <symbolinfo name=\"digital_out_of_home\" entity=\"f1de\"/>\n    <symbolinfo name=\"dining\" entity=\"eff4\"/>\n    <symbolinfo name=\"dinner_dining\" entity=\"ea57\"/>\n    <symbolinfo name=\"directions\" entity=\"e52e\"/>\n    <symbolinfo name=\"directions_alt\" entity=\"f880\"/>\n    <symbolinfo name=\"directions_alt_off\" entity=\"f881\"/>\n    <symbolinfo name=\"directions_bike\" entity=\"e52f\"/>\n    <symbolinfo name=\"directions_boat\" entity=\"eff5\"/>\n    <symbolinfo name=\"directions_boat_filled\" entity=\"eff5\"/>\n    <symbolinfo name=\"directions_bus\" entity=\"eff6\"/>\n    <symbolinfo name=\"directions_bus_filled\" entity=\"eff6\"/>\n    <symbolinfo name=\"directions_car\" entity=\"eff7\"/>\n    <symbolinfo name=\"directions_car_filled\" entity=\"eff7\"/>\n    <symbolinfo name=\"directions_off\" entity=\"f10f\"/>\n    <symbolinfo name=\"directions_railway\" entity=\"eff8\"/>\n    <symbolinfo name=\"directions_railway_filled\" entity=\"eff8\"/>\n    <symbolinfo name=\"directions_run\" entity=\"e566\"/>\n    <symbolinfo name=\"directions_subway\" entity=\"effa\"/>\n    <symbolinfo name=\"directions_subway_filled\" entity=\"effa\"/>\n    <symbolinfo name=\"directions_transit\" entity=\"effa\"/>\n    <symbolinfo name=\"directions_transit_filled\" entity=\"effa\"/>\n    <symbolinfo name=\"directions_walk\" entity=\"e536\"/>\n    <symbolinfo name=\"directory_sync\" entity=\"e394\"/>\n    <symbolinfo name=\"dirty_lens\" entity=\"ef4b\"/>\n    <symbolinfo name=\"disabled_by_default\" entity=\"f230\"/>\n    <symbolinfo name=\"disabled_visible\" entity=\"e76e\"/>\n    <symbolinfo name=\"disc_full\" entity=\"e610\"/>\n    <symbolinfo name=\"discover_tune\" entity=\"e018\"/>\n    <symbolinfo name=\"dishwasher_gen\" entity=\"e832\"/>\n    <symbolinfo name=\"display_external_input\" entity=\"f7e7\"/>\n    <symbolinfo name=\"display_settings\" entity=\"eb97\"/>\n    <symbolinfo name=\"distance\" entity=\"f6ea\"/>\n    <symbolinfo name=\"diversity_1\" entity=\"f8d7\"/>\n    <symbolinfo name=\"diversity_2\" entity=\"f8d8\"/>\n    <symbolinfo name=\"diversity_3\" entity=\"f8d9\"/>\n    <symbolinfo name=\"diversity_4\" entity=\"f857\"/>\n    <symbolinfo name=\"dns\" entity=\"e875\"/>\n    <symbolinfo name=\"do_disturb\" entity=\"f08c\"/>\n    <symbolinfo name=\"do_disturb_alt\" entity=\"f08d\"/>\n    <symbolinfo name=\"do_disturb_off\" entity=\"f08e\"/>\n    <symbolinfo name=\"do_disturb_on\" entity=\"f08f\"/>\n    <symbolinfo name=\"do_not_disturb\" entity=\"f08d\"/>\n    <symbolinfo name=\"do_not_disturb_alt\" entity=\"f08c\"/>\n    <symbolinfo name=\"do_not_disturb_off\" entity=\"f08e\"/>\n    <symbolinfo name=\"do_not_disturb_on\" entity=\"f08f\"/>\n    <symbolinfo name=\"do_not_disturb_on_total_silence\" entity=\"effb\"/>\n    <symbolinfo name=\"do_not_step\" entity=\"f19f\"/>\n    <symbolinfo name=\"do_not_touch\" entity=\"f1b0\"/>\n    <symbolinfo name=\"dock\" entity=\"e30e\"/>\n    <symbolinfo name=\"dock_to_bottom\" entity=\"f7e6\"/>\n    <symbolinfo name=\"dock_to_left\" entity=\"f7e5\"/>\n    <symbolinfo name=\"dock_to_right\" entity=\"f7e4\"/>\n    <symbolinfo name=\"docs_add_on\" entity=\"f0c2\"/>\n    <symbolinfo name=\"docs_apps_script\" entity=\"f0c3\"/>\n    <symbolinfo name=\"document_scanner\" entity=\"e5fa\"/>\n    <symbolinfo name=\"domain\" entity=\"e7ee\"/>\n    <symbolinfo name=\"domain_add\" entity=\"eb62\"/>\n    <symbolinfo name=\"domain_disabled\" entity=\"e0ef\"/>\n    <symbolinfo name=\"domain_verification\" entity=\"ef4c\"/>\n    <symbolinfo name=\"domain_verification_off\" entity=\"f7b0\"/>\n    <symbolinfo name=\"domino_mask\" entity=\"f5e4\"/>\n    <symbolinfo name=\"done\" entity=\"e876\"/>\n    <symbolinfo name=\"done_all\" entity=\"e877\"/>\n    <symbolinfo name=\"done_outline\" entity=\"e92f\"/>\n    <symbolinfo name=\"donut_large\" entity=\"e917\"/>\n    <symbolinfo name=\"donut_small\" entity=\"e918\"/>\n    <symbolinfo name=\"door_back\" entity=\"effc\"/>\n    <symbolinfo name=\"door_front\" entity=\"effd\"/>\n    <symbolinfo name=\"door_open\" entity=\"e77c\"/>\n    <symbolinfo name=\"door_sensor\" entity=\"e28a\"/>\n    <symbolinfo name=\"door_sliding\" entity=\"effe\"/>\n    <symbolinfo name=\"doorbell\" entity=\"efff\"/>\n    <symbolinfo name=\"doorbell_3p\" entity=\"e1e7\"/>\n    <symbolinfo name=\"doorbell_chime\" entity=\"e1f3\"/>\n    <symbolinfo name=\"double_arrow\" entity=\"ea50\"/>\n    <symbolinfo name=\"downhill_skiing\" entity=\"e509\"/>\n    <symbolinfo name=\"download\" entity=\"f090\"/>\n    <symbolinfo name=\"download_done\" entity=\"f091\"/>\n    <symbolinfo name=\"download_for_offline\" entity=\"f000\"/>\n    <symbolinfo name=\"downloading\" entity=\"f001\"/>\n    <symbolinfo name=\"draft\" entity=\"e66d\"/>\n    <symbolinfo name=\"draft_orders\" entity=\"e7b3\"/>\n    <symbolinfo name=\"drafts\" entity=\"e151\"/>\n    <symbolinfo name=\"drag_click\" entity=\"f71f\"/>\n    <symbolinfo name=\"drag_handle\" entity=\"e25d\"/>\n    <symbolinfo name=\"drag_indicator\" entity=\"e945\"/>\n    <symbolinfo name=\"drag_pan\" entity=\"f71e\"/>\n    <symbolinfo name=\"draw\" entity=\"e746\"/>\n    <symbolinfo name=\"draw_abstract\" entity=\"f7f8\"/>\n    <symbolinfo name=\"draw_collage\" entity=\"f7f7\"/>\n    <symbolinfo name=\"dresser\" entity=\"e210\"/>\n    <symbolinfo name=\"drive_eta\" entity=\"eff7\"/>\n    <symbolinfo name=\"drive_file_move\" entity=\"e9a1\"/>\n    <symbolinfo name=\"drive_file_move_outline\" entity=\"e9a1\"/>\n    <symbolinfo name=\"drive_file_move_rtl\" entity=\"e9a1\"/>\n    <symbolinfo name=\"drive_file_rename_outline\" entity=\"e9a2\"/>\n    <symbolinfo name=\"drive_folder_upload\" entity=\"e9a3\"/>\n    <symbolinfo name=\"drive_fusiontable\" entity=\"e678\"/>\n    <symbolinfo name=\"dropdown\" entity=\"e9a4\"/>\n    <symbolinfo name=\"dry\" entity=\"f1b3\"/>\n    <symbolinfo name=\"dry_cleaning\" entity=\"ea58\"/>\n    <symbolinfo name=\"dual_screen\" entity=\"f6cf\"/>\n    <symbolinfo name=\"duo\" entity=\"e9a5\"/>\n    <symbolinfo name=\"dvr\" entity=\"e1b2\"/>\n    <symbolinfo name=\"dynamic_feed\" entity=\"ea14\"/>\n    <symbolinfo name=\"dynamic_form\" entity=\"f1bf\"/>\n    <symbolinfo name=\"e911_avatar\" entity=\"f11a\"/>\n    <symbolinfo name=\"e911_emergency\" entity=\"f119\"/>\n    <symbolinfo name=\"e_mobiledata\" entity=\"f002\"/>\n    <symbolinfo name=\"e_mobiledata_badge\" entity=\"f7e3\"/>\n    <symbolinfo name=\"earbuds\" entity=\"f003\"/>\n    <symbolinfo name=\"earbuds_battery\" entity=\"f004\"/>\n    <symbolinfo name=\"early_on\" entity=\"e2ba\"/>\n    <symbolinfo name=\"earthquake\" entity=\"f64f\"/>\n    <symbolinfo name=\"east\" entity=\"f1df\"/>\n    <symbolinfo name=\"ecg\" entity=\"f80f\"/>\n    <symbolinfo name=\"ecg_heart\" entity=\"f6e9\"/>\n    <symbolinfo name=\"eco\" entity=\"ea35\"/>\n    <symbolinfo name=\"eda\" entity=\"f6e8\"/>\n    <symbolinfo name=\"edgesensor_high\" entity=\"f005\"/>\n    <symbolinfo name=\"edgesensor_low\" entity=\"f006\"/>\n    <symbolinfo name=\"edit\" entity=\"f097\"/>\n    <symbolinfo name=\"edit_attributes\" entity=\"e578\"/>\n    <symbolinfo name=\"edit_calendar\" entity=\"e742\"/>\n    <symbolinfo name=\"edit_document\" entity=\"f88c\"/>\n    <symbolinfo name=\"edit_location\" entity=\"e568\"/>\n    <symbolinfo name=\"edit_location_alt\" entity=\"e1c5\"/>\n    <symbolinfo name=\"edit_note\" entity=\"e745\"/>\n    <symbolinfo name=\"edit_notifications\" entity=\"e525\"/>\n    <symbolinfo name=\"edit_off\" entity=\"e950\"/>\n    <symbolinfo name=\"edit_road\" entity=\"ef4d\"/>\n    <symbolinfo name=\"edit_square\" entity=\"f88d\"/>\n    <symbolinfo name=\"egg\" entity=\"eacc\"/>\n    <symbolinfo name=\"egg_alt\" entity=\"eac8\"/>\n    <symbolinfo name=\"eject\" entity=\"e8fb\"/>\n    <symbolinfo name=\"elderly\" entity=\"f21a\"/>\n    <symbolinfo name=\"elderly_woman\" entity=\"eb69\"/>\n    <symbolinfo name=\"electric_bike\" entity=\"eb1b\"/>\n    <symbolinfo name=\"electric_bolt\" entity=\"ec1c\"/>\n    <symbolinfo name=\"electric_car\" entity=\"eb1c\"/>\n    <symbolinfo name=\"electric_meter\" entity=\"ec1b\"/>\n    <symbolinfo name=\"electric_moped\" entity=\"eb1d\"/>\n    <symbolinfo name=\"electric_rickshaw\" entity=\"eb1e\"/>\n    <symbolinfo name=\"electric_scooter\" entity=\"eb1f\"/>\n    <symbolinfo name=\"electrical_services\" entity=\"f102\"/>\n    <symbolinfo name=\"elevation\" entity=\"f6e7\"/>\n    <symbolinfo name=\"elevator\" entity=\"f1a0\"/>\n    <symbolinfo name=\"email\" entity=\"e159\"/>\n    <symbolinfo name=\"emergency\" entity=\"e1eb\"/>\n    <symbolinfo name=\"emergency_heat\" entity=\"f15d\"/>\n    <symbolinfo name=\"emergency_home\" entity=\"e82a\"/>\n    <symbolinfo name=\"emergency_recording\" entity=\"ebf4\"/>\n    <symbolinfo name=\"emergency_share\" entity=\"ebf6\"/>\n    <symbolinfo name=\"emergency_share_off\" entity=\"f59e\"/>\n    <symbolinfo name=\"emoji_emotions\" entity=\"ea22\"/>\n    <symbolinfo name=\"emoji_events\" entity=\"ea23\"/>\n    <symbolinfo name=\"emoji_flags\" entity=\"f0c6\"/>\n    <symbolinfo name=\"emoji_food_beverage\" entity=\"ea1b\"/>\n    <symbolinfo name=\"emoji_nature\" entity=\"ea1c\"/>\n    <symbolinfo name=\"emoji_objects\" entity=\"ea24\"/>\n    <symbolinfo name=\"emoji_people\" entity=\"ea1d\"/>\n    <symbolinfo name=\"emoji_symbols\" entity=\"ea1e\"/>\n    <symbolinfo name=\"emoji_transportation\" entity=\"ea1f\"/>\n    <symbolinfo name=\"emoticon\" entity=\"e5f3\"/>\n    <symbolinfo name=\"empty_dashboard\" entity=\"f844\"/>\n    <symbolinfo name=\"enable\" entity=\"f188\"/>\n    <symbolinfo name=\"encrypted\" entity=\"e593\"/>\n    <symbolinfo name=\"endocrinology\" entity=\"e0a9\"/>\n    <symbolinfo name=\"energy_program_saving\" entity=\"f15f\"/>\n    <symbolinfo name=\"energy_program_time_used\" entity=\"f161\"/>\n    <symbolinfo name=\"energy_savings_leaf\" entity=\"ec1a\"/>\n    <symbolinfo name=\"engineering\" entity=\"ea3d\"/>\n    <symbolinfo name=\"enhanced_encryption\" entity=\"e63f\"/>\n    <symbolinfo name=\"ent\" entity=\"e0aa\"/>\n    <symbolinfo name=\"equal\" entity=\"f77b\"/>\n    <symbolinfo name=\"equalizer\" entity=\"e01d\"/>\n    <symbolinfo name=\"error\" entity=\"f8b6\"/>\n    <symbolinfo name=\"error_circle_rounded\" entity=\"f8b6\"/>\n    <symbolinfo name=\"error_med\" entity=\"e49b\"/>\n    <symbolinfo name=\"error_outline\" entity=\"f8b6\"/>\n    <symbolinfo name=\"escalator\" entity=\"f1a1\"/>\n    <symbolinfo name=\"escalator_warning\" entity=\"f1ac\"/>\n    <symbolinfo name=\"euro\" entity=\"ea15\"/>\n    <symbolinfo name=\"euro_symbol\" entity=\"e926\"/>\n    <symbolinfo name=\"ev_charger\" entity=\"e56d\"/>\n    <symbolinfo name=\"ev_mobiledata_badge\" entity=\"f7e2\"/>\n    <symbolinfo name=\"ev_shadow\" entity=\"ef8f\"/>\n    <symbolinfo name=\"ev_shadow_add\" entity=\"f580\"/>\n    <symbolinfo name=\"ev_shadow_minus\" entity=\"f57f\"/>\n    <symbolinfo name=\"ev_station\" entity=\"e56d\"/>\n    <symbolinfo name=\"event\" entity=\"e878\"/>\n    <symbolinfo name=\"event_available\" entity=\"e614\"/>\n    <symbolinfo name=\"event_busy\" entity=\"e615\"/>\n    <symbolinfo name=\"event_list\" entity=\"f683\"/>\n    <symbolinfo name=\"event_note\" entity=\"e616\"/>\n    <symbolinfo name=\"event_repeat\" entity=\"eb7b\"/>\n    <symbolinfo name=\"event_seat\" entity=\"e903\"/>\n    <symbolinfo name=\"event_upcoming\" entity=\"f238\"/>\n    <symbolinfo name=\"exclamation\" entity=\"f22f\"/>\n    <symbolinfo name=\"exercise\" entity=\"f6e6\"/>\n    <symbolinfo name=\"exit_to_app\" entity=\"e879\"/>\n    <symbolinfo name=\"expand\" entity=\"e94f\"/>\n    <symbolinfo name=\"expand_all\" entity=\"e946\"/>\n    <symbolinfo name=\"expand_circle_down\" entity=\"e7cd\"/>\n    <symbolinfo name=\"expand_circle_right\" entity=\"f591\"/>\n    <symbolinfo name=\"expand_circle_up\" entity=\"f5d2\"/>\n    <symbolinfo name=\"expand_content\" entity=\"f830\"/>\n    <symbolinfo name=\"expand_less\" entity=\"e5ce\"/>\n    <symbolinfo name=\"expand_more\" entity=\"e5cf\"/>\n    <symbolinfo name=\"explicit\" entity=\"e01e\"/>\n    <symbolinfo name=\"explore\" entity=\"e87a\"/>\n    <symbolinfo name=\"explore_off\" entity=\"e9a8\"/>\n    <symbolinfo name=\"explosion\" entity=\"f685\"/>\n    <symbolinfo name=\"export_notes\" entity=\"e0ac\"/>\n    <symbolinfo name=\"exposure\" entity=\"e3f6\"/>\n    <symbolinfo name=\"exposure_neg_1\" entity=\"e3cb\"/>\n    <symbolinfo name=\"exposure_neg_2\" entity=\"e3cc\"/>\n    <symbolinfo name=\"exposure_plus_1\" entity=\"e800\"/>\n    <symbolinfo name=\"exposure_plus_2\" entity=\"e3ce\"/>\n    <symbolinfo name=\"exposure_zero\" entity=\"e3cf\"/>\n    <symbolinfo name=\"extension\" entity=\"e87b\"/>\n    <symbolinfo name=\"extension_off\" entity=\"e4f5\"/>\n    <symbolinfo name=\"eyeglasses\" entity=\"f6ee\"/>\n    <symbolinfo name=\"face\" entity=\"f008\"/>\n    <symbolinfo name=\"face_2\" entity=\"f8da\"/>\n    <symbolinfo name=\"face_3\" entity=\"f8db\"/>\n    <symbolinfo name=\"face_4\" entity=\"f8dc\"/>\n    <symbolinfo name=\"face_5\" entity=\"f8dd\"/>\n    <symbolinfo name=\"face_6\" entity=\"f8de\"/>\n    <symbolinfo name=\"face_retouching_natural\" entity=\"ef4e\"/>\n    <symbolinfo name=\"face_retouching_off\" entity=\"f007\"/>\n    <symbolinfo name=\"face_unlock\" entity=\"f008\"/>\n    <symbolinfo name=\"fact_check\" entity=\"f0c5\"/>\n    <symbolinfo name=\"factory\" entity=\"ebbc\"/>\n    <symbolinfo name=\"falling\" entity=\"f60d\"/>\n    <symbolinfo name=\"familiar_face_and_zone\" entity=\"e21c\"/>\n    <symbolinfo name=\"family_history\" entity=\"e0ad\"/>\n    <symbolinfo name=\"family_link\" entity=\"eb19\"/>\n    <symbolinfo name=\"family_restroom\" entity=\"f1a2\"/>\n    <symbolinfo name=\"farsight_digital\" entity=\"f559\"/>\n    <symbolinfo name=\"fast_forward\" entity=\"e01f\"/>\n    <symbolinfo name=\"fast_rewind\" entity=\"e020\"/>\n    <symbolinfo name=\"fastfood\" entity=\"e57a\"/>\n    <symbolinfo name=\"faucet\" entity=\"e278\"/>\n    <symbolinfo name=\"favorite\" entity=\"e87e\"/>\n    <symbolinfo name=\"favorite_border\" entity=\"e87e\"/>\n    <symbolinfo name=\"fax\" entity=\"ead8\"/>\n    <symbolinfo name=\"feature_search\" entity=\"e9a9\"/>\n    <symbolinfo name=\"featured_play_list\" entity=\"e06d\"/>\n    <symbolinfo name=\"featured_video\" entity=\"e06e\"/>\n    <symbolinfo name=\"feed\" entity=\"f009\"/>\n    <symbolinfo name=\"feedback\" entity=\"e87f\"/>\n    <symbolinfo name=\"female\" entity=\"e590\"/>\n    <symbolinfo name=\"femur\" entity=\"f891\"/>\n    <symbolinfo name=\"femur_alt\" entity=\"f892\"/>\n    <symbolinfo name=\"fence\" entity=\"f1f6\"/>\n    <symbolinfo name=\"fertile\" entity=\"f6e5\"/>\n    <symbolinfo name=\"festival\" entity=\"ea68\"/>\n    <symbolinfo name=\"fiber_dvr\" entity=\"e05d\"/>\n    <symbolinfo name=\"fiber_manual_record\" entity=\"e061\"/>\n    <symbolinfo name=\"fiber_new\" entity=\"e05e\"/>\n    <symbolinfo name=\"fiber_pin\" entity=\"e06a\"/>\n    <symbolinfo name=\"fiber_smart_record\" entity=\"e062\"/>\n    <symbolinfo name=\"file_copy\" entity=\"e173\"/>\n    <symbolinfo name=\"file_download\" entity=\"f090\"/>\n    <symbolinfo name=\"file_download_done\" entity=\"f091\"/>\n    <symbolinfo name=\"file_download_off\" entity=\"e4fe\"/>\n    <symbolinfo name=\"file_open\" entity=\"eaf3\"/>\n    <symbolinfo name=\"file_present\" entity=\"ea0e\"/>\n    <symbolinfo name=\"file_upload\" entity=\"f09b\"/>\n    <symbolinfo name=\"file_upload_off\" entity=\"f886\"/>\n    <symbolinfo name=\"filter\" entity=\"e3d3\"/>\n    <symbolinfo name=\"filter_1\" entity=\"e3d0\"/>\n    <symbolinfo name=\"filter_2\" entity=\"e3d1\"/>\n    <symbolinfo name=\"filter_3\" entity=\"e3d2\"/>\n    <symbolinfo name=\"filter_4\" entity=\"e3d4\"/>\n    <symbolinfo name=\"filter_5\" entity=\"e3d5\"/>\n    <symbolinfo name=\"filter_6\" entity=\"e3d6\"/>\n    <symbolinfo name=\"filter_7\" entity=\"e3d7\"/>\n    <symbolinfo name=\"filter_8\" entity=\"e3d8\"/>\n    <symbolinfo name=\"filter_9\" entity=\"e3d9\"/>\n    <symbolinfo name=\"filter_9_plus\" entity=\"e3da\"/>\n    <symbolinfo name=\"filter_alt\" entity=\"ef4f\"/>\n    <symbolinfo name=\"filter_alt_off\" entity=\"eb32\"/>\n    <symbolinfo name=\"filter_b_and_w\" entity=\"e3db\"/>\n    <symbolinfo name=\"filter_center_focus\" entity=\"e3dc\"/>\n    <symbolinfo name=\"filter_drama\" entity=\"e3dd\"/>\n    <symbolinfo name=\"filter_frames\" entity=\"e3de\"/>\n    <symbolinfo name=\"filter_hdr\" entity=\"e3df\"/>\n    <symbolinfo name=\"filter_list\" entity=\"e152\"/>\n    <symbolinfo name=\"filter_list_alt\" entity=\"e94e\"/>\n    <symbolinfo name=\"filter_list_off\" entity=\"eb57\"/>\n    <symbolinfo name=\"filter_none\" entity=\"e3e0\"/>\n    <symbolinfo name=\"filter_tilt_shift\" entity=\"e3e2\"/>\n    <symbolinfo name=\"filter_vintage\" entity=\"e3e3\"/>\n    <symbolinfo name=\"finance\" entity=\"e6bf\"/>\n    <symbolinfo name=\"finance_chip\" entity=\"f84e\"/>\n    <symbolinfo name=\"find_in_page\" entity=\"e880\"/>\n    <symbolinfo name=\"find_replace\" entity=\"e881\"/>\n    <symbolinfo name=\"fingerprint\" entity=\"e90d\"/>\n    <symbolinfo name=\"fire_extinguisher\" entity=\"f1d8\"/>\n    <symbolinfo name=\"fire_hydrant\" entity=\"f1a3\"/>\n    <symbolinfo name=\"fire_truck\" entity=\"f8f2\"/>\n    <symbolinfo name=\"fireplace\" entity=\"ea43\"/>\n    <symbolinfo name=\"first_page\" entity=\"e5dc\"/>\n    <symbolinfo name=\"fit_page\" entity=\"f77a\"/>\n    <symbolinfo name=\"fit_screen\" entity=\"ea10\"/>\n    <symbolinfo name=\"fit_width\" entity=\"f779\"/>\n    <symbolinfo name=\"fitness_center\" entity=\"eb43\"/>\n    <symbolinfo name=\"flag\" entity=\"f0c6\"/>\n    <symbolinfo name=\"flag_circle\" entity=\"eaf8\"/>\n    <symbolinfo name=\"flag_filled\" entity=\"f0c6\"/>\n    <symbolinfo name=\"flaky\" entity=\"ef50\"/>\n    <symbolinfo name=\"flare\" entity=\"e3e4\"/>\n    <symbolinfo name=\"flash_auto\" entity=\"e3e5\"/>\n    <symbolinfo name=\"flash_off\" entity=\"e3e6\"/>\n    <symbolinfo name=\"flash_on\" entity=\"e3e7\"/>\n    <symbolinfo name=\"flashlight_off\" entity=\"f00a\"/>\n    <symbolinfo name=\"flashlight_on\" entity=\"f00b\"/>\n    <symbolinfo name=\"flatware\" entity=\"f00c\"/>\n    <symbolinfo name=\"flex_direction\" entity=\"f778\"/>\n    <symbolinfo name=\"flex_no_wrap\" entity=\"f777\"/>\n    <symbolinfo name=\"flex_wrap\" entity=\"f776\"/>\n    <symbolinfo name=\"flight\" entity=\"e539\"/>\n    <symbolinfo name=\"flight_class\" entity=\"e7cb\"/>\n    <symbolinfo name=\"flight_land\" entity=\"e904\"/>\n    <symbolinfo name=\"flight_takeoff\" entity=\"e905\"/>\n    <symbolinfo name=\"flightsmode\" entity=\"ef93\"/>\n    <symbolinfo name=\"flip\" entity=\"e3e8\"/>\n    <symbolinfo name=\"flip_camera_android\" entity=\"ea37\"/>\n    <symbolinfo name=\"flip_camera_ios\" entity=\"ea38\"/>\n    <symbolinfo name=\"flip_to_back\" entity=\"e882\"/>\n    <symbolinfo name=\"flip_to_front\" entity=\"e883\"/>\n    <symbolinfo name=\"flood\" entity=\"ebe6\"/>\n    <symbolinfo name=\"floor\" entity=\"f6e4\"/>\n    <symbolinfo name=\"floor_lamp\" entity=\"e21e\"/>\n    <symbolinfo name=\"flourescent\" entity=\"f07d\"/>\n    <symbolinfo name=\"flowsheet\" entity=\"e0ae\"/>\n    <symbolinfo name=\"fluid\" entity=\"e483\"/>\n    <symbolinfo name=\"fluid_balance\" entity=\"f80d\"/>\n    <symbolinfo name=\"fluid_med\" entity=\"f80c\"/>\n    <symbolinfo name=\"fluorescent\" entity=\"f07d\"/>\n    <symbolinfo name=\"flutter\" entity=\"f1dd\"/>\n    <symbolinfo name=\"flutter_dash\" entity=\"e00b\"/>\n    <symbolinfo name=\"fmd_bad\" entity=\"f00e\"/>\n    <symbolinfo name=\"fmd_good\" entity=\"f1db\"/>\n    <symbolinfo name=\"foggy\" entity=\"e818\"/>\n    <symbolinfo name=\"folded_hands\" entity=\"f5ed\"/>\n    <symbolinfo name=\"folder\" entity=\"e2c7\"/>\n    <symbolinfo name=\"folder_copy\" entity=\"ebbd\"/>\n    <symbolinfo name=\"folder_data\" entity=\"f586\"/>\n    <symbolinfo name=\"folder_delete\" entity=\"eb34\"/>\n    <symbolinfo name=\"folder_managed\" entity=\"f775\"/>\n    <symbolinfo name=\"folder_off\" entity=\"eb83\"/>\n    <symbolinfo name=\"folder_open\" entity=\"e2c8\"/>\n    <symbolinfo name=\"folder_shared\" entity=\"e2c9\"/>\n    <symbolinfo name=\"folder_special\" entity=\"e617\"/>\n    <symbolinfo name=\"folder_supervised\" entity=\"f774\"/>\n    <symbolinfo name=\"folder_zip\" entity=\"eb2c\"/>\n    <symbolinfo name=\"follow_the_signs\" entity=\"f222\"/>\n    <symbolinfo name=\"font_download\" entity=\"e167\"/>\n    <symbolinfo name=\"font_download_off\" entity=\"e4f9\"/>\n    <symbolinfo name=\"food_bank\" entity=\"f1f2\"/>\n    <symbolinfo name=\"foot_bones\" entity=\"f893\"/>\n    <symbolinfo name=\"footprint\" entity=\"f87d\"/>\n    <symbolinfo name=\"forest\" entity=\"ea99\"/>\n    <symbolinfo name=\"fork_left\" entity=\"eba0\"/>\n    <symbolinfo name=\"fork_right\" entity=\"ebac\"/>\n    <symbolinfo name=\"forklift\" entity=\"f868\"/>\n    <symbolinfo name=\"format_align_center\" entity=\"e234\"/>\n    <symbolinfo name=\"format_align_justify\" entity=\"e235\"/>\n    <symbolinfo name=\"format_align_left\" entity=\"e236\"/>\n    <symbolinfo name=\"format_align_right\" entity=\"e237\"/>\n    <symbolinfo name=\"format_bold\" entity=\"e238\"/>\n    <symbolinfo name=\"format_clear\" entity=\"e239\"/>\n    <symbolinfo name=\"format_color_fill\" entity=\"e23a\"/>\n    <symbolinfo name=\"format_color_reset\" entity=\"e23b\"/>\n    <symbolinfo name=\"format_color_text\" entity=\"e23c\"/>\n    <symbolinfo name=\"format_h1\" entity=\"f85d\"/>\n    <symbolinfo name=\"format_h2\" entity=\"f85e\"/>\n    <symbolinfo name=\"format_h3\" entity=\"f85f\"/>\n    <symbolinfo name=\"format_h4\" entity=\"f860\"/>\n    <symbolinfo name=\"format_h5\" entity=\"f861\"/>\n    <symbolinfo name=\"format_h6\" entity=\"f862\"/>\n    <symbolinfo name=\"format_image_left\" entity=\"f863\"/>\n    <symbolinfo name=\"format_image_right\" entity=\"f864\"/>\n    <symbolinfo name=\"format_indent_decrease\" entity=\"e23d\"/>\n    <symbolinfo name=\"format_indent_increase\" entity=\"e23e\"/>\n    <symbolinfo name=\"format_ink_highlighter\" entity=\"f82b\"/>\n    <symbolinfo name=\"format_italic\" entity=\"e23f\"/>\n    <symbolinfo name=\"format_letter_spacing\" entity=\"f773\"/>\n    <symbolinfo name=\"format_letter_spacing_2\" entity=\"f618\"/>\n    <symbolinfo name=\"format_letter_spacing_standard\" entity=\"f617\"/>\n    <symbolinfo name=\"format_letter_spacing_wide\" entity=\"f616\"/>\n    <symbolinfo name=\"format_letter_spacing_wider\" entity=\"f615\"/>\n    <symbolinfo name=\"format_line_spacing\" entity=\"e240\"/>\n    <symbolinfo name=\"format_list_bulleted\" entity=\"e241\"/>\n    <symbolinfo name=\"format_list_bulleted_add\" entity=\"f849\"/>\n    <symbolinfo name=\"format_list_numbered\" entity=\"e242\"/>\n    <symbolinfo name=\"format_list_numbered_rtl\" entity=\"e267\"/>\n    <symbolinfo name=\"format_overline\" entity=\"eb65\"/>\n    <symbolinfo name=\"format_paint\" entity=\"e243\"/>\n    <symbolinfo name=\"format_paragraph\" entity=\"f865\"/>\n    <symbolinfo name=\"format_quote\" entity=\"e244\"/>\n    <symbolinfo name=\"format_shapes\" entity=\"e25e\"/>\n    <symbolinfo name=\"format_size\" entity=\"e245\"/>\n    <symbolinfo name=\"format_strikethrough\" entity=\"e246\"/>\n    <symbolinfo name=\"format_text_clip\" entity=\"f82a\"/>\n    <symbolinfo name=\"format_text_overflow\" entity=\"f829\"/>\n    <symbolinfo name=\"format_text_wrap\" entity=\"f828\"/>\n    <symbolinfo name=\"format_textdirection_l_to_r\" entity=\"e247\"/>\n    <symbolinfo name=\"format_textdirection_r_to_l\" entity=\"e248\"/>\n    <symbolinfo name=\"format_underlined\" entity=\"e249\"/>\n    <symbolinfo name=\"format_underlined_squiggle\" entity=\"f885\"/>\n    <symbolinfo name=\"forms_add_on\" entity=\"f0c7\"/>\n    <symbolinfo name=\"forms_apps_script\" entity=\"f0c8\"/>\n    <symbolinfo name=\"fort\" entity=\"eaad\"/>\n    <symbolinfo name=\"forum\" entity=\"e8af\"/>\n    <symbolinfo name=\"forward\" entity=\"f57a\"/>\n    <symbolinfo name=\"forward_10\" entity=\"e056\"/>\n    <symbolinfo name=\"forward_30\" entity=\"e057\"/>\n    <symbolinfo name=\"forward_5\" entity=\"e058\"/>\n    <symbolinfo name=\"forward_circle\" entity=\"f6f5\"/>\n    <symbolinfo name=\"forward_media\" entity=\"f6f4\"/>\n    <symbolinfo name=\"forward_to_inbox\" entity=\"f187\"/>\n    <symbolinfo name=\"foundation\" entity=\"f200\"/>\n    <symbolinfo name=\"frame_inspect\" entity=\"f772\"/>\n    <symbolinfo name=\"frame_person\" entity=\"f8a6\"/>\n    <symbolinfo name=\"frame_person_off\" entity=\"f7d1\"/>\n    <symbolinfo name=\"frame_reload\" entity=\"f771\"/>\n    <symbolinfo name=\"frame_source\" entity=\"f770\"/>\n    <symbolinfo name=\"free_breakfast\" entity=\"eb44\"/>\n    <symbolinfo name=\"free_cancellation\" entity=\"e748\"/>\n    <symbolinfo name=\"front_hand\" entity=\"e769\"/>\n    <symbolinfo name=\"front_loader\" entity=\"f869\"/>\n    <symbolinfo name=\"full_coverage\" entity=\"eb12\"/>\n    <symbolinfo name=\"full_hd\" entity=\"f58b\"/>\n    <symbolinfo name=\"full_stacked_bar_chart\" entity=\"f212\"/>\n    <symbolinfo name=\"fullscreen\" entity=\"e5d0\"/>\n    <symbolinfo name=\"fullscreen_exit\" entity=\"e5d1\"/>\n    <symbolinfo name=\"function\" entity=\"f866\"/>\n    <symbolinfo name=\"functions\" entity=\"e24a\"/>\n    <symbolinfo name=\"g_mobiledata\" entity=\"f010\"/>\n    <symbolinfo name=\"g_mobiledata_badge\" entity=\"f7e1\"/>\n    <symbolinfo name=\"g_translate\" entity=\"e927\"/>\n    <symbolinfo name=\"gallery_thumbnail\" entity=\"f86f\"/>\n    <symbolinfo name=\"gamepad\" entity=\"e30f\"/>\n    <symbolinfo name=\"games\" entity=\"e30f\"/>\n    <symbolinfo name=\"garage\" entity=\"f011\"/>\n    <symbolinfo name=\"garage_home\" entity=\"e82d\"/>\n    <symbolinfo name=\"garden_cart\" entity=\"f8a9\"/>\n    <symbolinfo name=\"gas_meter\" entity=\"ec19\"/>\n    <symbolinfo name=\"gastroenterology\" entity=\"e0f1\"/>\n    <symbolinfo name=\"gate\" entity=\"e277\"/>\n    <symbolinfo name=\"gavel\" entity=\"e90e\"/>\n    <symbolinfo name=\"generating_tokens\" entity=\"e749\"/>\n    <symbolinfo name=\"genetics\" entity=\"e0f3\"/>\n    <symbolinfo name=\"genres\" entity=\"e6ee\"/>\n    <symbolinfo name=\"gesture\" entity=\"e155\"/>\n    <symbolinfo name=\"gesture_select\" entity=\"f657\"/>\n    <symbolinfo name=\"get_app\" entity=\"f090\"/>\n    <symbolinfo name=\"gif\" entity=\"e908\"/>\n    <symbolinfo name=\"gif_box\" entity=\"e7a3\"/>\n    <symbolinfo name=\"girl\" entity=\"eb68\"/>\n    <symbolinfo name=\"gite\" entity=\"e58b\"/>\n    <symbolinfo name=\"glass_cup\" entity=\"f6e3\"/>\n    <symbolinfo name=\"globe\" entity=\"e64c\"/>\n    <symbolinfo name=\"globe_asia\" entity=\"f799\"/>\n    <symbolinfo name=\"globe_uk\" entity=\"f798\"/>\n    <symbolinfo name=\"glucose\" entity=\"e4a0\"/>\n    <symbolinfo name=\"glyphs\" entity=\"f8a3\"/>\n    <symbolinfo name=\"go_to_line\" entity=\"f71d\"/>\n    <symbolinfo name=\"golf_course\" entity=\"eb45\"/>\n    <symbolinfo name=\"google_plus_reshare\" entity=\"f57a\"/>\n    <symbolinfo name=\"google_tv_remote\" entity=\"f5db\"/>\n    <symbolinfo name=\"google_wifi\" entity=\"f579\"/>\n    <symbolinfo name=\"gpp_bad\" entity=\"f012\"/>\n    <symbolinfo name=\"gpp_good\" entity=\"f013\"/>\n    <symbolinfo name=\"gpp_maybe\" entity=\"f014\"/>\n    <symbolinfo name=\"gps_fixed\" entity=\"e55c\"/>\n    <symbolinfo name=\"gps_not_fixed\" entity=\"e1b7\"/>\n    <symbolinfo name=\"gps_off\" entity=\"e1b6\"/>\n    <symbolinfo name=\"grade\" entity=\"e885\"/>\n    <symbolinfo name=\"gradient\" entity=\"e3e9\"/>\n    <symbolinfo name=\"grading\" entity=\"ea4f\"/>\n    <symbolinfo name=\"grain\" entity=\"e3ea\"/>\n    <symbolinfo name=\"graphic_eq\" entity=\"e1b8\"/>\n    <symbolinfo name=\"grass\" entity=\"f205\"/>\n    <symbolinfo name=\"grid_3x3\" entity=\"f015\"/>\n    <symbolinfo name=\"grid_3x3_off\" entity=\"f67c\"/>\n    <symbolinfo name=\"grid_4x4\" entity=\"f016\"/>\n    <symbolinfo name=\"grid_goldenratio\" entity=\"f017\"/>\n    <symbolinfo name=\"grid_guides\" entity=\"f76f\"/>\n    <symbolinfo name=\"grid_off\" entity=\"e3eb\"/>\n    <symbolinfo name=\"grid_on\" entity=\"e3ec\"/>\n    <symbolinfo name=\"grid_view\" entity=\"e9b0\"/>\n    <symbolinfo name=\"group\" entity=\"ea21\"/>\n    <symbolinfo name=\"group_add\" entity=\"e7f0\"/>\n    <symbolinfo name=\"group_auto\" entity=\"f551\"/>\n    <symbolinfo name=\"group_off\" entity=\"e747\"/>\n    <symbolinfo name=\"group_remove\" entity=\"e7ad\"/>\n    <symbolinfo name=\"group_work\" entity=\"e886\"/>\n    <symbolinfo name=\"grouped_bar_chart\" entity=\"f211\"/>\n    <symbolinfo name=\"groups\" entity=\"f233\"/>\n    <symbolinfo name=\"groups_2\" entity=\"f8df\"/>\n    <symbolinfo name=\"groups_3\" entity=\"f8e0\"/>\n    <symbolinfo name=\"gynecology\" entity=\"e0f4\"/>\n    <symbolinfo name=\"h_mobiledata\" entity=\"f018\"/>\n    <symbolinfo name=\"h_mobiledata_badge\" entity=\"f7e0\"/>\n    <symbolinfo name=\"h_plus_mobiledata\" entity=\"f019\"/>\n    <symbolinfo name=\"h_plus_mobiledata_badge\" entity=\"f7df\"/>\n    <symbolinfo name=\"hail\" entity=\"e9b1\"/>\n    <symbolinfo name=\"hallway\" entity=\"e6f8\"/>\n    <symbolinfo name=\"hand_bones\" entity=\"f894\"/>\n    <symbolinfo name=\"hand_gesture\" entity=\"ef9c\"/>\n    <symbolinfo name=\"handshake\" entity=\"ebcb\"/>\n    <symbolinfo name=\"handyman\" entity=\"f10b\"/>\n    <symbolinfo name=\"hangout_video\" entity=\"e0c1\"/>\n    <symbolinfo name=\"hangout_video_off\" entity=\"e0c2\"/>\n    <symbolinfo name=\"hard_drive\" entity=\"f80e\"/>\n    <symbolinfo name=\"hard_drive_2\" entity=\"f7a4\"/>\n    <symbolinfo name=\"hardware\" entity=\"ea59\"/>\n    <symbolinfo name=\"hd\" entity=\"e052\"/>\n    <symbolinfo name=\"hdr_auto\" entity=\"f01a\"/>\n    <symbolinfo name=\"hdr_auto_select\" entity=\"f01b\"/>\n    <symbolinfo name=\"hdr_enhanced_select\" entity=\"ef51\"/>\n    <symbolinfo name=\"hdr_off\" entity=\"e3ed\"/>\n    <symbolinfo name=\"hdr_off_select\" entity=\"f01c\"/>\n    <symbolinfo name=\"hdr_on\" entity=\"e3ee\"/>\n    <symbolinfo name=\"hdr_on_select\" entity=\"f01d\"/>\n    <symbolinfo name=\"hdr_plus\" entity=\"f01e\"/>\n    <symbolinfo name=\"hdr_strong\" entity=\"e3f1\"/>\n    <symbolinfo name=\"hdr_weak\" entity=\"e3f2\"/>\n    <symbolinfo name=\"headphones\" entity=\"f01f\"/>\n    <symbolinfo name=\"headphones_battery\" entity=\"f020\"/>\n    <symbolinfo name=\"headset\" entity=\"f01f\"/>\n    <symbolinfo name=\"headset_mic\" entity=\"e311\"/>\n    <symbolinfo name=\"headset_off\" entity=\"e33a\"/>\n    <symbolinfo name=\"healing\" entity=\"e3f3\"/>\n    <symbolinfo name=\"health_and_safety\" entity=\"e1d5\"/>\n    <symbolinfo name=\"health_metrics\" entity=\"f6e2\"/>\n    <symbolinfo name=\"heap_snapshot_large\" entity=\"f76e\"/>\n    <symbolinfo name=\"heap_snapshot_multiple\" entity=\"f76d\"/>\n    <symbolinfo name=\"heap_snapshot_thumbnail\" entity=\"f76c\"/>\n    <symbolinfo name=\"hearing\" entity=\"e023\"/>\n    <symbolinfo name=\"hearing_disabled\" entity=\"f104\"/>\n    <symbolinfo name=\"heart_broken\" entity=\"eac2\"/>\n    <symbolinfo name=\"heart_check\" entity=\"f60a\"/>\n    <symbolinfo name=\"heart_minus\" entity=\"f883\"/>\n    <symbolinfo name=\"heart_plus\" entity=\"f884\"/>\n    <symbolinfo name=\"heat_pump\" entity=\"ec18\"/>\n    <symbolinfo name=\"heat_pump_balance\" entity=\"e27e\"/>\n    <symbolinfo name=\"height\" entity=\"ea16\"/>\n    <symbolinfo name=\"helicopter\" entity=\"f60c\"/>\n    <symbolinfo name=\"help\" entity=\"e8fd\"/>\n    <symbolinfo name=\"help_center\" entity=\"f1c0\"/>\n    <symbolinfo name=\"help_clinic\" entity=\"f810\"/>\n    <symbolinfo name=\"help_outline\" entity=\"e8fd\"/>\n    <symbolinfo name=\"hematology\" entity=\"e0f6\"/>\n    <symbolinfo name=\"hevc\" entity=\"f021\"/>\n    <symbolinfo name=\"hexagon\" entity=\"eb39\"/>\n    <symbolinfo name=\"hide\" entity=\"ef9e\"/>\n    <symbolinfo name=\"hide_image\" entity=\"f022\"/>\n    <symbolinfo name=\"hide_source\" entity=\"f023\"/>\n    <symbolinfo name=\"high_density\" entity=\"f79c\"/>\n    <symbolinfo name=\"high_quality\" entity=\"e024\"/>\n    <symbolinfo name=\"high_res\" entity=\"f54b\"/>\n    <symbolinfo name=\"highlight\" entity=\"e25f\"/>\n    <symbolinfo name=\"highlight_off\" entity=\"e888\"/>\n    <symbolinfo name=\"highlighter_size_1\" entity=\"f76b\"/>\n    <symbolinfo name=\"highlighter_size_2\" entity=\"f76a\"/>\n    <symbolinfo name=\"highlighter_size_3\" entity=\"f769\"/>\n    <symbolinfo name=\"highlighter_size_4\" entity=\"f768\"/>\n    <symbolinfo name=\"highlighter_size_5\" entity=\"f767\"/>\n    <symbolinfo name=\"hiking\" entity=\"e50a\"/>\n    <symbolinfo name=\"history\" entity=\"e8b3\"/>\n    <symbolinfo name=\"history_edu\" entity=\"ea3e\"/>\n    <symbolinfo name=\"history_toggle_off\" entity=\"f17d\"/>\n    <symbolinfo name=\"hive\" entity=\"eaa6\"/>\n    <symbolinfo name=\"hls\" entity=\"eb8a\"/>\n    <symbolinfo name=\"hls_off\" entity=\"eb8c\"/>\n    <symbolinfo name=\"holiday_village\" entity=\"e58a\"/>\n    <symbolinfo name=\"home\" entity=\"e9b2\"/>\n    <symbolinfo name=\"home_app_logo\" entity=\"e295\"/>\n    <symbolinfo name=\"home_filled\" entity=\"e9b2\"/>\n    <symbolinfo name=\"home_health\" entity=\"e4b9\"/>\n    <symbolinfo name=\"home_iot_device\" entity=\"e283\"/>\n    <symbolinfo name=\"home_max\" entity=\"f024\"/>\n    <symbolinfo name=\"home_max_dots\" entity=\"e849\"/>\n    <symbolinfo name=\"home_mini\" entity=\"f025\"/>\n    <symbolinfo name=\"home_pin\" entity=\"f14d\"/>\n    <symbolinfo name=\"home_repair_service\" entity=\"f100\"/>\n    <symbolinfo name=\"home_speaker\" entity=\"f11c\"/>\n    <symbolinfo name=\"home_storage\" entity=\"f86c\"/>\n    <symbolinfo name=\"home_work\" entity=\"f030\"/>\n    <symbolinfo name=\"horizontal_distribute\" entity=\"e014\"/>\n    <symbolinfo name=\"horizontal_rule\" entity=\"f108\"/>\n    <symbolinfo name=\"horizontal_split\" entity=\"e947\"/>\n    <symbolinfo name=\"hot_tub\" entity=\"eb46\"/>\n    <symbolinfo name=\"hotel\" entity=\"e549\"/>\n    <symbolinfo name=\"hotel_class\" entity=\"e743\"/>\n    <symbolinfo name=\"hourglass\" entity=\"ebff\"/>\n    <symbolinfo name=\"hourglass_bottom\" entity=\"ea5c\"/>\n    <symbolinfo name=\"hourglass_disabled\" entity=\"ef53\"/>\n    <symbolinfo name=\"hourglass_empty\" entity=\"e88b\"/>\n    <symbolinfo name=\"hourglass_full\" entity=\"e88c\"/>\n    <symbolinfo name=\"hourglass_top\" entity=\"ea5b\"/>\n    <symbolinfo name=\"house\" entity=\"ea44\"/>\n    <symbolinfo name=\"house_siding\" entity=\"f202\"/>\n    <symbolinfo name=\"house_with_shield\" entity=\"e786\"/>\n    <symbolinfo name=\"houseboat\" entity=\"e584\"/>\n    <symbolinfo name=\"how_to_reg\" entity=\"e174\"/>\n    <symbolinfo name=\"how_to_vote\" entity=\"e175\"/>\n    <symbolinfo name=\"hr_resting\" entity=\"f6ba\"/>\n    <symbolinfo name=\"html\" entity=\"eb7e\"/>\n    <symbolinfo name=\"http\" entity=\"e902\"/>\n    <symbolinfo name=\"https\" entity=\"e899\"/>\n    <symbolinfo name=\"hub\" entity=\"e9f4\"/>\n    <symbolinfo name=\"humerus\" entity=\"f895\"/>\n    <symbolinfo name=\"humerus_alt\" entity=\"f896\"/>\n    <symbolinfo name=\"humidity_helper\" entity=\"f55f\"/>\n    <symbolinfo name=\"humidity_high\" entity=\"f163\"/>\n    <symbolinfo name=\"humidity_indoor\" entity=\"f558\"/>\n    <symbolinfo name=\"humidity_low\" entity=\"f164\"/>\n    <symbolinfo name=\"humidity_mid\" entity=\"f165\"/>\n    <symbolinfo name=\"humidity_percentage\" entity=\"f87e\"/>\n    <symbolinfo name=\"hvac\" entity=\"f10e\"/>\n    <symbolinfo name=\"ice_skating\" entity=\"e50b\"/>\n    <symbolinfo name=\"icecream\" entity=\"ea69\"/>\n    <symbolinfo name=\"ifl\" entity=\"e025\"/>\n    <symbolinfo name=\"iframe\" entity=\"f71b\"/>\n    <symbolinfo name=\"iframe_off\" entity=\"f71c\"/>\n    <symbolinfo name=\"image\" entity=\"e3f4\"/>\n    <symbolinfo name=\"image_aspect_ratio\" entity=\"e3f5\"/>\n    <symbolinfo name=\"image_not_supported\" entity=\"f116\"/>\n    <symbolinfo name=\"image_search\" entity=\"e43f\"/>\n    <symbolinfo name=\"imagesearch_roller\" entity=\"e9b4\"/>\n    <symbolinfo name=\"imagesmode\" entity=\"efa2\"/>\n    <symbolinfo name=\"immunology\" entity=\"e0fb\"/>\n    <symbolinfo name=\"import_contacts\" entity=\"e0e0\"/>\n    <symbolinfo name=\"import_export\" entity=\"e8d5\"/>\n    <symbolinfo name=\"important_devices\" entity=\"e912\"/>\n    <symbolinfo name=\"in_home_mode\" entity=\"e833\"/>\n    <symbolinfo name=\"inactive_order\" entity=\"e0fc\"/>\n    <symbolinfo name=\"inbox\" entity=\"e156\"/>\n    <symbolinfo name=\"inbox_customize\" entity=\"f859\"/>\n    <symbolinfo name=\"incomplete_circle\" entity=\"e79b\"/>\n    <symbolinfo name=\"indeterminate_check_box\" entity=\"e909\"/>\n    <symbolinfo name=\"indeterminate_question_box\" entity=\"f56d\"/>\n    <symbolinfo name=\"info\" entity=\"e88e\"/>\n    <symbolinfo name=\"info_i\" entity=\"f59b\"/>\n    <symbolinfo name=\"infrared\" entity=\"f87c\"/>\n    <symbolinfo name=\"ink_eraser\" entity=\"e6d0\"/>\n    <symbolinfo name=\"ink_eraser_off\" entity=\"e7e3\"/>\n    <symbolinfo name=\"ink_highlighter\" entity=\"e6d1\"/>\n    <symbolinfo name=\"ink_marker\" entity=\"e6d2\"/>\n    <symbolinfo name=\"ink_pen\" entity=\"e6d3\"/>\n    <symbolinfo name=\"inpatient\" entity=\"e0fe\"/>\n    <symbolinfo name=\"input\" entity=\"e890\"/>\n    <symbolinfo name=\"input_circle\" entity=\"f71a\"/>\n    <symbolinfo name=\"insert_chart\" entity=\"f0cc\"/>\n    <symbolinfo name=\"insert_chart_filled\" entity=\"f0cc\"/>\n    <symbolinfo name=\"insert_chart_outlined\" entity=\"f0cc\"/>\n    <symbolinfo name=\"insert_comment\" entity=\"e24c\"/>\n    <symbolinfo name=\"insert_drive_file\" entity=\"e66d\"/>\n    <symbolinfo name=\"insert_emoticon\" entity=\"ea22\"/>\n    <symbolinfo name=\"insert_invitation\" entity=\"e878\"/>\n    <symbolinfo name=\"insert_link\" entity=\"e250\"/>\n    <symbolinfo name=\"insert_page_break\" entity=\"eaca\"/>\n    <symbolinfo name=\"insert_photo\" entity=\"e3f4\"/>\n    <symbolinfo name=\"insert_text\" entity=\"f827\"/>\n    <symbolinfo name=\"insights\" entity=\"f092\"/>\n    <symbolinfo name=\"install_desktop\" entity=\"eb71\"/>\n    <symbolinfo name=\"install_mobile\" entity=\"eb72\"/>\n    <symbolinfo name=\"instant_mix\" entity=\"e026\"/>\n    <symbolinfo name=\"integration_instructions\" entity=\"ef54\"/>\n    <symbolinfo name=\"interactive_space\" entity=\"f7ff\"/>\n    <symbolinfo name=\"interests\" entity=\"e7c8\"/>\n    <symbolinfo name=\"interpreter_mode\" entity=\"e83b\"/>\n    <symbolinfo name=\"inventory\" entity=\"e179\"/>\n    <symbolinfo name=\"inventory_2\" entity=\"e1a1\"/>\n    <symbolinfo name=\"invert_colors\" entity=\"e891\"/>\n    <symbolinfo name=\"invert_colors_off\" entity=\"e0c4\"/>\n    <symbolinfo name=\"ios_share\" entity=\"e6b8\"/>\n    <symbolinfo name=\"iron\" entity=\"e583\"/>\n    <symbolinfo name=\"iso\" entity=\"e3f6\"/>\n    <symbolinfo name=\"jamboard_kiosk\" entity=\"e9b5\"/>\n    <symbolinfo name=\"javascript\" entity=\"eb7c\"/>\n    <symbolinfo name=\"join\" entity=\"f84f\"/>\n    <symbolinfo name=\"join_full\" entity=\"f84f\"/>\n    <symbolinfo name=\"join_inner\" entity=\"eaf4\"/>\n    <symbolinfo name=\"join_left\" entity=\"eaf2\"/>\n    <symbolinfo name=\"join_right\" entity=\"eaea\"/>\n    <symbolinfo name=\"joystick\" entity=\"f5ee\"/>\n    <symbolinfo name=\"jump_to_element\" entity=\"f719\"/>\n    <symbolinfo name=\"kayaking\" entity=\"e50c\"/>\n    <symbolinfo name=\"kebab_dining\" entity=\"e842\"/>\n    <symbolinfo name=\"keep_public\" entity=\"f56f\"/>\n    <symbolinfo name=\"kettle\" entity=\"e2b9\"/>\n    <symbolinfo name=\"key\" entity=\"e73c\"/>\n    <symbolinfo name=\"key_off\" entity=\"eb84\"/>\n    <symbolinfo name=\"key_visualizer\" entity=\"f199\"/>\n    <symbolinfo name=\"keyboard\" entity=\"e312\"/>\n    <symbolinfo name=\"keyboard_alt\" entity=\"f028\"/>\n    <symbolinfo name=\"keyboard_arrow_down\" entity=\"e313\"/>\n    <symbolinfo name=\"keyboard_arrow_left\" entity=\"e314\"/>\n    <symbolinfo name=\"keyboard_arrow_right\" entity=\"e315\"/>\n    <symbolinfo name=\"keyboard_arrow_up\" entity=\"e316\"/>\n    <symbolinfo name=\"keyboard_backspace\" entity=\"e317\"/>\n    <symbolinfo name=\"keyboard_capslock\" entity=\"e318\"/>\n    <symbolinfo name=\"keyboard_capslock_badge\" entity=\"f7de\"/>\n    <symbolinfo name=\"keyboard_command_key\" entity=\"eae7\"/>\n    <symbolinfo name=\"keyboard_control_key\" entity=\"eae6\"/>\n    <symbolinfo name=\"keyboard_double_arrow_down\" entity=\"ead0\"/>\n    <symbolinfo name=\"keyboard_double_arrow_left\" entity=\"eac3\"/>\n    <symbolinfo name=\"keyboard_double_arrow_right\" entity=\"eac9\"/>\n    <symbolinfo name=\"keyboard_double_arrow_up\" entity=\"eacf\"/>\n    <symbolinfo name=\"keyboard_external_input\" entity=\"f7dd\"/>\n    <symbolinfo name=\"keyboard_full\" entity=\"f7dc\"/>\n    <symbolinfo name=\"keyboard_hide\" entity=\"e31a\"/>\n    <symbolinfo name=\"keyboard_keys\" entity=\"f67b\"/>\n    <symbolinfo name=\"keyboard_off\" entity=\"f67a\"/>\n    <symbolinfo name=\"keyboard_onscreen\" entity=\"f7db\"/>\n    <symbolinfo name=\"keyboard_option_key\" entity=\"eae8\"/>\n    <symbolinfo name=\"keyboard_previous_language\" entity=\"f7da\"/>\n    <symbolinfo name=\"keyboard_return\" entity=\"e31b\"/>\n    <symbolinfo name=\"keyboard_tab\" entity=\"e31c\"/>\n    <symbolinfo name=\"keyboard_tab_rtl\" entity=\"ec73\"/>\n    <symbolinfo name=\"keyboard_voice\" entity=\"e31d\"/>\n    <symbolinfo name=\"king_bed\" entity=\"ea45\"/>\n    <symbolinfo name=\"kitchen\" entity=\"eb47\"/>\n    <symbolinfo name=\"kitesurfing\" entity=\"e50d\"/>\n    <symbolinfo name=\"lab_panel\" entity=\"e103\"/>\n    <symbolinfo name=\"lab_profile\" entity=\"e104\"/>\n    <symbolinfo name=\"lab_research\" entity=\"f80b\"/>\n    <symbolinfo name=\"label\" entity=\"e893\"/>\n    <symbolinfo name=\"label_important\" entity=\"e948\"/>\n    <symbolinfo name=\"label_important_outline\" entity=\"e948\"/>\n    <symbolinfo name=\"label_off\" entity=\"e9b6\"/>\n    <symbolinfo name=\"label_outline\" entity=\"e893\"/>\n    <symbolinfo name=\"labs\" entity=\"e105\"/>\n    <symbolinfo name=\"lan\" entity=\"eb2f\"/>\n    <symbolinfo name=\"landscape\" entity=\"e564\"/>\n    <symbolinfo name=\"landslide\" entity=\"ebd7\"/>\n    <symbolinfo name=\"language\" entity=\"e894\"/>\n    <symbolinfo name=\"language_chinese_array\" entity=\"f766\"/>\n    <symbolinfo name=\"language_chinese_cangjie\" entity=\"f765\"/>\n    <symbolinfo name=\"language_chinese_dayi\" entity=\"f764\"/>\n    <symbolinfo name=\"language_chinese_pinyin\" entity=\"f763\"/>\n    <symbolinfo name=\"language_chinese_quick\" entity=\"f762\"/>\n    <symbolinfo name=\"language_chinese_wubi\" entity=\"f761\"/>\n    <symbolinfo name=\"language_french\" entity=\"f760\"/>\n    <symbolinfo name=\"language_gb_english\" entity=\"f75f\"/>\n    <symbolinfo name=\"language_international\" entity=\"f75e\"/>\n    <symbolinfo name=\"language_korean_latin\" entity=\"f75d\"/>\n    <symbolinfo name=\"language_pinyin\" entity=\"f75c\"/>\n    <symbolinfo name=\"language_spanish\" entity=\"f5e9\"/>\n    <symbolinfo name=\"language_us\" entity=\"f759\"/>\n    <symbolinfo name=\"language_us_colemak\" entity=\"f75b\"/>\n    <symbolinfo name=\"language_us_dvorak\" entity=\"f75a\"/>\n    <symbolinfo name=\"laps\" entity=\"f6b9\"/>\n    <symbolinfo name=\"laptop\" entity=\"e31e\"/>\n    <symbolinfo name=\"laptop_chromebook\" entity=\"e31f\"/>\n    <symbolinfo name=\"laptop_mac\" entity=\"e320\"/>\n    <symbolinfo name=\"laptop_windows\" entity=\"e321\"/>\n    <symbolinfo name=\"lasso_select\" entity=\"eb03\"/>\n    <symbolinfo name=\"last_page\" entity=\"e5dd\"/>\n    <symbolinfo name=\"launch\" entity=\"e89e\"/>\n    <symbolinfo name=\"laundry\" entity=\"e2a8\"/>\n    <symbolinfo name=\"layers\" entity=\"e53b\"/>\n    <symbolinfo name=\"layers_clear\" entity=\"e53c\"/>\n    <symbolinfo name=\"lda\" entity=\"e106\"/>\n    <symbolinfo name=\"leaderboard\" entity=\"f20c\"/>\n    <symbolinfo name=\"leaf_spark\" entity=\"f55e\"/>\n    <symbolinfo name=\"leak_add\" entity=\"e3f8\"/>\n    <symbolinfo name=\"leak_remove\" entity=\"e3f9\"/>\n    <symbolinfo name=\"left_click\" entity=\"f718\"/>\n    <symbolinfo name=\"left_panel_close\" entity=\"f717\"/>\n    <symbolinfo name=\"left_panel_open\" entity=\"f716\"/>\n    <symbolinfo name=\"legend_toggle\" entity=\"f11b\"/>\n    <symbolinfo name=\"lens\" entity=\"e3fa\"/>\n    <symbolinfo name=\"lens_blur\" entity=\"f029\"/>\n    <symbolinfo name=\"letter_switch\" entity=\"f758\"/>\n    <symbolinfo name=\"library_add\" entity=\"e03c\"/>\n    <symbolinfo name=\"library_add_check\" entity=\"e9b7\"/>\n    <symbolinfo name=\"library_books\" entity=\"e02f\"/>\n    <symbolinfo name=\"library_music\" entity=\"e030\"/>\n    <symbolinfo name=\"lift_to_talk\" entity=\"efa3\"/>\n    <symbolinfo name=\"light\" entity=\"f02a\"/>\n    <symbolinfo name=\"light_group\" entity=\"e28b\"/>\n    <symbolinfo name=\"light_mode\" entity=\"e518\"/>\n    <symbolinfo name=\"lightbulb\" entity=\"e90f\"/>\n    <symbolinfo name=\"lightbulb_circle\" entity=\"ebfe\"/>\n    <symbolinfo name=\"lightbulb_outline\" entity=\"e90f\"/>\n    <symbolinfo name=\"line_axis\" entity=\"ea9a\"/>\n    <symbolinfo name=\"line_curve\" entity=\"f757\"/>\n    <symbolinfo name=\"line_end\" entity=\"f826\"/>\n    <symbolinfo name=\"line_end_arrow\" entity=\"f81d\"/>\n    <symbolinfo name=\"line_end_arrow_notch\" entity=\"f81c\"/>\n    <symbolinfo name=\"line_end_circle\" entity=\"f81b\"/>\n    <symbolinfo name=\"line_end_diamond\" entity=\"f81a\"/>\n    <symbolinfo name=\"line_end_square\" entity=\"f819\"/>\n    <symbolinfo name=\"line_start\" entity=\"f825\"/>\n    <symbolinfo name=\"line_start_arrow\" entity=\"f818\"/>\n    <symbolinfo name=\"line_start_arrow_notch\" entity=\"f817\"/>\n    <symbolinfo name=\"line_start_circle\" entity=\"f816\"/>\n    <symbolinfo name=\"line_start_diamond\" entity=\"f815\"/>\n    <symbolinfo name=\"line_start_square\" entity=\"f814\"/>\n    <symbolinfo name=\"line_style\" entity=\"e919\"/>\n    <symbolinfo name=\"line_weight\" entity=\"e91a\"/>\n    <symbolinfo name=\"linear_scale\" entity=\"e260\"/>\n    <symbolinfo name=\"link\" entity=\"e250\"/>\n    <symbolinfo name=\"link_off\" entity=\"e16f\"/>\n    <symbolinfo name=\"linked_camera\" entity=\"e438\"/>\n    <symbolinfo name=\"liquor\" entity=\"ea60\"/>\n    <symbolinfo name=\"list\" entity=\"e896\"/>\n    <symbolinfo name=\"list_alt\" entity=\"e0ee\"/>\n    <symbolinfo name=\"list_alt_add\" entity=\"f756\"/>\n    <symbolinfo name=\"lists\" entity=\"e9b9\"/>\n    <symbolinfo name=\"live_help\" entity=\"e0c6\"/>\n    <symbolinfo name=\"live_tv\" entity=\"e63a\"/>\n    <symbolinfo name=\"living\" entity=\"f02b\"/>\n    <symbolinfo name=\"local_activity\" entity=\"e553\"/>\n    <symbolinfo name=\"local_airport\" entity=\"e53d\"/>\n    <symbolinfo name=\"local_atm\" entity=\"e53e\"/>\n    <symbolinfo name=\"local_bar\" entity=\"e540\"/>\n    <symbolinfo name=\"local_cafe\" entity=\"eb44\"/>\n    <symbolinfo name=\"local_car_wash\" entity=\"e542\"/>\n    <symbolinfo name=\"local_convenience_store\" entity=\"e543\"/>\n    <symbolinfo name=\"local_dining\" entity=\"e561\"/>\n    <symbolinfo name=\"local_drink\" entity=\"e544\"/>\n    <symbolinfo name=\"local_fire_department\" entity=\"ef55\"/>\n    <symbolinfo name=\"local_florist\" entity=\"e545\"/>\n    <symbolinfo name=\"local_gas_station\" entity=\"e546\"/>\n    <symbolinfo name=\"local_grocery_store\" entity=\"e8cc\"/>\n    <symbolinfo name=\"local_hospital\" entity=\"e548\"/>\n    <symbolinfo name=\"local_hotel\" entity=\"e549\"/>\n    <symbolinfo name=\"local_laundry_service\" entity=\"e54a\"/>\n    <symbolinfo name=\"local_library\" entity=\"e54b\"/>\n    <symbolinfo name=\"local_mall\" entity=\"e54c\"/>\n    <symbolinfo name=\"local_movies\" entity=\"e8da\"/>\n    <symbolinfo name=\"local_offer\" entity=\"f05b\"/>\n    <symbolinfo name=\"local_parking\" entity=\"e54f\"/>\n    <symbolinfo name=\"local_pharmacy\" entity=\"e550\"/>\n    <symbolinfo name=\"local_phone\" entity=\"f0d4\"/>\n    <symbolinfo name=\"local_pizza\" entity=\"e552\"/>\n    <symbolinfo name=\"local_play\" entity=\"e553\"/>\n    <symbolinfo name=\"local_police\" entity=\"ef56\"/>\n    <symbolinfo name=\"local_post_office\" entity=\"e554\"/>\n    <symbolinfo name=\"local_printshop\" entity=\"e8ad\"/>\n    <symbolinfo name=\"local_see\" entity=\"e557\"/>\n    <symbolinfo name=\"local_shipping\" entity=\"e558\"/>\n    <symbolinfo name=\"local_taxi\" entity=\"e559\"/>\n    <symbolinfo name=\"location_automation\" entity=\"f14f\"/>\n    <symbolinfo name=\"location_away\" entity=\"f150\"/>\n    <symbolinfo name=\"location_chip\" entity=\"f850\"/>\n    <symbolinfo name=\"location_city\" entity=\"e7f1\"/>\n    <symbolinfo name=\"location_disabled\" entity=\"e1b6\"/>\n    <symbolinfo name=\"location_home\" entity=\"f152\"/>\n    <symbolinfo name=\"location_off\" entity=\"e0c7\"/>\n    <symbolinfo name=\"location_on\" entity=\"f1db\"/>\n    <symbolinfo name=\"location_pin\" entity=\"f1db\"/>\n    <symbolinfo name=\"location_searching\" entity=\"e1b7\"/>\n    <symbolinfo name=\"locator_tag\" entity=\"f8c1\"/>\n    <symbolinfo name=\"lock\" entity=\"e899\"/>\n    <symbolinfo name=\"lock_clock\" entity=\"ef57\"/>\n    <symbolinfo name=\"lock_open\" entity=\"e898\"/>\n    <symbolinfo name=\"lock_open_right\" entity=\"f656\"/>\n    <symbolinfo name=\"lock_outline\" entity=\"e899\"/>\n    <symbolinfo name=\"lock_person\" entity=\"f8f3\"/>\n    <symbolinfo name=\"lock_reset\" entity=\"eade\"/>\n    <symbolinfo name=\"login\" entity=\"ea77\"/>\n    <symbolinfo name=\"logo_dev\" entity=\"ead6\"/>\n    <symbolinfo name=\"logout\" entity=\"e9ba\"/>\n    <symbolinfo name=\"looks\" entity=\"e3fc\"/>\n    <symbolinfo name=\"looks_3\" entity=\"e3fb\"/>\n    <symbolinfo name=\"looks_4\" entity=\"e3fd\"/>\n    <symbolinfo name=\"looks_5\" entity=\"e3fe\"/>\n    <symbolinfo name=\"looks_6\" entity=\"e3ff\"/>\n    <symbolinfo name=\"looks_one\" entity=\"e400\"/>\n    <symbolinfo name=\"looks_two\" entity=\"e401\"/>\n    <symbolinfo name=\"loop\" entity=\"e863\"/>\n    <symbolinfo name=\"loupe\" entity=\"e402\"/>\n    <symbolinfo name=\"low_density\" entity=\"f79b\"/>\n    <symbolinfo name=\"low_priority\" entity=\"e16d\"/>\n    <symbolinfo name=\"loyalty\" entity=\"e89a\"/>\n    <symbolinfo name=\"lte_mobiledata\" entity=\"f02c\"/>\n    <symbolinfo name=\"lte_mobiledata_badge\" entity=\"f7d9\"/>\n    <symbolinfo name=\"lte_plus_mobiledata\" entity=\"f02d\"/>\n    <symbolinfo name=\"lte_plus_mobiledata_badge\" entity=\"f7d8\"/>\n    <symbolinfo name=\"luggage\" entity=\"f235\"/>\n    <symbolinfo name=\"lunch_dining\" entity=\"ea61\"/>\n    <symbolinfo name=\"lyrics\" entity=\"ec0b\"/>\n    <symbolinfo name=\"macro_auto\" entity=\"f6f2\"/>\n    <symbolinfo name=\"macro_off\" entity=\"f8d2\"/>\n    <symbolinfo name=\"magic_button\" entity=\"f136\"/>\n    <symbolinfo name=\"magic_exchange\" entity=\"f7f4\"/>\n    <symbolinfo name=\"magic_tether\" entity=\"f7d7\"/>\n    <symbolinfo name=\"magnification_large\" entity=\"f83d\"/>\n    <symbolinfo name=\"magnification_small\" entity=\"f83c\"/>\n    <symbolinfo name=\"magnify_docked\" entity=\"f7d6\"/>\n    <symbolinfo name=\"magnify_fullscreen\" entity=\"f7d5\"/>\n    <symbolinfo name=\"mail\" entity=\"e159\"/>\n    <symbolinfo name=\"mail_lock\" entity=\"ec0a\"/>\n    <symbolinfo name=\"mail_outline\" entity=\"e159\"/>\n    <symbolinfo name=\"male\" entity=\"e58e\"/>\n    <symbolinfo name=\"man\" entity=\"e4eb\"/>\n    <symbolinfo name=\"man_2\" entity=\"f8e1\"/>\n    <symbolinfo name=\"man_3\" entity=\"f8e2\"/>\n    <symbolinfo name=\"man_4\" entity=\"f8e3\"/>\n    <symbolinfo name=\"manage_accounts\" entity=\"f02e\"/>\n    <symbolinfo name=\"manage_history\" entity=\"ebe7\"/>\n    <symbolinfo name=\"manage_search\" entity=\"f02f\"/>\n    <symbolinfo name=\"manga\" entity=\"f5e3\"/>\n    <symbolinfo name=\"map\" entity=\"e55b\"/>\n    <symbolinfo name=\"maps_home_work\" entity=\"f030\"/>\n    <symbolinfo name=\"maps_ugc\" entity=\"ef58\"/>\n    <symbolinfo name=\"margin\" entity=\"e9bb\"/>\n    <symbolinfo name=\"mark_as_unread\" entity=\"e9bc\"/>\n    <symbolinfo name=\"mark_chat_read\" entity=\"f18b\"/>\n    <symbolinfo name=\"mark_chat_unread\" entity=\"f189\"/>\n    <symbolinfo name=\"mark_email_read\" entity=\"f18c\"/>\n    <symbolinfo name=\"mark_email_unread\" entity=\"f18a\"/>\n    <symbolinfo name=\"mark_unread_chat_alt\" entity=\"eb9d\"/>\n    <symbolinfo name=\"markdown\" entity=\"f552\"/>\n    <symbolinfo name=\"markdown_copy\" entity=\"f553\"/>\n    <symbolinfo name=\"markdown_paste\" entity=\"f554\"/>\n    <symbolinfo name=\"markunread\" entity=\"e159\"/>\n    <symbolinfo name=\"markunread_mailbox\" entity=\"e89b\"/>\n    <symbolinfo name=\"masked_transitions\" entity=\"e72e\"/>\n    <symbolinfo name=\"masks\" entity=\"f218\"/>\n    <symbolinfo name=\"match_case\" entity=\"f6f1\"/>\n    <symbolinfo name=\"match_word\" entity=\"f6f0\"/>\n    <symbolinfo name=\"matter\" entity=\"e907\"/>\n    <symbolinfo name=\"maximize\" entity=\"e930\"/>\n    <symbolinfo name=\"measuring_tape\" entity=\"f6af\"/>\n    <symbolinfo name=\"media_bluetooth_off\" entity=\"f031\"/>\n    <symbolinfo name=\"media_bluetooth_on\" entity=\"f032\"/>\n    <symbolinfo name=\"media_link\" entity=\"f83f\"/>\n    <symbolinfo name=\"mediation\" entity=\"efa7\"/>\n    <symbolinfo name=\"medical_information\" entity=\"ebed\"/>\n    <symbolinfo name=\"medical_mask\" entity=\"f80a\"/>\n    <symbolinfo name=\"medical_services\" entity=\"f109\"/>\n    <symbolinfo name=\"medication\" entity=\"f033\"/>\n    <symbolinfo name=\"medication_liquid\" entity=\"ea87\"/>\n    <symbolinfo name=\"meeting_room\" entity=\"eb4f\"/>\n    <symbolinfo name=\"memory\" entity=\"e322\"/>\n    <symbolinfo name=\"memory_alt\" entity=\"f7a3\"/>\n    <symbolinfo name=\"menstrual_health\" entity=\"f6e1\"/>\n    <symbolinfo name=\"menu\" entity=\"e5d2\"/>\n    <symbolinfo name=\"menu_book\" entity=\"ea19\"/>\n    <symbolinfo name=\"menu_open\" entity=\"e9bd\"/>\n    <symbolinfo name=\"merge\" entity=\"eb98\"/>\n    <symbolinfo name=\"merge_type\" entity=\"e252\"/>\n    <symbolinfo name=\"message\" entity=\"e0c9\"/>\n    <symbolinfo name=\"metabolism\" entity=\"e10b\"/>\n    <symbolinfo name=\"mfg_nest_yale_lock\" entity=\"f11d\"/>\n    <symbolinfo name=\"mic\" entity=\"e31d\"/>\n    <symbolinfo name=\"mic_double\" entity=\"f5d1\"/>\n    <symbolinfo name=\"mic_external_off\" entity=\"ef59\"/>\n    <symbolinfo name=\"mic_external_on\" entity=\"ef5a\"/>\n    <symbolinfo name=\"mic_none\" entity=\"e31d\"/>\n    <symbolinfo name=\"mic_off\" entity=\"e02b\"/>\n    <symbolinfo name=\"microbiology\" entity=\"e10c\"/>\n    <symbolinfo name=\"microwave\" entity=\"f204\"/>\n    <symbolinfo name=\"microwave_gen\" entity=\"e847\"/>\n    <symbolinfo name=\"military_tech\" entity=\"ea3f\"/>\n    <symbolinfo name=\"mimo\" entity=\"e9be\"/>\n    <symbolinfo name=\"mimo_disconnect\" entity=\"e9bf\"/>\n    <symbolinfo name=\"mindfulness\" entity=\"f6e0\"/>\n    <symbolinfo name=\"minimize\" entity=\"e931\"/>\n    <symbolinfo name=\"minor_crash\" entity=\"ebf1\"/>\n    <symbolinfo name=\"missed_video_call\" entity=\"f0ce\"/>\n    <symbolinfo name=\"missed_video_call_filled\" entity=\"f0ce\"/>\n    <symbolinfo name=\"mist\" entity=\"e188\"/>\n    <symbolinfo name=\"mixture_med\" entity=\"e4c8\"/>\n    <symbolinfo name=\"mms\" entity=\"e618\"/>\n    <symbolinfo name=\"mobile_friendly\" entity=\"e200\"/>\n    <symbolinfo name=\"mobile_off\" entity=\"e201\"/>\n    <symbolinfo name=\"mobile_screen_share\" entity=\"e0e7\"/>\n    <symbolinfo name=\"mobiledata_off\" entity=\"f034\"/>\n    <symbolinfo name=\"mode\" entity=\"f097\"/>\n    <symbolinfo name=\"mode_comment\" entity=\"e253\"/>\n    <symbolinfo name=\"mode_cool\" entity=\"f166\"/>\n    <symbolinfo name=\"mode_cool_off\" entity=\"f167\"/>\n    <symbolinfo name=\"mode_dual\" entity=\"f557\"/>\n    <symbolinfo name=\"mode_edit\" entity=\"f097\"/>\n    <symbolinfo name=\"mode_edit_outline\" entity=\"f097\"/>\n    <symbolinfo name=\"mode_fan\" entity=\"f168\"/>\n    <symbolinfo name=\"mode_fan_off\" entity=\"ec17\"/>\n    <symbolinfo name=\"mode_heat\" entity=\"f16a\"/>\n    <symbolinfo name=\"mode_heat_cool\" entity=\"f16b\"/>\n    <symbolinfo name=\"mode_heat_off\" entity=\"f16d\"/>\n    <symbolinfo name=\"mode_night\" entity=\"f036\"/>\n    <symbolinfo name=\"mode_of_travel\" entity=\"e7ce\"/>\n    <symbolinfo name=\"mode_off_on\" entity=\"f16f\"/>\n    <symbolinfo name=\"mode_standby\" entity=\"f037\"/>\n    <symbolinfo name=\"model_training\" entity=\"f0cf\"/>\n    <symbolinfo name=\"monetization_on\" entity=\"e263\"/>\n    <symbolinfo name=\"money\" entity=\"e57d\"/>\n    <symbolinfo name=\"money_off\" entity=\"f038\"/>\n    <symbolinfo name=\"money_off_csred\" entity=\"f038\"/>\n    <symbolinfo name=\"monitor\" entity=\"ef5b\"/>\n    <symbolinfo name=\"monitor_heart\" entity=\"eaa2\"/>\n    <symbolinfo name=\"monitor_weight\" entity=\"f039\"/>\n    <symbolinfo name=\"monitor_weight_gain\" entity=\"f6df\"/>\n    <symbolinfo name=\"monitor_weight_loss\" entity=\"f6de\"/>\n    <symbolinfo name=\"monitoring\" entity=\"f190\"/>\n    <symbolinfo name=\"monochrome_photos\" entity=\"e403\"/>\n    <symbolinfo name=\"mood\" entity=\"ea22\"/>\n    <symbolinfo name=\"mood_bad\" entity=\"e7f3\"/>\n    <symbolinfo name=\"mop\" entity=\"e28d\"/>\n    <symbolinfo name=\"more\" entity=\"e619\"/>\n    <symbolinfo name=\"more_down\" entity=\"f196\"/>\n    <symbolinfo name=\"more_horiz\" entity=\"e5d3\"/>\n    <symbolinfo name=\"more_time\" entity=\"ea5d\"/>\n    <symbolinfo name=\"more_up\" entity=\"f197\"/>\n    <symbolinfo name=\"more_vert\" entity=\"e5d4\"/>\n    <symbolinfo name=\"mosque\" entity=\"eab2\"/>\n    <symbolinfo name=\"motion_blur\" entity=\"f0d0\"/>\n    <symbolinfo name=\"motion_mode\" entity=\"f842\"/>\n    <symbolinfo name=\"motion_photos_auto\" entity=\"f03a\"/>\n    <symbolinfo name=\"motion_photos_off\" entity=\"e9c0\"/>\n    <symbolinfo name=\"motion_photos_on\" entity=\"e9c1\"/>\n    <symbolinfo name=\"motion_photos_pause\" entity=\"f227\"/>\n    <symbolinfo name=\"motion_photos_paused\" entity=\"f227\"/>\n    <symbolinfo name=\"motion_sensor_active\" entity=\"e792\"/>\n    <symbolinfo name=\"motion_sensor_alert\" entity=\"e784\"/>\n    <symbolinfo name=\"motion_sensor_idle\" entity=\"e783\"/>\n    <symbolinfo name=\"motion_sensor_urgent\" entity=\"e78e\"/>\n    <symbolinfo name=\"motorcycle\" entity=\"e91b\"/>\n    <symbolinfo name=\"mountain_flag\" entity=\"f5e2\"/>\n    <symbolinfo name=\"mouse\" entity=\"e323\"/>\n    <symbolinfo name=\"move\" entity=\"e740\"/>\n    <symbolinfo name=\"move_down\" entity=\"eb61\"/>\n    <symbolinfo name=\"move_group\" entity=\"f715\"/>\n    <symbolinfo name=\"move_item\" entity=\"f1ff\"/>\n    <symbolinfo name=\"move_location\" entity=\"e741\"/>\n    <symbolinfo name=\"move_selection_down\" entity=\"f714\"/>\n    <symbolinfo name=\"move_selection_left\" entity=\"f713\"/>\n    <symbolinfo name=\"move_selection_right\" entity=\"f712\"/>\n    <symbolinfo name=\"move_selection_up\" entity=\"f711\"/>\n    <symbolinfo name=\"move_to_inbox\" entity=\"e168\"/>\n    <symbolinfo name=\"move_up\" entity=\"eb64\"/>\n    <symbolinfo name=\"moved_location\" entity=\"e594\"/>\n    <symbolinfo name=\"movie\" entity=\"e404\"/>\n    <symbolinfo name=\"movie_creation\" entity=\"e404\"/>\n    <symbolinfo name=\"movie_edit\" entity=\"f840\"/>\n    <symbolinfo name=\"movie_filter\" entity=\"e43a\"/>\n    <symbolinfo name=\"movie_info\" entity=\"e02d\"/>\n    <symbolinfo name=\"moving\" entity=\"e501\"/>\n    <symbolinfo name=\"moving_beds\" entity=\"e73d\"/>\n    <symbolinfo name=\"moving_ministry\" entity=\"e73e\"/>\n    <symbolinfo name=\"mp\" entity=\"e9c3\"/>\n    <symbolinfo name=\"multicooker\" entity=\"e293\"/>\n    <symbolinfo name=\"multiline_chart\" entity=\"e6df\"/>\n    <symbolinfo name=\"multiple_stop\" entity=\"f1b9\"/>\n    <symbolinfo name=\"museum\" entity=\"ea36\"/>\n    <symbolinfo name=\"music_note\" entity=\"e405\"/>\n    <symbolinfo name=\"music_off\" entity=\"e440\"/>\n    <symbolinfo name=\"music_video\" entity=\"e063\"/>\n    <symbolinfo name=\"my_location\" entity=\"e55c\"/>\n    <symbolinfo name=\"mystery\" entity=\"f5e1\"/>\n    <symbolinfo name=\"nat\" entity=\"ef5c\"/>\n    <symbolinfo name=\"nature\" entity=\"e406\"/>\n    <symbolinfo name=\"nature_people\" entity=\"e407\"/>\n    <symbolinfo name=\"navigate_before\" entity=\"e408\"/>\n    <symbolinfo name=\"navigate_next\" entity=\"e409\"/>\n    <symbolinfo name=\"navigation\" entity=\"e55d\"/>\n    <symbolinfo name=\"near_me\" entity=\"e569\"/>\n    <symbolinfo name=\"near_me_disabled\" entity=\"f1ef\"/>\n    <symbolinfo name=\"nearby\" entity=\"e6b7\"/>\n    <symbolinfo name=\"nearby_error\" entity=\"f03b\"/>\n    <symbolinfo name=\"nearby_off\" entity=\"f03c\"/>\n    <symbolinfo name=\"nephrology\" entity=\"e10d\"/>\n    <symbolinfo name=\"nest_audio\" entity=\"ebbf\"/>\n    <symbolinfo name=\"nest_cam_floodlight\" entity=\"f8b7\"/>\n    <symbolinfo name=\"nest_cam_indoor\" entity=\"f11e\"/>\n    <symbolinfo name=\"nest_cam_iq\" entity=\"f11f\"/>\n    <symbolinfo name=\"nest_cam_iq_outdoor\" entity=\"f120\"/>\n    <symbolinfo name=\"nest_cam_magnet_mount\" entity=\"f8b8\"/>\n    <symbolinfo name=\"nest_cam_outdoor\" entity=\"f121\"/>\n    <symbolinfo name=\"nest_cam_stand\" entity=\"f8b9\"/>\n    <symbolinfo name=\"nest_cam_wall_mount\" entity=\"f8ba\"/>\n    <symbolinfo name=\"nest_cam_wired_stand\" entity=\"ec16\"/>\n    <symbolinfo name=\"nest_clock_farsight_analog\" entity=\"f8bb\"/>\n    <symbolinfo name=\"nest_clock_farsight_digital\" entity=\"f8bc\"/>\n    <symbolinfo name=\"nest_connect\" entity=\"f122\"/>\n    <symbolinfo name=\"nest_detect\" entity=\"f123\"/>\n    <symbolinfo name=\"nest_display\" entity=\"f124\"/>\n    <symbolinfo name=\"nest_display_max\" entity=\"f125\"/>\n    <symbolinfo name=\"nest_doorbell_visitor\" entity=\"f8bd\"/>\n    <symbolinfo name=\"nest_eco_leaf\" entity=\"f8be\"/>\n    <symbolinfo name=\"nest_farsight_weather\" entity=\"f8bf\"/>\n    <symbolinfo name=\"nest_found_savings\" entity=\"f8c0\"/>\n    <symbolinfo name=\"nest_gale_wifi\" entity=\"f579\"/>\n    <symbolinfo name=\"nest_heat_link_e\" entity=\"f126\"/>\n    <symbolinfo name=\"nest_heat_link_gen_3\" entity=\"f127\"/>\n    <symbolinfo name=\"nest_hello_doorbell\" entity=\"e82c\"/>\n    <symbolinfo name=\"nest_locator_tag\" entity=\"f8c1\"/>\n    <symbolinfo name=\"nest_mini\" entity=\"e789\"/>\n    <symbolinfo name=\"nest_multi_room\" entity=\"f8c2\"/>\n    <symbolinfo name=\"nest_protect\" entity=\"e68e\"/>\n    <symbolinfo name=\"nest_remote\" entity=\"f5db\"/>\n    <symbolinfo name=\"nest_remote_comfort_sensor\" entity=\"f12a\"/>\n    <symbolinfo name=\"nest_secure_alarm\" entity=\"f12b\"/>\n    <symbolinfo name=\"nest_sunblock\" entity=\"f8c3\"/>\n    <symbolinfo name=\"nest_tag\" entity=\"f8c1\"/>\n    <symbolinfo name=\"nest_thermostat\" entity=\"e68f\"/>\n    <symbolinfo name=\"nest_thermostat_e_eu\" entity=\"f12d\"/>\n    <symbolinfo name=\"nest_thermostat_gen_3\" entity=\"f12e\"/>\n    <symbolinfo name=\"nest_thermostat_sensor\" entity=\"f12f\"/>\n    <symbolinfo name=\"nest_thermostat_sensor_eu\" entity=\"f130\"/>\n    <symbolinfo name=\"nest_thermostat_zirconium_eu\" entity=\"f131\"/>\n    <symbolinfo name=\"nest_true_radiant\" entity=\"f8c4\"/>\n    <symbolinfo name=\"nest_wake_on_approach\" entity=\"f8c5\"/>\n    <symbolinfo name=\"nest_wake_on_press\" entity=\"f8c6\"/>\n    <symbolinfo name=\"nest_wifi_gale\" entity=\"f132\"/>\n    <symbolinfo name=\"nest_wifi_mistral\" entity=\"f133\"/>\n    <symbolinfo name=\"nest_wifi_point\" entity=\"f134\"/>\n    <symbolinfo name=\"nest_wifi_point_vento\" entity=\"f134\"/>\n    <symbolinfo name=\"nest_wifi_pro\" entity=\"f56b\"/>\n    <symbolinfo name=\"nest_wifi_pro_2\" entity=\"f56a\"/>\n    <symbolinfo name=\"nest_wifi_router\" entity=\"f133\"/>\n    <symbolinfo name=\"network_cell\" entity=\"e1b9\"/>\n    <symbolinfo name=\"network_check\" entity=\"e640\"/>\n    <symbolinfo name=\"network_intelligence_history\" entity=\"f5f6\"/>\n    <symbolinfo name=\"network_intelligence_update\" entity=\"f5f5\"/>\n    <symbolinfo name=\"network_locked\" entity=\"e61a\"/>\n    <symbolinfo name=\"network_manage\" entity=\"f7ab\"/>\n    <symbolinfo name=\"network_node\" entity=\"f56e\"/>\n    <symbolinfo name=\"network_ping\" entity=\"ebca\"/>\n    <symbolinfo name=\"network_wifi\" entity=\"e1ba\"/>\n    <symbolinfo name=\"network_wifi_1_bar\" entity=\"ebe4\"/>\n    <symbolinfo name=\"network_wifi_1_bar_locked\" entity=\"f58f\"/>\n    <symbolinfo name=\"network_wifi_2_bar\" entity=\"ebd6\"/>\n    <symbolinfo name=\"network_wifi_2_bar_locked\" entity=\"f58e\"/>\n    <symbolinfo name=\"network_wifi_3_bar\" entity=\"ebe1\"/>\n    <symbolinfo name=\"network_wifi_3_bar_locked\" entity=\"f58d\"/>\n    <symbolinfo name=\"neurology\" entity=\"e10e\"/>\n    <symbolinfo name=\"new_label\" entity=\"e609\"/>\n    <symbolinfo name=\"new_releases\" entity=\"ef76\"/>\n    <symbolinfo name=\"new_window\" entity=\"f710\"/>\n    <symbolinfo name=\"news\" entity=\"e032\"/>\n    <symbolinfo name=\"newsmode\" entity=\"efad\"/>\n    <symbolinfo name=\"newspaper\" entity=\"eb81\"/>\n    <symbolinfo name=\"next_plan\" entity=\"ef5d\"/>\n    <symbolinfo name=\"next_week\" entity=\"e16a\"/>\n    <symbolinfo name=\"nfc\" entity=\"e1bb\"/>\n    <symbolinfo name=\"night_shelter\" entity=\"f1f1\"/>\n    <symbolinfo name=\"night_sight_auto\" entity=\"f1d7\"/>\n    <symbolinfo name=\"night_sight_auto_off\" entity=\"f1f9\"/>\n    <symbolinfo name=\"night_sight_max\" entity=\"f6c3\"/>\n    <symbolinfo name=\"nightlife\" entity=\"ea62\"/>\n    <symbolinfo name=\"nightlight\" entity=\"f03d\"/>\n    <symbolinfo name=\"nightlight_round\" entity=\"f03d\"/>\n    <symbolinfo name=\"nights_stay\" entity=\"ea46\"/>\n    <symbolinfo name=\"no_accounts\" entity=\"f03e\"/>\n    <symbolinfo name=\"no_adult_content\" entity=\"f8fe\"/>\n    <symbolinfo name=\"no_backpack\" entity=\"f237\"/>\n    <symbolinfo name=\"no_crash\" entity=\"ebf0\"/>\n    <symbolinfo name=\"no_drinks\" entity=\"f1a5\"/>\n    <symbolinfo name=\"no_encryption\" entity=\"f03f\"/>\n    <symbolinfo name=\"no_encryption_gmailerrorred\" entity=\"f03f\"/>\n    <symbolinfo name=\"no_flash\" entity=\"f1a6\"/>\n    <symbolinfo name=\"no_food\" entity=\"f1a7\"/>\n    <symbolinfo name=\"no_luggage\" entity=\"f23b\"/>\n    <symbolinfo name=\"no_meals\" entity=\"f1d6\"/>\n    <symbolinfo name=\"no_meeting_room\" entity=\"eb4e\"/>\n    <symbolinfo name=\"no_photography\" entity=\"f1a8\"/>\n    <symbolinfo name=\"no_sim\" entity=\"e1ce\"/>\n    <symbolinfo name=\"no_sound\" entity=\"e710\"/>\n    <symbolinfo name=\"no_stroller\" entity=\"f1af\"/>\n    <symbolinfo name=\"no_transfer\" entity=\"f1d5\"/>\n    <symbolinfo name=\"noise_aware\" entity=\"ebec\"/>\n    <symbolinfo name=\"noise_control_off\" entity=\"ebf3\"/>\n    <symbolinfo name=\"noise_control_on\" entity=\"f8a8\"/>\n    <symbolinfo name=\"nordic_walking\" entity=\"e50e\"/>\n    <symbolinfo name=\"north\" entity=\"f1e0\"/>\n    <symbolinfo name=\"north_east\" entity=\"f1e1\"/>\n    <symbolinfo name=\"north_west\" entity=\"f1e2\"/>\n    <symbolinfo name=\"not_accessible\" entity=\"f0fe\"/>\n    <symbolinfo name=\"not_accessible_forward\" entity=\"f54a\"/>\n    <symbolinfo name=\"not_interested\" entity=\"f08c\"/>\n    <symbolinfo name=\"not_listed_location\" entity=\"e575\"/>\n    <symbolinfo name=\"not_started\" entity=\"f0d1\"/>\n    <symbolinfo name=\"note\" entity=\"e66d\"/>\n    <symbolinfo name=\"note_add\" entity=\"e89c\"/>\n    <symbolinfo name=\"note_alt\" entity=\"f040\"/>\n    <symbolinfo name=\"note_stack\" entity=\"f562\"/>\n    <symbolinfo name=\"note_stack_add\" entity=\"f563\"/>\n    <symbolinfo name=\"notes\" entity=\"e26c\"/>\n    <symbolinfo name=\"notification_add\" entity=\"e399\"/>\n    <symbolinfo name=\"notification_important\" entity=\"e004\"/>\n    <symbolinfo name=\"notification_multiple\" entity=\"e6c2\"/>\n    <symbolinfo name=\"notifications\" entity=\"e7f5\"/>\n    <symbolinfo name=\"notifications_active\" entity=\"e7f7\"/>\n    <symbolinfo name=\"notifications_none\" entity=\"e7f5\"/>\n    <symbolinfo name=\"notifications_off\" entity=\"e7f6\"/>\n    <symbolinfo name=\"notifications_paused\" entity=\"e7f8\"/>\n    <symbolinfo name=\"numbers\" entity=\"eac7\"/>\n    <symbolinfo name=\"nutrition\" entity=\"e110\"/>\n    <symbolinfo name=\"ods\" entity=\"e6e8\"/>\n    <symbolinfo name=\"odt\" entity=\"e6e9\"/>\n    <symbolinfo name=\"offline_bolt\" entity=\"e932\"/>\n    <symbolinfo name=\"offline_pin\" entity=\"e90a\"/>\n    <symbolinfo name=\"offline_share\" entity=\"e9c5\"/>\n    <symbolinfo name=\"oil_barrel\" entity=\"ec15\"/>\n    <symbolinfo name=\"on_device_training\" entity=\"ebfd\"/>\n    <symbolinfo name=\"oncology\" entity=\"e114\"/>\n    <symbolinfo name=\"ondemand_video\" entity=\"e63a\"/>\n    <symbolinfo name=\"online_prediction\" entity=\"f0eb\"/>\n    <symbolinfo name=\"onsen\" entity=\"f6f8\"/>\n    <symbolinfo name=\"opacity\" entity=\"e91c\"/>\n    <symbolinfo name=\"open_in_browser\" entity=\"e89d\"/>\n    <symbolinfo name=\"open_in_full\" entity=\"f1ce\"/>\n    <symbolinfo name=\"open_in_new\" entity=\"e89e\"/>\n    <symbolinfo name=\"open_in_new_down\" entity=\"f70f\"/>\n    <symbolinfo name=\"open_in_new_off\" entity=\"e4f6\"/>\n    <symbolinfo name=\"open_in_phone\" entity=\"e702\"/>\n    <symbolinfo name=\"open_jam\" entity=\"efae\"/>\n    <symbolinfo name=\"open_with\" entity=\"e89f\"/>\n    <symbolinfo name=\"ophthalmology\" entity=\"e115\"/>\n    <symbolinfo name=\"oral_disease\" entity=\"e116\"/>\n    <symbolinfo name=\"order_approve\" entity=\"f812\"/>\n    <symbolinfo name=\"order_play\" entity=\"f811\"/>\n    <symbolinfo name=\"orthopedics\" entity=\"f897\"/>\n    <symbolinfo name=\"other_admission\" entity=\"e47b\"/>\n    <symbolinfo name=\"other_houses\" entity=\"e58c\"/>\n    <symbolinfo name=\"outbound\" entity=\"e1ca\"/>\n    <symbolinfo name=\"outbox\" entity=\"ef5f\"/>\n    <symbolinfo name=\"outbox_alt\" entity=\"eb17\"/>\n    <symbolinfo name=\"outdoor_garden\" entity=\"e205\"/>\n    <symbolinfo name=\"outdoor_grill\" entity=\"ea47\"/>\n    <symbolinfo name=\"outgoing_mail\" entity=\"f0d2\"/>\n    <symbolinfo name=\"outlet\" entity=\"f1d4\"/>\n    <symbolinfo name=\"outlined_flag\" entity=\"f0c6\"/>\n    <symbolinfo name=\"outpatient\" entity=\"e118\"/>\n    <symbolinfo name=\"outpatient_med\" entity=\"e119\"/>\n    <symbolinfo name=\"output\" entity=\"ebbe\"/>\n    <symbolinfo name=\"output_circle\" entity=\"f70e\"/>\n    <symbolinfo name=\"oven_gen\" entity=\"e843\"/>\n    <symbolinfo name=\"overview\" entity=\"e4a7\"/>\n    <symbolinfo name=\"overview_key\" entity=\"f7d4\"/>\n    <symbolinfo name=\"oxygen_saturation\" entity=\"e4de\"/>\n    <symbolinfo name=\"pace\" entity=\"f6b8\"/>\n    <symbolinfo name=\"pacemaker\" entity=\"e656\"/>\n    <symbolinfo name=\"package\" entity=\"e48f\"/>\n    <symbolinfo name=\"package_2\" entity=\"f569\"/>\n    <symbolinfo name=\"padding\" entity=\"e9c8\"/>\n    <symbolinfo name=\"page_control\" entity=\"e731\"/>\n    <symbolinfo name=\"page_info\" entity=\"f614\"/>\n    <symbolinfo name=\"pages\" entity=\"e7f9\"/>\n    <symbolinfo name=\"pageview\" entity=\"e8a0\"/>\n    <symbolinfo name=\"paid\" entity=\"f041\"/>\n    <symbolinfo name=\"palette\" entity=\"e40a\"/>\n    <symbolinfo name=\"pallet\" entity=\"f86a\"/>\n    <symbolinfo name=\"pan_tool\" entity=\"e925\"/>\n    <symbolinfo name=\"pan_tool_alt\" entity=\"ebb9\"/>\n    <symbolinfo name=\"pan_zoom\" entity=\"f655\"/>\n    <symbolinfo name=\"panorama\" entity=\"e40b\"/>\n    <symbolinfo name=\"panorama_fish_eye\" entity=\"e40c\"/>\n    <symbolinfo name=\"panorama_horizontal\" entity=\"e40d\"/>\n    <symbolinfo name=\"panorama_photosphere\" entity=\"e9c9\"/>\n    <symbolinfo name=\"panorama_vertical\" entity=\"e40e\"/>\n    <symbolinfo name=\"panorama_wide_angle\" entity=\"e40f\"/>\n    <symbolinfo name=\"paragliding\" entity=\"e50f\"/>\n    <symbolinfo name=\"park\" entity=\"ea63\"/>\n    <symbolinfo name=\"partly_cloudy_day\" entity=\"f172\"/>\n    <symbolinfo name=\"partly_cloudy_night\" entity=\"f174\"/>\n    <symbolinfo name=\"partner_exchange\" entity=\"f7f9\"/>\n    <symbolinfo name=\"partner_reports\" entity=\"efaf\"/>\n    <symbolinfo name=\"party_mode\" entity=\"e7fa\"/>\n    <symbolinfo name=\"passkey\" entity=\"f87f\"/>\n    <symbolinfo name=\"password\" entity=\"f042\"/>\n    <symbolinfo name=\"patient_list\" entity=\"e653\"/>\n    <symbolinfo name=\"pattern\" entity=\"f043\"/>\n    <symbolinfo name=\"pause\" entity=\"e034\"/>\n    <symbolinfo name=\"pause_circle\" entity=\"e1a2\"/>\n    <symbolinfo name=\"pause_circle_filled\" entity=\"e1a2\"/>\n    <symbolinfo name=\"pause_circle_outline\" entity=\"e1a2\"/>\n    <symbolinfo name=\"pause_presentation\" entity=\"e0ea\"/>\n    <symbolinfo name=\"payment\" entity=\"e8a1\"/>\n    <symbolinfo name=\"payments\" entity=\"ef63\"/>\n    <symbolinfo name=\"pedal_bike\" entity=\"eb29\"/>\n    <symbolinfo name=\"pediatrics\" entity=\"e11d\"/>\n    <symbolinfo name=\"pen_size_1\" entity=\"f755\"/>\n    <symbolinfo name=\"pen_size_2\" entity=\"f754\"/>\n    <symbolinfo name=\"pen_size_3\" entity=\"f753\"/>\n    <symbolinfo name=\"pen_size_4\" entity=\"f752\"/>\n    <symbolinfo name=\"pen_size_5\" entity=\"f751\"/>\n    <symbolinfo name=\"pending\" entity=\"ef64\"/>\n    <symbolinfo name=\"pending_actions\" entity=\"f1bb\"/>\n    <symbolinfo name=\"pentagon\" entity=\"eb50\"/>\n    <symbolinfo name=\"people\" entity=\"ea21\"/>\n    <symbolinfo name=\"people_alt\" entity=\"ea21\"/>\n    <symbolinfo name=\"people_outline\" entity=\"ea21\"/>\n    <symbolinfo name=\"percent\" entity=\"eb58\"/>\n    <symbolinfo name=\"performance_max\" entity=\"e51a\"/>\n    <symbolinfo name=\"pergola\" entity=\"e203\"/>\n    <symbolinfo name=\"perm_camera_mic\" entity=\"e8a2\"/>\n    <symbolinfo name=\"perm_contact_calendar\" entity=\"e8a3\"/>\n    <symbolinfo name=\"perm_data_setting\" entity=\"e8a4\"/>\n    <symbolinfo name=\"perm_device_information\" entity=\"e8a5\"/>\n    <symbolinfo name=\"perm_identity\" entity=\"f0d3\"/>\n    <symbolinfo name=\"perm_media\" entity=\"e8a7\"/>\n    <symbolinfo name=\"perm_phone_msg\" entity=\"e8a8\"/>\n    <symbolinfo name=\"perm_scan_wifi\" entity=\"e8a9\"/>\n    <symbolinfo name=\"person\" entity=\"f0d3\"/>\n    <symbolinfo name=\"person_2\" entity=\"f8e4\"/>\n    <symbolinfo name=\"person_3\" entity=\"f8e5\"/>\n    <symbolinfo name=\"person_4\" entity=\"f8e6\"/>\n    <symbolinfo name=\"person_add\" entity=\"ea4d\"/>\n    <symbolinfo name=\"person_add_alt\" entity=\"ea4d\"/>\n    <symbolinfo name=\"person_add_disabled\" entity=\"e9cb\"/>\n    <symbolinfo name=\"person_alert\" entity=\"f567\"/>\n    <symbolinfo name=\"person_apron\" entity=\"f5a3\"/>\n    <symbolinfo name=\"person_book\" entity=\"f5e8\"/>\n    <symbolinfo name=\"person_cancel\" entity=\"f566\"/>\n    <symbolinfo name=\"person_celebrate\" entity=\"f7fe\"/>\n    <symbolinfo name=\"person_check\" entity=\"f565\"/>\n    <symbolinfo name=\"person_filled\" entity=\"f0d3\"/>\n    <symbolinfo name=\"person_off\" entity=\"e510\"/>\n    <symbolinfo name=\"person_outline\" entity=\"f0d3\"/>\n    <symbolinfo name=\"person_pin\" entity=\"e55a\"/>\n    <symbolinfo name=\"person_pin_circle\" entity=\"e56a\"/>\n    <symbolinfo name=\"person_play\" entity=\"f7fd\"/>\n    <symbolinfo name=\"person_raised_hand\" entity=\"f59a\"/>\n    <symbolinfo name=\"person_remove\" entity=\"ef66\"/>\n    <symbolinfo name=\"person_search\" entity=\"f106\"/>\n    <symbolinfo name=\"personal_injury\" entity=\"e6da\"/>\n    <symbolinfo name=\"personal_video\" entity=\"e63b\"/>\n    <symbolinfo name=\"pest_control\" entity=\"f0fa\"/>\n    <symbolinfo name=\"pest_control_rodent\" entity=\"f0fd\"/>\n    <symbolinfo name=\"pet_supplies\" entity=\"efb1\"/>\n    <symbolinfo name=\"pets\" entity=\"e91d\"/>\n    <symbolinfo name=\"phishing\" entity=\"ead7\"/>\n    <symbolinfo name=\"phone\" entity=\"f0d4\"/>\n    <symbolinfo name=\"phone_alt\" entity=\"f0d4\"/>\n    <symbolinfo name=\"phone_android\" entity=\"e324\"/>\n    <symbolinfo name=\"phone_bluetooth_speaker\" entity=\"e61b\"/>\n    <symbolinfo name=\"phone_callback\" entity=\"e649\"/>\n    <symbolinfo name=\"phone_disabled\" entity=\"e9cc\"/>\n    <symbolinfo name=\"phone_enabled\" entity=\"e9cd\"/>\n    <symbolinfo name=\"phone_forwarded\" entity=\"e61c\"/>\n    <symbolinfo name=\"phone_in_talk\" entity=\"e61d\"/>\n    <symbolinfo name=\"phone_iphone\" entity=\"e325\"/>\n    <symbolinfo name=\"phone_locked\" entity=\"e61e\"/>\n    <symbolinfo name=\"phone_missed\" entity=\"e61f\"/>\n    <symbolinfo name=\"phone_paused\" entity=\"e620\"/>\n    <symbolinfo name=\"phonelink\" entity=\"e326\"/>\n    <symbolinfo name=\"phonelink_erase\" entity=\"e0db\"/>\n    <symbolinfo name=\"phonelink_lock\" entity=\"e0dc\"/>\n    <symbolinfo name=\"phonelink_off\" entity=\"e327\"/>\n    <symbolinfo name=\"phonelink_ring\" entity=\"e0dd\"/>\n    <symbolinfo name=\"phonelink_ring_off\" entity=\"f7aa\"/>\n    <symbolinfo name=\"phonelink_setup\" entity=\"ef41\"/>\n    <symbolinfo name=\"photo\" entity=\"e432\"/>\n    <symbolinfo name=\"photo_album\" entity=\"e411\"/>\n    <symbolinfo name=\"photo_camera\" entity=\"e412\"/>\n    <symbolinfo name=\"photo_camera_back\" entity=\"ef68\"/>\n    <symbolinfo name=\"photo_camera_front\" entity=\"ef69\"/>\n    <symbolinfo name=\"photo_filter\" entity=\"e43b\"/>\n    <symbolinfo name=\"photo_frame\" entity=\"f0d9\"/>\n    <symbolinfo name=\"photo_library\" entity=\"e413\"/>\n    <symbolinfo name=\"photo_prints\" entity=\"efb2\"/>\n    <symbolinfo name=\"photo_size_select_actual\" entity=\"e432\"/>\n    <symbolinfo name=\"photo_size_select_large\" entity=\"e433\"/>\n    <symbolinfo name=\"photo_size_select_small\" entity=\"e434\"/>\n    <symbolinfo name=\"php\" entity=\"eb8f\"/>\n    <symbolinfo name=\"physical_therapy\" entity=\"e11e\"/>\n    <symbolinfo name=\"piano\" entity=\"e521\"/>\n    <symbolinfo name=\"piano_off\" entity=\"e520\"/>\n    <symbolinfo name=\"picture_as_pdf\" entity=\"e415\"/>\n    <symbolinfo name=\"picture_in_picture\" entity=\"e8aa\"/>\n    <symbolinfo name=\"picture_in_picture_alt\" entity=\"e911\"/>\n    <symbolinfo name=\"picture_in_picture_center\" entity=\"f550\"/>\n    <symbolinfo name=\"picture_in_picture_large\" entity=\"f54f\"/>\n    <symbolinfo name=\"picture_in_picture_medium\" entity=\"f54e\"/>\n    <symbolinfo name=\"picture_in_picture_small\" entity=\"f54d\"/>\n    <symbolinfo name=\"pie_chart\" entity=\"f0da\"/>\n    <symbolinfo name=\"pie_chart_filled\" entity=\"f0da\"/>\n    <symbolinfo name=\"pie_chart_outline\" entity=\"f0da\"/>\n    <symbolinfo name=\"pie_chart_outlined\" entity=\"f0da\"/>\n    <symbolinfo name=\"pill\" entity=\"e11f\"/>\n    <symbolinfo name=\"pill_off\" entity=\"f809\"/>\n    <symbolinfo name=\"pin\" entity=\"f045\"/>\n    <symbolinfo name=\"pin_drop\" entity=\"e55e\"/>\n    <symbolinfo name=\"pin_end\" entity=\"e767\"/>\n    <symbolinfo name=\"pin_invoke\" entity=\"e763\"/>\n    <symbolinfo name=\"pinch\" entity=\"eb38\"/>\n    <symbolinfo name=\"pinch_zoom_in\" entity=\"f1fa\"/>\n    <symbolinfo name=\"pinch_zoom_out\" entity=\"f1fb\"/>\n    <symbolinfo name=\"pip\" entity=\"f64d\"/>\n    <symbolinfo name=\"pip_exit\" entity=\"f70d\"/>\n    <symbolinfo name=\"pivot_table_chart\" entity=\"e9ce\"/>\n    <symbolinfo name=\"place\" entity=\"f1db\"/>\n    <symbolinfo name=\"place_item\" entity=\"f1f0\"/>\n    <symbolinfo name=\"plagiarism\" entity=\"ea5a\"/>\n    <symbolinfo name=\"planner_banner_ad_pt\" entity=\"e692\"/>\n    <symbolinfo name=\"play_arrow\" entity=\"e037\"/>\n    <symbolinfo name=\"play_circle\" entity=\"e1c4\"/>\n    <symbolinfo name=\"play_disabled\" entity=\"ef6a\"/>\n    <symbolinfo name=\"play_for_work\" entity=\"e906\"/>\n    <symbolinfo name=\"play_lesson\" entity=\"f047\"/>\n    <symbolinfo name=\"play_music\" entity=\"e6ee\"/>\n    <symbolinfo name=\"play_pause\" entity=\"f137\"/>\n    <symbolinfo name=\"play_shapes\" entity=\"f7fc\"/>\n    <symbolinfo name=\"playing_cards\" entity=\"f5dc\"/>\n    <symbolinfo name=\"playlist_add\" entity=\"e03b\"/>\n    <symbolinfo name=\"playlist_add_check\" entity=\"e065\"/>\n    <symbolinfo name=\"playlist_add_check_circle\" entity=\"e7e6\"/>\n    <symbolinfo name=\"playlist_add_circle\" entity=\"e7e5\"/>\n    <symbolinfo name=\"playlist_play\" entity=\"e05f\"/>\n    <symbolinfo name=\"playlist_remove\" entity=\"eb80\"/>\n    <symbolinfo name=\"plumbing\" entity=\"f107\"/>\n    <symbolinfo name=\"plus_one\" entity=\"e800\"/>\n    <symbolinfo name=\"podcasts\" entity=\"f048\"/>\n    <symbolinfo name=\"podiatry\" entity=\"e120\"/>\n    <symbolinfo name=\"podium\" entity=\"f7fb\"/>\n    <symbolinfo name=\"point_of_sale\" entity=\"f17e\"/>\n    <symbolinfo name=\"point_scan\" entity=\"f70c\"/>\n    <symbolinfo name=\"policy\" entity=\"ea17\"/>\n    <symbolinfo name=\"poll\" entity=\"f0cc\"/>\n    <symbolinfo name=\"polyline\" entity=\"ebbb\"/>\n    <symbolinfo name=\"polymer\" entity=\"e8ab\"/>\n    <symbolinfo name=\"pool\" entity=\"eb48\"/>\n    <symbolinfo name=\"portable_wifi_off\" entity=\"f087\"/>\n    <symbolinfo name=\"portrait\" entity=\"e851\"/>\n    <symbolinfo name=\"position_bottom_left\" entity=\"f70b\"/>\n    <symbolinfo name=\"position_bottom_right\" entity=\"f70a\"/>\n    <symbolinfo name=\"position_top_right\" entity=\"f709\"/>\n    <symbolinfo name=\"post\" entity=\"e705\"/>\n    <symbolinfo name=\"post_add\" entity=\"ea20\"/>\n    <symbolinfo name=\"potted_plant\" entity=\"f8aa\"/>\n    <symbolinfo name=\"power\" entity=\"e63c\"/>\n    <symbolinfo name=\"power_input\" entity=\"e336\"/>\n    <symbolinfo name=\"power_off\" entity=\"e646\"/>\n    <symbolinfo name=\"power_rounded\" entity=\"f8c7\"/>\n    <symbolinfo name=\"power_settings_new\" entity=\"f8c7\"/>\n    <symbolinfo name=\"prayer_times\" entity=\"f838\"/>\n    <symbolinfo name=\"precision_manufacturing\" entity=\"f049\"/>\n    <symbolinfo name=\"pregnancy\" entity=\"f5f1\"/>\n    <symbolinfo name=\"pregnant_woman\" entity=\"f5f1\"/>\n    <symbolinfo name=\"preliminary\" entity=\"e7d8\"/>\n    <symbolinfo name=\"prescriptions\" entity=\"e121\"/>\n    <symbolinfo name=\"present_to_all\" entity=\"e0df\"/>\n    <symbolinfo name=\"preview\" entity=\"f1c5\"/>\n    <symbolinfo name=\"preview_off\" entity=\"f7af\"/>\n    <symbolinfo name=\"price_change\" entity=\"f04a\"/>\n    <symbolinfo name=\"price_check\" entity=\"f04b\"/>\n    <symbolinfo name=\"print\" entity=\"e8ad\"/>\n    <symbolinfo name=\"print_add\" entity=\"f7a2\"/>\n    <symbolinfo name=\"print_connect\" entity=\"f7a1\"/>\n    <symbolinfo name=\"print_disabled\" entity=\"e9cf\"/>\n    <symbolinfo name=\"print_error\" entity=\"f7a0\"/>\n    <symbolinfo name=\"print_lock\" entity=\"f651\"/>\n    <symbolinfo name=\"priority\" entity=\"e19f\"/>\n    <symbolinfo name=\"priority_high\" entity=\"e645\"/>\n    <symbolinfo name=\"privacy\" entity=\"f148\"/>\n    <symbolinfo name=\"privacy_tip\" entity=\"f0dc\"/>\n    <symbolinfo name=\"private_connectivity\" entity=\"e744\"/>\n    <symbolinfo name=\"problem\" entity=\"e122\"/>\n    <symbolinfo name=\"procedure\" entity=\"e651\"/>\n    <symbolinfo name=\"process_chart\" entity=\"f855\"/>\n    <symbolinfo name=\"production_quantity_limits\" entity=\"e1d1\"/>\n    <symbolinfo name=\"productivity\" entity=\"e296\"/>\n    <symbolinfo name=\"progress_activity\" entity=\"e9d0\"/>\n    <symbolinfo name=\"propane\" entity=\"ec14\"/>\n    <symbolinfo name=\"propane_tank\" entity=\"ec13\"/>\n    <symbolinfo name=\"psychiatry\" entity=\"e123\"/>\n    <symbolinfo name=\"psychology\" entity=\"ea4a\"/>\n    <symbolinfo name=\"psychology_alt\" entity=\"f8ea\"/>\n    <symbolinfo name=\"public\" entity=\"e80b\"/>\n    <symbolinfo name=\"public_off\" entity=\"f1ca\"/>\n    <symbolinfo name=\"publish\" entity=\"e255\"/>\n    <symbolinfo name=\"published_with_changes\" entity=\"f232\"/>\n    <symbolinfo name=\"pulmonology\" entity=\"e124\"/>\n    <symbolinfo name=\"punch_clock\" entity=\"eaa8\"/>\n    <symbolinfo name=\"push_pin\" entity=\"f10d\"/>\n    <symbolinfo name=\"qr_code\" entity=\"ef6b\"/>\n    <symbolinfo name=\"qr_code_2\" entity=\"e00a\"/>\n    <symbolinfo name=\"qr_code_2_add\" entity=\"f658\"/>\n    <symbolinfo name=\"qr_code_scanner\" entity=\"f206\"/>\n    <symbolinfo name=\"query_builder\" entity=\"efd6\"/>\n    <symbolinfo name=\"query_stats\" entity=\"e4fc\"/>\n    <symbolinfo name=\"question_answer\" entity=\"e8af\"/>\n    <symbolinfo name=\"question_exchange\" entity=\"f7f3\"/>\n    <symbolinfo name=\"question_mark\" entity=\"eb8b\"/>\n    <symbolinfo name=\"queue\" entity=\"e03c\"/>\n    <symbolinfo name=\"queue_music\" entity=\"e03d\"/>\n    <symbolinfo name=\"queue_play_next\" entity=\"e066\"/>\n    <symbolinfo name=\"quick_phrases\" entity=\"e7d1\"/>\n    <symbolinfo name=\"quick_reference\" entity=\"e46e\"/>\n    <symbolinfo name=\"quick_reference_all\" entity=\"f801\"/>\n    <symbolinfo name=\"quickreply\" entity=\"ef6c\"/>\n    <symbolinfo name=\"quiet_time\" entity=\"e1f9\"/>\n    <symbolinfo name=\"quiet_time_active\" entity=\"e291\"/>\n    <symbolinfo name=\"quiz\" entity=\"f04c\"/>\n    <symbolinfo name=\"r_mobiledata\" entity=\"f04d\"/>\n    <symbolinfo name=\"radar\" entity=\"f04e\"/>\n    <symbolinfo name=\"radio\" entity=\"e03e\"/>\n    <symbolinfo name=\"radio_button_checked\" entity=\"e837\"/>\n    <symbolinfo name=\"radio_button_partial\" entity=\"f560\"/>\n    <symbolinfo name=\"radio_button_unchecked\" entity=\"e836\"/>\n    <symbolinfo name=\"radiology\" entity=\"e125\"/>\n    <symbolinfo name=\"railway_alert\" entity=\"e9d1\"/>\n    <symbolinfo name=\"rainy\" entity=\"f176\"/>\n    <symbolinfo name=\"rainy_heavy\" entity=\"f61f\"/>\n    <symbolinfo name=\"rainy_light\" entity=\"f61e\"/>\n    <symbolinfo name=\"rainy_snow\" entity=\"f61d\"/>\n    <symbolinfo name=\"ramen_dining\" entity=\"ea64\"/>\n    <symbolinfo name=\"ramp_left\" entity=\"eb9c\"/>\n    <symbolinfo name=\"ramp_right\" entity=\"eb96\"/>\n    <symbolinfo name=\"range_hood\" entity=\"e1ea\"/>\n    <symbolinfo name=\"rate_review\" entity=\"e560\"/>\n    <symbolinfo name=\"raven\" entity=\"f555\"/>\n    <symbolinfo name=\"raw_off\" entity=\"f04f\"/>\n    <symbolinfo name=\"raw_on\" entity=\"f050\"/>\n    <symbolinfo name=\"read_more\" entity=\"ef6d\"/>\n    <symbolinfo name=\"readiness_score\" entity=\"f6dd\"/>\n    <symbolinfo name=\"real_estate_agent\" entity=\"e73a\"/>\n    <symbolinfo name=\"rear_camera\" entity=\"f6c2\"/>\n    <symbolinfo name=\"rebase\" entity=\"f845\"/>\n    <symbolinfo name=\"rebase_edit\" entity=\"f846\"/>\n    <symbolinfo name=\"receipt\" entity=\"e8b0\"/>\n    <symbolinfo name=\"receipt_long\" entity=\"ef6e\"/>\n    <symbolinfo name=\"recent_actors\" entity=\"e03f\"/>\n    <symbolinfo name=\"recent_patient\" entity=\"f808\"/>\n    <symbolinfo name=\"recommend\" entity=\"e9d2\"/>\n    <symbolinfo name=\"record_voice_over\" entity=\"e91f\"/>\n    <symbolinfo name=\"rectangle\" entity=\"eb54\"/>\n    <symbolinfo name=\"recycling\" entity=\"e760\"/>\n    <symbolinfo name=\"redeem\" entity=\"e8f6\"/>\n    <symbolinfo name=\"redo\" entity=\"e15a\"/>\n    <symbolinfo name=\"reduce_capacity\" entity=\"f21c\"/>\n    <symbolinfo name=\"refresh\" entity=\"e5d5\"/>\n    <symbolinfo name=\"regular_expression\" entity=\"f750\"/>\n    <symbolinfo name=\"relax\" entity=\"f6dc\"/>\n    <symbolinfo name=\"release_alert\" entity=\"f654\"/>\n    <symbolinfo name=\"remember_me\" entity=\"f051\"/>\n    <symbolinfo name=\"reminder\" entity=\"e6c6\"/>\n    <symbolinfo name=\"reminders_alt\" entity=\"e6c6\"/>\n    <symbolinfo name=\"remote_gen\" entity=\"e83e\"/>\n    <symbolinfo name=\"remove\" entity=\"e15b\"/>\n    <symbolinfo name=\"remove_circle\" entity=\"f08f\"/>\n    <symbolinfo name=\"remove_circle_outline\" entity=\"f08f\"/>\n    <symbolinfo name=\"remove_done\" entity=\"e9d3\"/>\n    <symbolinfo name=\"remove_from_queue\" entity=\"e067\"/>\n    <symbolinfo name=\"remove_moderator\" entity=\"e9d4\"/>\n    <symbolinfo name=\"remove_red_eye\" entity=\"e8f4\"/>\n    <symbolinfo name=\"remove_road\" entity=\"ebfc\"/>\n    <symbolinfo name=\"remove_selection\" entity=\"e9d5\"/>\n    <symbolinfo name=\"remove_shopping_cart\" entity=\"e928\"/>\n    <symbolinfo name=\"reopen_window\" entity=\"f708\"/>\n    <symbolinfo name=\"reorder\" entity=\"e8fe\"/>\n    <symbolinfo name=\"repartition\" entity=\"f8e8\"/>\n    <symbolinfo name=\"repeat\" entity=\"e040\"/>\n    <symbolinfo name=\"repeat_on\" entity=\"e9d6\"/>\n    <symbolinfo name=\"repeat_one\" entity=\"e041\"/>\n    <symbolinfo name=\"repeat_one_on\" entity=\"e9d7\"/>\n    <symbolinfo name=\"replay\" entity=\"e042\"/>\n    <symbolinfo name=\"replay_10\" entity=\"e059\"/>\n    <symbolinfo name=\"replay_30\" entity=\"e05a\"/>\n    <symbolinfo name=\"replay_5\" entity=\"e05b\"/>\n    <symbolinfo name=\"replay_circle_filled\" entity=\"e9d8\"/>\n    <symbolinfo name=\"reply\" entity=\"e15e\"/>\n    <symbolinfo name=\"reply_all\" entity=\"e15f\"/>\n    <symbolinfo name=\"report\" entity=\"f052\"/>\n    <symbolinfo name=\"report_gmailerrorred\" entity=\"f052\"/>\n    <symbolinfo name=\"report_off\" entity=\"e170\"/>\n    <symbolinfo name=\"report_problem\" entity=\"f083\"/>\n    <symbolinfo name=\"request_page\" entity=\"f22c\"/>\n    <symbolinfo name=\"request_quote\" entity=\"f1b6\"/>\n    <symbolinfo name=\"reset_image\" entity=\"f824\"/>\n    <symbolinfo name=\"reset_tv\" entity=\"e9d9\"/>\n    <symbolinfo name=\"reset_wrench\" entity=\"f56c\"/>\n    <symbolinfo name=\"resize\" entity=\"f707\"/>\n    <symbolinfo name=\"respiratory_rate\" entity=\"e127\"/>\n    <symbolinfo name=\"restart_alt\" entity=\"f053\"/>\n    <symbolinfo name=\"restaurant\" entity=\"e56c\"/>\n    <symbolinfo name=\"restaurant_menu\" entity=\"e561\"/>\n    <symbolinfo name=\"restore\" entity=\"e8b3\"/>\n    <symbolinfo name=\"restore_from_trash\" entity=\"e938\"/>\n    <symbolinfo name=\"restore_page\" entity=\"e929\"/>\n    <symbolinfo name=\"resume\" entity=\"f7d0\"/>\n    <symbolinfo name=\"reviews\" entity=\"f07c\"/>\n    <symbolinfo name=\"rewarded_ads\" entity=\"efb6\"/>\n    <symbolinfo name=\"rheumatology\" entity=\"e128\"/>\n    <symbolinfo name=\"rib_cage\" entity=\"f898\"/>\n    <symbolinfo name=\"rice_bowl\" entity=\"f1f5\"/>\n    <symbolinfo name=\"right_click\" entity=\"f706\"/>\n    <symbolinfo name=\"right_panel_close\" entity=\"f705\"/>\n    <symbolinfo name=\"right_panel_open\" entity=\"f704\"/>\n    <symbolinfo name=\"ring_volume\" entity=\"f0dd\"/>\n    <symbolinfo name=\"ring_volume_filled\" entity=\"f0dd\"/>\n    <symbolinfo name=\"ripples\" entity=\"e9db\"/>\n    <symbolinfo name=\"robot\" entity=\"f882\"/>\n    <symbolinfo name=\"robot_2\" entity=\"f5d0\"/>\n    <symbolinfo name=\"rocket\" entity=\"eba5\"/>\n    <symbolinfo name=\"rocket_launch\" entity=\"eb9b\"/>\n    <symbolinfo name=\"roller_shades\" entity=\"ec12\"/>\n    <symbolinfo name=\"roller_shades_closed\" entity=\"ec11\"/>\n    <symbolinfo name=\"roller_skating\" entity=\"ebcd\"/>\n    <symbolinfo name=\"roofing\" entity=\"f201\"/>\n    <symbolinfo name=\"room\" entity=\"f1db\"/>\n    <symbolinfo name=\"room_preferences\" entity=\"f1b8\"/>\n    <symbolinfo name=\"room_service\" entity=\"eb49\"/>\n    <symbolinfo name=\"rotate_90_degrees_ccw\" entity=\"e418\"/>\n    <symbolinfo name=\"rotate_90_degrees_cw\" entity=\"eaab\"/>\n    <symbolinfo name=\"rotate_left\" entity=\"e419\"/>\n    <symbolinfo name=\"rotate_right\" entity=\"e41a\"/>\n    <symbolinfo name=\"roundabout_left\" entity=\"eb99\"/>\n    <symbolinfo name=\"roundabout_right\" entity=\"eba3\"/>\n    <symbolinfo name=\"rounded_corner\" entity=\"e920\"/>\n    <symbolinfo name=\"route\" entity=\"eacd\"/>\n    <symbolinfo name=\"router\" entity=\"e328\"/>\n    <symbolinfo name=\"routine\" entity=\"e20c\"/>\n    <symbolinfo name=\"rowing\" entity=\"e921\"/>\n    <symbolinfo name=\"rss_feed\" entity=\"e0e5\"/>\n    <symbolinfo name=\"rsvp\" entity=\"f055\"/>\n    <symbolinfo name=\"rtt\" entity=\"e9ad\"/>\n    <symbolinfo name=\"rule\" entity=\"f1c2\"/>\n    <symbolinfo name=\"rule_folder\" entity=\"f1c9\"/>\n    <symbolinfo name=\"rule_settings\" entity=\"f64c\"/>\n    <symbolinfo name=\"run_circle\" entity=\"ef6f\"/>\n    <symbolinfo name=\"running_with_errors\" entity=\"e51d\"/>\n    <symbolinfo name=\"rv_hookup\" entity=\"e642\"/>\n    <symbolinfo name=\"safety_check\" entity=\"ebef\"/>\n    <symbolinfo name=\"safety_check_off\" entity=\"f59d\"/>\n    <symbolinfo name=\"safety_divider\" entity=\"e1cc\"/>\n    <symbolinfo name=\"sailing\" entity=\"e502\"/>\n    <symbolinfo name=\"salinity\" entity=\"f876\"/>\n    <symbolinfo name=\"sanitizer\" entity=\"f21d\"/>\n    <symbolinfo name=\"satellite\" entity=\"e562\"/>\n    <symbolinfo name=\"satellite_alt\" entity=\"eb3a\"/>\n    <symbolinfo name=\"sauna\" entity=\"f6f7\"/>\n    <symbolinfo name=\"save\" entity=\"e161\"/>\n    <symbolinfo name=\"save_alt\" entity=\"f090\"/>\n    <symbolinfo name=\"save_as\" entity=\"eb60\"/>\n    <symbolinfo name=\"saved_search\" entity=\"ea11\"/>\n    <symbolinfo name=\"savings\" entity=\"e2eb\"/>\n    <symbolinfo name=\"scale\" entity=\"eb5f\"/>\n    <symbolinfo name=\"scan\" entity=\"f74e\"/>\n    <symbolinfo name=\"scan_delete\" entity=\"f74f\"/>\n    <symbolinfo name=\"scanner\" entity=\"e329\"/>\n    <symbolinfo name=\"scatter_plot\" entity=\"e268\"/>\n    <symbolinfo name=\"scene\" entity=\"e2a7\"/>\n    <symbolinfo name=\"schedule\" entity=\"efd6\"/>\n    <symbolinfo name=\"schedule_send\" entity=\"ea0a\"/>\n    <symbolinfo name=\"schema\" entity=\"e4fd\"/>\n    <symbolinfo name=\"school\" entity=\"e80c\"/>\n    <symbolinfo name=\"science\" entity=\"ea4b\"/>\n    <symbolinfo name=\"score\" entity=\"e269\"/>\n    <symbolinfo name=\"scoreboard\" entity=\"ebd0\"/>\n    <symbolinfo name=\"screen_lock_landscape\" entity=\"e1be\"/>\n    <symbolinfo name=\"screen_lock_portrait\" entity=\"e1bf\"/>\n    <symbolinfo name=\"screen_lock_rotation\" entity=\"e1c0\"/>\n    <symbolinfo name=\"screen_record\" entity=\"f679\"/>\n    <symbolinfo name=\"screen_rotation\" entity=\"e1c1\"/>\n    <symbolinfo name=\"screen_rotation_alt\" entity=\"ebee\"/>\n    <symbolinfo name=\"screen_rotation_up\" entity=\"f678\"/>\n    <symbolinfo name=\"screen_search_desktop\" entity=\"ef70\"/>\n    <symbolinfo name=\"screen_share\" entity=\"e0e2\"/>\n    <symbolinfo name=\"screenshot\" entity=\"f056\"/>\n    <symbolinfo name=\"screenshot_frame\" entity=\"f677\"/>\n    <symbolinfo name=\"screenshot_keyboard\" entity=\"f7d3\"/>\n    <symbolinfo name=\"screenshot_monitor\" entity=\"ec08\"/>\n    <symbolinfo name=\"screenshot_region\" entity=\"f7d2\"/>\n    <symbolinfo name=\"screenshot_tablet\" entity=\"f697\"/>\n    <symbolinfo name=\"scrollable_header\" entity=\"e9dc\"/>\n    <symbolinfo name=\"scuba_diving\" entity=\"ebce\"/>\n    <symbolinfo name=\"sd\" entity=\"e9dd\"/>\n    <symbolinfo name=\"sd_card\" entity=\"e623\"/>\n    <symbolinfo name=\"sd_card_alert\" entity=\"f057\"/>\n    <symbolinfo name=\"sd_storage\" entity=\"e623\"/>\n    <symbolinfo name=\"search\" entity=\"e8b6\"/>\n    <symbolinfo name=\"search_check\" entity=\"f800\"/>\n    <symbolinfo name=\"search_off\" entity=\"ea76\"/>\n    <symbolinfo name=\"security\" entity=\"e32a\"/>\n    <symbolinfo name=\"security_update\" entity=\"f072\"/>\n    <symbolinfo name=\"security_update_good\" entity=\"f073\"/>\n    <symbolinfo name=\"security_update_warning\" entity=\"f074\"/>\n    <symbolinfo name=\"segment\" entity=\"e94b\"/>\n    <symbolinfo name=\"select\" entity=\"f74d\"/>\n    <symbolinfo name=\"select_all\" entity=\"e162\"/>\n    <symbolinfo name=\"select_check_box\" entity=\"f1fe\"/>\n    <symbolinfo name=\"select_to_speak\" entity=\"f7cf\"/>\n    <symbolinfo name=\"select_window\" entity=\"e6fa\"/>\n    <symbolinfo name=\"select_window_off\" entity=\"e506\"/>\n    <symbolinfo name=\"self_care\" entity=\"f86d\"/>\n    <symbolinfo name=\"self_improvement\" entity=\"ea78\"/>\n    <symbolinfo name=\"sell\" entity=\"f05b\"/>\n    <symbolinfo name=\"send\" entity=\"e163\"/>\n    <symbolinfo name=\"send_and_archive\" entity=\"ea0c\"/>\n    <symbolinfo name=\"send_money\" entity=\"e8b7\"/>\n    <symbolinfo name=\"send_time_extension\" entity=\"eadb\"/>\n    <symbolinfo name=\"send_to_mobile\" entity=\"f05c\"/>\n    <symbolinfo name=\"sensor_door\" entity=\"f1b5\"/>\n    <symbolinfo name=\"sensor_occupied\" entity=\"ec10\"/>\n    <symbolinfo name=\"sensor_window\" entity=\"f1b4\"/>\n    <symbolinfo name=\"sensors\" entity=\"e51e\"/>\n    <symbolinfo name=\"sensors_krx\" entity=\"f556\"/>\n    <symbolinfo name=\"sensors_off\" entity=\"e51f\"/>\n    <symbolinfo name=\"sentiment_calm\" entity=\"f6a7\"/>\n    <symbolinfo name=\"sentiment_content\" entity=\"f6a6\"/>\n    <symbolinfo name=\"sentiment_dissatisfied\" entity=\"e811\"/>\n    <symbolinfo name=\"sentiment_excited\" entity=\"f6a5\"/>\n    <symbolinfo name=\"sentiment_extremely_dissatisfied\" entity=\"f194\"/>\n    <symbolinfo name=\"sentiment_frustrated\" entity=\"f6a4\"/>\n    <symbolinfo name=\"sentiment_neutral\" entity=\"e812\"/>\n    <symbolinfo name=\"sentiment_sad\" entity=\"f6a3\"/>\n    <symbolinfo name=\"sentiment_satisfied\" entity=\"e813\"/>\n    <symbolinfo name=\"sentiment_satisfied_alt\" entity=\"e813\"/>\n    <symbolinfo name=\"sentiment_stressed\" entity=\"f6a2\"/>\n    <symbolinfo name=\"sentiment_very_dissatisfied\" entity=\"e814\"/>\n    <symbolinfo name=\"sentiment_very_satisfied\" entity=\"e815\"/>\n    <symbolinfo name=\"sentiment_worried\" entity=\"f6a1\"/>\n    <symbolinfo name=\"set_meal\" entity=\"f1ea\"/>\n    <symbolinfo name=\"settings\" entity=\"e8b8\"/>\n    <symbolinfo name=\"settings_accessibility\" entity=\"f05d\"/>\n    <symbolinfo name=\"settings_account_box\" entity=\"f835\"/>\n    <symbolinfo name=\"settings_alert\" entity=\"f143\"/>\n    <symbolinfo name=\"settings_applications\" entity=\"e8b9\"/>\n    <symbolinfo name=\"settings_b_roll\" entity=\"f625\"/>\n    <symbolinfo name=\"settings_backup_restore\" entity=\"e8ba\"/>\n    <symbolinfo name=\"settings_bluetooth\" entity=\"e8bb\"/>\n    <symbolinfo name=\"settings_brightness\" entity=\"e8bd\"/>\n    <symbolinfo name=\"settings_cell\" entity=\"e8bc\"/>\n    <symbolinfo name=\"settings_cinematic_blur\" entity=\"f624\"/>\n    <symbolinfo name=\"settings_ethernet\" entity=\"e8be\"/>\n    <symbolinfo name=\"settings_input_antenna\" entity=\"e8bf\"/>\n    <symbolinfo name=\"settings_input_component\" entity=\"e8c1\"/>\n    <symbolinfo name=\"settings_input_composite\" entity=\"e8c1\"/>\n    <symbolinfo name=\"settings_input_hdmi\" entity=\"e8c2\"/>\n    <symbolinfo name=\"settings_input_svideo\" entity=\"e8c3\"/>\n    <symbolinfo name=\"settings_motion_mode\" entity=\"f833\"/>\n    <symbolinfo name=\"settings_night_sight\" entity=\"f832\"/>\n    <symbolinfo name=\"settings_overscan\" entity=\"e8c4\"/>\n    <symbolinfo name=\"settings_panorama\" entity=\"f831\"/>\n    <symbolinfo name=\"settings_phone\" entity=\"e8c5\"/>\n    <symbolinfo name=\"settings_photo_camera\" entity=\"f834\"/>\n    <symbolinfo name=\"settings_power\" entity=\"e8c6\"/>\n    <symbolinfo name=\"settings_remote\" entity=\"e8c7\"/>\n    <symbolinfo name=\"settings_slow_motion\" entity=\"f623\"/>\n    <symbolinfo name=\"settings_suggest\" entity=\"f05e\"/>\n    <symbolinfo name=\"settings_system_daydream\" entity=\"e1c3\"/>\n    <symbolinfo name=\"settings_timelapse\" entity=\"f622\"/>\n    <symbolinfo name=\"settings_video_camera\" entity=\"f621\"/>\n    <symbolinfo name=\"settings_voice\" entity=\"e8c8\"/>\n    <symbolinfo name=\"settop_component\" entity=\"e2ac\"/>\n    <symbolinfo name=\"severe_cold\" entity=\"ebd3\"/>\n    <symbolinfo name=\"shadow\" entity=\"e9df\"/>\n    <symbolinfo name=\"shadow_add\" entity=\"f584\"/>\n    <symbolinfo name=\"shadow_minus\" entity=\"f583\"/>\n    <symbolinfo name=\"shape_line\" entity=\"f8d3\"/>\n    <symbolinfo name=\"shapes\" entity=\"e602\"/>\n    <symbolinfo name=\"share\" entity=\"e80d\"/>\n    <symbolinfo name=\"share_location\" entity=\"f05f\"/>\n    <symbolinfo name=\"share_off\" entity=\"f6cb\"/>\n    <symbolinfo name=\"share_reviews\" entity=\"f8a4\"/>\n    <symbolinfo name=\"share_windows\" entity=\"f613\"/>\n    <symbolinfo name=\"sheets_rtl\" entity=\"f823\"/>\n    <symbolinfo name=\"shelf_auto_hide\" entity=\"f703\"/>\n    <symbolinfo name=\"shelf_position\" entity=\"f702\"/>\n    <symbolinfo name=\"shelves\" entity=\"f86e\"/>\n    <symbolinfo name=\"shield\" entity=\"e9e0\"/>\n    <symbolinfo name=\"shield_lock\" entity=\"f686\"/>\n    <symbolinfo name=\"shield_locked\" entity=\"f592\"/>\n    <symbolinfo name=\"shield_moon\" entity=\"eaa9\"/>\n    <symbolinfo name=\"shield_person\" entity=\"f650\"/>\n    <symbolinfo name=\"shield_spark\" entity=\"f55d\"/>\n    <symbolinfo name=\"shield_with_heart\" entity=\"e78f\"/>\n    <symbolinfo name=\"shield_with_house\" entity=\"e78d\"/>\n    <symbolinfo name=\"shift\" entity=\"e5f2\"/>\n    <symbolinfo name=\"shift_lock\" entity=\"f7ae\"/>\n    <symbolinfo name=\"shop\" entity=\"e8c9\"/>\n    <symbolinfo name=\"shop_2\" entity=\"e8ca\"/>\n    <symbolinfo name=\"shop_two\" entity=\"e8ca\"/>\n    <symbolinfo name=\"shopping_bag\" entity=\"f1cc\"/>\n    <symbolinfo name=\"shopping_basket\" entity=\"e8cb\"/>\n    <symbolinfo name=\"shopping_cart\" entity=\"e8cc\"/>\n    <symbolinfo name=\"shopping_cart_checkout\" entity=\"eb88\"/>\n    <symbolinfo name=\"short_stay\" entity=\"e4d0\"/>\n    <symbolinfo name=\"short_text\" entity=\"e261\"/>\n    <symbolinfo name=\"shortcut\" entity=\"f57a\"/>\n    <symbolinfo name=\"show_chart\" entity=\"e6e1\"/>\n    <symbolinfo name=\"shower\" entity=\"f061\"/>\n    <symbolinfo name=\"shuffle\" entity=\"e043\"/>\n    <symbolinfo name=\"shuffle_on\" entity=\"e9e1\"/>\n    <symbolinfo name=\"shutter_speed\" entity=\"e43d\"/>\n    <symbolinfo name=\"shutter_speed_add\" entity=\"f57e\"/>\n    <symbolinfo name=\"shutter_speed_minus\" entity=\"f57d\"/>\n    <symbolinfo name=\"sick\" entity=\"f220\"/>\n    <symbolinfo name=\"side_navigation\" entity=\"e9e2\"/>\n    <symbolinfo name=\"sign_language\" entity=\"ebe5\"/>\n    <symbolinfo name=\"signal_cellular_0_bar\" entity=\"f0a8\"/>\n    <symbolinfo name=\"signal_cellular_1_bar\" entity=\"f0a9\"/>\n    <symbolinfo name=\"signal_cellular_2_bar\" entity=\"f0aa\"/>\n    <symbolinfo name=\"signal_cellular_3_bar\" entity=\"f0ab\"/>\n    <symbolinfo name=\"signal_cellular_4_bar\" entity=\"e1c8\"/>\n    <symbolinfo name=\"signal_cellular_add\" entity=\"f7a9\"/>\n    <symbolinfo name=\"signal_cellular_alt\" entity=\"e202\"/>\n    <symbolinfo name=\"signal_cellular_alt_1_bar\" entity=\"ebdf\"/>\n    <symbolinfo name=\"signal_cellular_alt_2_bar\" entity=\"ebe3\"/>\n    <symbolinfo name=\"signal_cellular_connected_no_internet_0_bar\" entity=\"f0ac\"/>\n    <symbolinfo name=\"signal_cellular_connected_no_internet_4_bar\" entity=\"e1cd\"/>\n    <symbolinfo name=\"signal_cellular_no_sim\" entity=\"e1ce\"/>\n    <symbolinfo name=\"signal_cellular_nodata\" entity=\"f062\"/>\n    <symbolinfo name=\"signal_cellular_null\" entity=\"e1cf\"/>\n    <symbolinfo name=\"signal_cellular_off\" entity=\"e1d0\"/>\n    <symbolinfo name=\"signal_cellular_pause\" entity=\"f5a7\"/>\n    <symbolinfo name=\"signal_disconnected\" entity=\"f239\"/>\n    <symbolinfo name=\"signal_wifi_0_bar\" entity=\"f0b0\"/>\n    <symbolinfo name=\"signal_wifi_4_bar\" entity=\"f065\"/>\n    <symbolinfo name=\"signal_wifi_4_bar_lock\" entity=\"e1e1\"/>\n    <symbolinfo name=\"signal_wifi_bad\" entity=\"f064\"/>\n    <symbolinfo name=\"signal_wifi_connected_no_internet_4\" entity=\"f064\"/>\n    <symbolinfo name=\"signal_wifi_off\" entity=\"e1da\"/>\n    <symbolinfo name=\"signal_wifi_statusbar_4_bar\" entity=\"f065\"/>\n    <symbolinfo name=\"signal_wifi_statusbar_not_connected\" entity=\"f0ef\"/>\n    <symbolinfo name=\"signal_wifi_statusbar_null\" entity=\"f067\"/>\n    <symbolinfo name=\"signature\" entity=\"f74c\"/>\n    <symbolinfo name=\"signpost\" entity=\"eb91\"/>\n    <symbolinfo name=\"sim_card\" entity=\"e32b\"/>\n    <symbolinfo name=\"sim_card_alert\" entity=\"f057\"/>\n    <symbolinfo name=\"sim_card_download\" entity=\"f068\"/>\n    <symbolinfo name=\"single_bed\" entity=\"ea48\"/>\n    <symbolinfo name=\"sip\" entity=\"f069\"/>\n    <symbolinfo name=\"skateboarding\" entity=\"e511\"/>\n    <symbolinfo name=\"skeleton\" entity=\"f899\"/>\n    <symbolinfo name=\"skip_next\" entity=\"e044\"/>\n    <symbolinfo name=\"skip_previous\" entity=\"e045\"/>\n    <symbolinfo name=\"skull\" entity=\"f89a\"/>\n    <symbolinfo name=\"sledding\" entity=\"e512\"/>\n    <symbolinfo name=\"sleep\" entity=\"e213\"/>\n    <symbolinfo name=\"sleep_score\" entity=\"f6b7\"/>\n    <symbolinfo name=\"slide_library\" entity=\"f822\"/>\n    <symbolinfo name=\"sliders\" entity=\"e9e3\"/>\n    <symbolinfo name=\"slideshow\" entity=\"e41b\"/>\n    <symbolinfo name=\"slow_motion_video\" entity=\"e068\"/>\n    <symbolinfo name=\"smart_button\" entity=\"f1c1\"/>\n    <symbolinfo name=\"smart_display\" entity=\"f06a\"/>\n    <symbolinfo name=\"smart_outlet\" entity=\"e844\"/>\n    <symbolinfo name=\"smart_screen\" entity=\"f06b\"/>\n    <symbolinfo name=\"smart_toy\" entity=\"f06c\"/>\n    <symbolinfo name=\"smart_ventilation\" entity=\"f55c\"/>\n    <symbolinfo name=\"smartphone\" entity=\"e32c\"/>\n    <symbolinfo name=\"smb_share\" entity=\"f74b\"/>\n    <symbolinfo name=\"smoke_free\" entity=\"eb4a\"/>\n    <symbolinfo name=\"smoking_rooms\" entity=\"eb4b\"/>\n    <symbolinfo name=\"sms\" entity=\"e625\"/>\n    <symbolinfo name=\"sms_failed\" entity=\"e87f\"/>\n    <symbolinfo name=\"snippet_folder\" entity=\"f1c7\"/>\n    <symbolinfo name=\"snooze\" entity=\"e046\"/>\n    <symbolinfo name=\"snowboarding\" entity=\"e513\"/>\n    <symbolinfo name=\"snowing\" entity=\"e80f\"/>\n    <symbolinfo name=\"snowing_heavy\" entity=\"f61c\"/>\n    <symbolinfo name=\"snowmobile\" entity=\"e503\"/>\n    <symbolinfo name=\"snowshoeing\" entity=\"e514\"/>\n    <symbolinfo name=\"soap\" entity=\"f1b2\"/>\n    <symbolinfo name=\"social_distance\" entity=\"e1cb\"/>\n    <symbolinfo name=\"social_leaderboard\" entity=\"f6a0\"/>\n    <symbolinfo name=\"solar_power\" entity=\"ec0f\"/>\n    <symbolinfo name=\"sort\" entity=\"e164\"/>\n    <symbolinfo name=\"sort_by_alpha\" entity=\"e053\"/>\n    <symbolinfo name=\"sos\" entity=\"ebf7\"/>\n    <symbolinfo name=\"sound_detection_dog_barking\" entity=\"f149\"/>\n    <symbolinfo name=\"sound_detection_glass_break\" entity=\"f14a\"/>\n    <symbolinfo name=\"sound_detection_loud_sound\" entity=\"f14b\"/>\n    <symbolinfo name=\"sound_sampler\" entity=\"f6b4\"/>\n    <symbolinfo name=\"soup_kitchen\" entity=\"e7d3\"/>\n    <symbolinfo name=\"source\" entity=\"f1c8\"/>\n    <symbolinfo name=\"source_notes\" entity=\"e12d\"/>\n    <symbolinfo name=\"south\" entity=\"f1e3\"/>\n    <symbolinfo name=\"south_america\" entity=\"e7e4\"/>\n    <symbolinfo name=\"south_east\" entity=\"f1e4\"/>\n    <symbolinfo name=\"south_west\" entity=\"f1e5\"/>\n    <symbolinfo name=\"spa\" entity=\"eb4c\"/>\n    <symbolinfo name=\"space_bar\" entity=\"e256\"/>\n    <symbolinfo name=\"space_dashboard\" entity=\"e66b\"/>\n    <symbolinfo name=\"spatial_audio\" entity=\"ebeb\"/>\n    <symbolinfo name=\"spatial_audio_off\" entity=\"ebe8\"/>\n    <symbolinfo name=\"spatial_tracking\" entity=\"ebea\"/>\n    <symbolinfo name=\"speaker\" entity=\"e32d\"/>\n    <symbolinfo name=\"speaker_group\" entity=\"e32e\"/>\n    <symbolinfo name=\"speaker_notes\" entity=\"e8cd\"/>\n    <symbolinfo name=\"speaker_notes_off\" entity=\"e92a\"/>\n    <symbolinfo name=\"speaker_phone\" entity=\"e0d2\"/>\n    <symbolinfo name=\"special_character\" entity=\"f74a\"/>\n    <symbolinfo name=\"specific_gravity\" entity=\"f872\"/>\n    <symbolinfo name=\"speech_to_text\" entity=\"f8a7\"/>\n    <symbolinfo name=\"speed\" entity=\"e9e4\"/>\n    <symbolinfo name=\"spellcheck\" entity=\"e8ce\"/>\n    <symbolinfo name=\"splitscreen\" entity=\"f06d\"/>\n    <symbolinfo name=\"splitscreen_bottom\" entity=\"f676\"/>\n    <symbolinfo name=\"splitscreen_left\" entity=\"f675\"/>\n    <symbolinfo name=\"splitscreen_right\" entity=\"f674\"/>\n    <symbolinfo name=\"splitscreen_top\" entity=\"f673\"/>\n    <symbolinfo name=\"spo2\" entity=\"f6db\"/>\n    <symbolinfo name=\"spoke\" entity=\"e9a7\"/>\n    <symbolinfo name=\"sports\" entity=\"ea30\"/>\n    <symbolinfo name=\"sports_bar\" entity=\"f1f3\"/>\n    <symbolinfo name=\"sports_baseball\" entity=\"ea51\"/>\n    <symbolinfo name=\"sports_basketball\" entity=\"ea26\"/>\n    <symbolinfo name=\"sports_cricket\" entity=\"ea27\"/>\n    <symbolinfo name=\"sports_esports\" entity=\"ea28\"/>\n    <symbolinfo name=\"sports_football\" entity=\"ea29\"/>\n    <symbolinfo name=\"sports_golf\" entity=\"ea2a\"/>\n    <symbolinfo name=\"sports_gymnastics\" entity=\"ebc4\"/>\n    <symbolinfo name=\"sports_handball\" entity=\"ea33\"/>\n    <symbolinfo name=\"sports_hockey\" entity=\"ea2b\"/>\n    <symbolinfo name=\"sports_kabaddi\" entity=\"ea34\"/>\n    <symbolinfo name=\"sports_martial_arts\" entity=\"eae9\"/>\n    <symbolinfo name=\"sports_mma\" entity=\"ea2c\"/>\n    <symbolinfo name=\"sports_motorsports\" entity=\"ea2d\"/>\n    <symbolinfo name=\"sports_rugby\" entity=\"ea2e\"/>\n    <symbolinfo name=\"sports_score\" entity=\"f06e\"/>\n    <symbolinfo name=\"sports_soccer\" entity=\"ea2f\"/>\n    <symbolinfo name=\"sports_tennis\" entity=\"ea32\"/>\n    <symbolinfo name=\"sports_volleyball\" entity=\"ea31\"/>\n    <symbolinfo name=\"sprinkler\" entity=\"e29a\"/>\n    <symbolinfo name=\"sprint\" entity=\"f81f\"/>\n    <symbolinfo name=\"square\" entity=\"eb36\"/>\n    <symbolinfo name=\"square_foot\" entity=\"ea49\"/>\n    <symbolinfo name=\"ssid_chart\" entity=\"eb66\"/>\n    <symbolinfo name=\"stack\" entity=\"f609\"/>\n    <symbolinfo name=\"stack_off\" entity=\"f608\"/>\n    <symbolinfo name=\"stack_star\" entity=\"f607\"/>\n    <symbolinfo name=\"stacked_bar_chart\" entity=\"e9e6\"/>\n    <symbolinfo name=\"stacked_email\" entity=\"e6c7\"/>\n    <symbolinfo name=\"stacked_inbox\" entity=\"e6c9\"/>\n    <symbolinfo name=\"stacked_line_chart\" entity=\"f22b\"/>\n    <symbolinfo name=\"stadia_controller\" entity=\"f135\"/>\n    <symbolinfo name=\"stadium\" entity=\"eb90\"/>\n    <symbolinfo name=\"stairs\" entity=\"f1a9\"/>\n    <symbolinfo name=\"star\" entity=\"f09a\"/>\n    <symbolinfo name=\"star_border\" entity=\"f09a\"/>\n    <symbolinfo name=\"star_border_purple500\" entity=\"f09a\"/>\n    <symbolinfo name=\"star_half\" entity=\"e839\"/>\n    <symbolinfo name=\"star_outline\" entity=\"f09a\"/>\n    <symbolinfo name=\"star_purple500\" entity=\"f09a\"/>\n    <symbolinfo name=\"star_rate\" entity=\"f0ec\"/>\n    <symbolinfo name=\"star_rate_half\" entity=\"ec45\"/>\n    <symbolinfo name=\"stars\" entity=\"e8d0\"/>\n    <symbolinfo name=\"start\" entity=\"e089\"/>\n    <symbolinfo name=\"stat_1\" entity=\"e698\"/>\n    <symbolinfo name=\"stat_2\" entity=\"e699\"/>\n    <symbolinfo name=\"stat_3\" entity=\"e69a\"/>\n    <symbolinfo name=\"stat_minus_1\" entity=\"e69b\"/>\n    <symbolinfo name=\"stat_minus_2\" entity=\"e69c\"/>\n    <symbolinfo name=\"stat_minus_3\" entity=\"e69d\"/>\n    <symbolinfo name=\"stay_current_landscape\" entity=\"e0d3\"/>\n    <symbolinfo name=\"stay_current_portrait\" entity=\"e0d4\"/>\n    <symbolinfo name=\"stay_primary_landscape\" entity=\"e0d5\"/>\n    <symbolinfo name=\"stay_primary_portrait\" entity=\"e0d6\"/>\n    <symbolinfo name=\"step\" entity=\"f6fe\"/>\n    <symbolinfo name=\"step_into\" entity=\"f701\"/>\n    <symbolinfo name=\"step_out\" entity=\"f700\"/>\n    <symbolinfo name=\"step_over\" entity=\"f6ff\"/>\n    <symbolinfo name=\"steppers\" entity=\"e9e7\"/>\n    <symbolinfo name=\"steps\" entity=\"f6da\"/>\n    <symbolinfo name=\"stethoscope\" entity=\"f805\"/>\n    <symbolinfo name=\"stethoscope_arrow\" entity=\"f807\"/>\n    <symbolinfo name=\"stethoscope_check\" entity=\"f806\"/>\n    <symbolinfo name=\"sticky_note\" entity=\"e9e8\"/>\n    <symbolinfo name=\"sticky_note_2\" entity=\"f1fc\"/>\n    <symbolinfo name=\"stock_media\" entity=\"f570\"/>\n    <symbolinfo name=\"stop\" entity=\"e047\"/>\n    <symbolinfo name=\"stop_circle\" entity=\"ef71\"/>\n    <symbolinfo name=\"stop_screen_share\" entity=\"e0e3\"/>\n    <symbolinfo name=\"storage\" entity=\"e1db\"/>\n    <symbolinfo name=\"store\" entity=\"e8d1\"/>\n    <symbolinfo name=\"store_mall_directory\" entity=\"e8d1\"/>\n    <symbolinfo name=\"storefront\" entity=\"ea12\"/>\n    <symbolinfo name=\"storm\" entity=\"f070\"/>\n    <symbolinfo name=\"straight\" entity=\"eb95\"/>\n    <symbolinfo name=\"straighten\" entity=\"e41c\"/>\n    <symbolinfo name=\"strategy\" entity=\"f5df\"/>\n    <symbolinfo name=\"stream\" entity=\"e9e9\"/>\n    <symbolinfo name=\"stream_apps\" entity=\"f79f\"/>\n    <symbolinfo name=\"streetview\" entity=\"e56e\"/>\n    <symbolinfo name=\"stress_management\" entity=\"f6d9\"/>\n    <symbolinfo name=\"strikethrough_s\" entity=\"e257\"/>\n    <symbolinfo name=\"stroke_full\" entity=\"f749\"/>\n    <symbolinfo name=\"stroke_partial\" entity=\"f748\"/>\n    <symbolinfo name=\"stroller\" entity=\"f1ae\"/>\n    <symbolinfo name=\"style\" entity=\"e41d\"/>\n    <symbolinfo name=\"styler\" entity=\"e273\"/>\n    <symbolinfo name=\"stylus\" entity=\"f604\"/>\n    <symbolinfo name=\"stylus_laser_pointer\" entity=\"f747\"/>\n    <symbolinfo name=\"stylus_note\" entity=\"f603\"/>\n    <symbolinfo name=\"subdirectory_arrow_left\" entity=\"e5d9\"/>\n    <symbolinfo name=\"subdirectory_arrow_right\" entity=\"e5da\"/>\n    <symbolinfo name=\"subheader\" entity=\"e9ea\"/>\n    <symbolinfo name=\"subject\" entity=\"e8d2\"/>\n    <symbolinfo name=\"subscript\" entity=\"f111\"/>\n    <symbolinfo name=\"subscriptions\" entity=\"e064\"/>\n    <symbolinfo name=\"subtitles\" entity=\"e048\"/>\n    <symbolinfo name=\"subtitles_off\" entity=\"ef72\"/>\n    <symbolinfo name=\"subway\" entity=\"e56f\"/>\n    <symbolinfo name=\"summarize\" entity=\"f071\"/>\n    <symbolinfo name=\"sunny\" entity=\"e81a\"/>\n    <symbolinfo name=\"sunny_snowing\" entity=\"e819\"/>\n    <symbolinfo name=\"superscript\" entity=\"f112\"/>\n    <symbolinfo name=\"supervised_user_circle\" entity=\"e939\"/>\n    <symbolinfo name=\"supervised_user_circle_off\" entity=\"f60e\"/>\n    <symbolinfo name=\"supervisor_account\" entity=\"e8d3\"/>\n    <symbolinfo name=\"support\" entity=\"ef73\"/>\n    <symbolinfo name=\"support_agent\" entity=\"f0e2\"/>\n    <symbolinfo name=\"surfing\" entity=\"e515\"/>\n    <symbolinfo name=\"surgical\" entity=\"e131\"/>\n    <symbolinfo name=\"surround_sound\" entity=\"e049\"/>\n    <symbolinfo name=\"swap_calls\" entity=\"e0d7\"/>\n    <symbolinfo name=\"swap_driving_apps_wheel\" entity=\"e69f\"/>\n    <symbolinfo name=\"swap_horiz\" entity=\"e8d4\"/>\n    <symbolinfo name=\"swap_horizontal_circle\" entity=\"e933\"/>\n    <symbolinfo name=\"swap_vert\" entity=\"e8d5\"/>\n    <symbolinfo name=\"swap_vertical_circle\" entity=\"e8d6\"/>\n    <symbolinfo name=\"sweep\" entity=\"e6ac\"/>\n    <symbolinfo name=\"swipe\" entity=\"e9ec\"/>\n    <symbolinfo name=\"swipe_down\" entity=\"eb53\"/>\n    <symbolinfo name=\"swipe_down_alt\" entity=\"eb30\"/>\n    <symbolinfo name=\"swipe_left\" entity=\"eb59\"/>\n    <symbolinfo name=\"swipe_left_alt\" entity=\"eb33\"/>\n    <symbolinfo name=\"swipe_right\" entity=\"eb52\"/>\n    <symbolinfo name=\"swipe_right_alt\" entity=\"eb56\"/>\n    <symbolinfo name=\"swipe_up\" entity=\"eb2e\"/>\n    <symbolinfo name=\"swipe_up_alt\" entity=\"eb35\"/>\n    <symbolinfo name=\"swipe_vertical\" entity=\"eb51\"/>\n    <symbolinfo name=\"switch\" entity=\"e1f4\"/>\n    <symbolinfo name=\"switch_access\" entity=\"f6fd\"/>\n    <symbolinfo name=\"switch_access_shortcut\" entity=\"e7e1\"/>\n    <symbolinfo name=\"switch_access_shortcut_add\" entity=\"e7e2\"/>\n    <symbolinfo name=\"switch_account\" entity=\"e9ed\"/>\n    <symbolinfo name=\"switch_camera\" entity=\"e41e\"/>\n    <symbolinfo name=\"switch_left\" entity=\"f1d1\"/>\n    <symbolinfo name=\"switch_right\" entity=\"f1d2\"/>\n    <symbolinfo name=\"switch_video\" entity=\"e41f\"/>\n    <symbolinfo name=\"switches\" entity=\"e733\"/>\n    <symbolinfo name=\"sword_rose\" entity=\"f5de\"/>\n    <symbolinfo name=\"swords\" entity=\"f889\"/>\n    <symbolinfo name=\"symptoms\" entity=\"e132\"/>\n    <symbolinfo name=\"synagogue\" entity=\"eab0\"/>\n    <symbolinfo name=\"sync\" entity=\"e627\"/>\n    <symbolinfo name=\"sync_alt\" entity=\"ea18\"/>\n    <symbolinfo name=\"sync_disabled\" entity=\"e628\"/>\n    <symbolinfo name=\"sync_lock\" entity=\"eaee\"/>\n    <symbolinfo name=\"sync_problem\" entity=\"e629\"/>\n    <symbolinfo name=\"sync_saved_locally\" entity=\"f820\"/>\n    <symbolinfo name=\"syringe\" entity=\"e133\"/>\n    <symbolinfo name=\"system_security_update\" entity=\"f072\"/>\n    <symbolinfo name=\"system_security_update_good\" entity=\"f073\"/>\n    <symbolinfo name=\"system_security_update_warning\" entity=\"f074\"/>\n    <symbolinfo name=\"system_update\" entity=\"f072\"/>\n    <symbolinfo name=\"system_update_alt\" entity=\"e8d7\"/>\n    <symbolinfo name=\"tab\" entity=\"e8d8\"/>\n    <symbolinfo name=\"tab_close\" entity=\"f745\"/>\n    <symbolinfo name=\"tab_close_right\" entity=\"f746\"/>\n    <symbolinfo name=\"tab_duplicate\" entity=\"f744\"/>\n    <symbolinfo name=\"tab_group\" entity=\"f743\"/>\n    <symbolinfo name=\"tab_move\" entity=\"f742\"/>\n    <symbolinfo name=\"tab_new_right\" entity=\"f741\"/>\n    <symbolinfo name=\"tab_recent\" entity=\"f740\"/>\n    <symbolinfo name=\"tab_unselected\" entity=\"e8d9\"/>\n    <symbolinfo name=\"table\" entity=\"f191\"/>\n    <symbolinfo name=\"table_bar\" entity=\"ead2\"/>\n    <symbolinfo name=\"table_chart\" entity=\"e265\"/>\n    <symbolinfo name=\"table_chart_view\" entity=\"f6ef\"/>\n    <symbolinfo name=\"table_lamp\" entity=\"e1f2\"/>\n    <symbolinfo name=\"table_restaurant\" entity=\"eac6\"/>\n    <symbolinfo name=\"table_rows\" entity=\"f101\"/>\n    <symbolinfo name=\"table_rows_narrow\" entity=\"f73f\"/>\n    <symbolinfo name=\"table_view\" entity=\"f1be\"/>\n    <symbolinfo name=\"tablet\" entity=\"e32f\"/>\n    <symbolinfo name=\"tablet_android\" entity=\"e330\"/>\n    <symbolinfo name=\"tablet_mac\" entity=\"e331\"/>\n    <symbolinfo name=\"tabs\" entity=\"e9ee\"/>\n    <symbolinfo name=\"tactic\" entity=\"f564\"/>\n    <symbolinfo name=\"tag\" entity=\"e9ef\"/>\n    <symbolinfo name=\"tag_faces\" entity=\"ea22\"/>\n    <symbolinfo name=\"takeout_dining\" entity=\"ea74\"/>\n    <symbolinfo name=\"tamper_detection_off\" entity=\"e82e\"/>\n    <symbolinfo name=\"tamper_detection_on\" entity=\"f8c8\"/>\n    <symbolinfo name=\"tap_and_play\" entity=\"e62b\"/>\n    <symbolinfo name=\"tapas\" entity=\"f1e9\"/>\n    <symbolinfo name=\"target\" entity=\"e719\"/>\n    <symbolinfo name=\"task\" entity=\"f075\"/>\n    <symbolinfo name=\"task_alt\" entity=\"e2e6\"/>\n    <symbolinfo name=\"taunt\" entity=\"f69f\"/>\n    <symbolinfo name=\"taxi_alert\" entity=\"ef74\"/>\n    <symbolinfo name=\"team_dashboard\" entity=\"e013\"/>\n    <symbolinfo name=\"temp_preferences_custom\" entity=\"f8c9\"/>\n    <symbolinfo name=\"temp_preferences_eco\" entity=\"f8ca\"/>\n    <symbolinfo name=\"temple_buddhist\" entity=\"eab3\"/>\n    <symbolinfo name=\"temple_hindu\" entity=\"eaaf\"/>\n    <symbolinfo name=\"tenancy\" entity=\"f0e3\"/>\n    <symbolinfo name=\"terminal\" entity=\"eb8e\"/>\n    <symbolinfo name=\"terrain\" entity=\"e564\"/>\n    <symbolinfo name=\"text_ad\" entity=\"e728\"/>\n    <symbolinfo name=\"text_decrease\" entity=\"eadd\"/>\n    <symbolinfo name=\"text_fields\" entity=\"e262\"/>\n    <symbolinfo name=\"text_format\" entity=\"e165\"/>\n    <symbolinfo name=\"text_increase\" entity=\"eae2\"/>\n    <symbolinfo name=\"text_rotate_up\" entity=\"e93a\"/>\n    <symbolinfo name=\"text_rotate_vertical\" entity=\"e93b\"/>\n    <symbolinfo name=\"text_rotation_angledown\" entity=\"e93c\"/>\n    <symbolinfo name=\"text_rotation_angleup\" entity=\"e93d\"/>\n    <symbolinfo name=\"text_rotation_down\" entity=\"e93e\"/>\n    <symbolinfo name=\"text_rotation_none\" entity=\"e93f\"/>\n    <symbolinfo name=\"text_select_end\" entity=\"f73e\"/>\n    <symbolinfo name=\"text_select_jump_to_beginning\" entity=\"f73d\"/>\n    <symbolinfo name=\"text_select_jump_to_end\" entity=\"f73c\"/>\n    <symbolinfo name=\"text_select_move_back_character\" entity=\"f73b\"/>\n    <symbolinfo name=\"text_select_move_back_word\" entity=\"f73a\"/>\n    <symbolinfo name=\"text_select_move_down\" entity=\"f739\"/>\n    <symbolinfo name=\"text_select_move_forward_character\" entity=\"f738\"/>\n    <symbolinfo name=\"text_select_move_forward_word\" entity=\"f737\"/>\n    <symbolinfo name=\"text_select_move_up\" entity=\"f736\"/>\n    <symbolinfo name=\"text_select_start\" entity=\"f735\"/>\n    <symbolinfo name=\"text_snippet\" entity=\"f1c6\"/>\n    <symbolinfo name=\"text_to_speech\" entity=\"f1bc\"/>\n    <symbolinfo name=\"textsms\" entity=\"e625\"/>\n    <symbolinfo name=\"texture\" entity=\"e421\"/>\n    <symbolinfo name=\"texture_add\" entity=\"f57c\"/>\n    <symbolinfo name=\"texture_minus\" entity=\"f57b\"/>\n    <symbolinfo name=\"theater_comedy\" entity=\"ea66\"/>\n    <symbolinfo name=\"theaters\" entity=\"e8da\"/>\n    <symbolinfo name=\"thermometer\" entity=\"e846\"/>\n    <symbolinfo name=\"thermometer_add\" entity=\"f582\"/>\n    <symbolinfo name=\"thermometer_gain\" entity=\"f6d8\"/>\n    <symbolinfo name=\"thermometer_loss\" entity=\"f6d7\"/>\n    <symbolinfo name=\"thermometer_minus\" entity=\"f581\"/>\n    <symbolinfo name=\"thermostat\" entity=\"f076\"/>\n    <symbolinfo name=\"thermostat_auto\" entity=\"f077\"/>\n    <symbolinfo name=\"thermostat_carbon\" entity=\"f178\"/>\n    <symbolinfo name=\"thumb_down\" entity=\"f578\"/>\n    <symbolinfo name=\"thumb_down_alt\" entity=\"f578\"/>\n    <symbolinfo name=\"thumb_down_filled\" entity=\"f578\"/>\n    <symbolinfo name=\"thumb_down_off\" entity=\"f578\"/>\n    <symbolinfo name=\"thumb_down_off_alt\" entity=\"f578\"/>\n    <symbolinfo name=\"thumb_up\" entity=\"f577\"/>\n    <symbolinfo name=\"thumb_up_alt\" entity=\"f577\"/>\n    <symbolinfo name=\"thumb_up_filled\" entity=\"f577\"/>\n    <symbolinfo name=\"thumb_up_off\" entity=\"f577\"/>\n    <symbolinfo name=\"thumb_up_off_alt\" entity=\"f577\"/>\n    <symbolinfo name=\"thumbnail_bar\" entity=\"f734\"/>\n    <symbolinfo name=\"thumbs_up_down\" entity=\"e8dd\"/>\n    <symbolinfo name=\"thunderstorm\" entity=\"ebdb\"/>\n    <symbolinfo name=\"tibia\" entity=\"f89b\"/>\n    <symbolinfo name=\"tibia_alt\" entity=\"f89c\"/>\n    <symbolinfo name=\"time_auto\" entity=\"f0e4\"/>\n    <symbolinfo name=\"time_to_leave\" entity=\"eff7\"/>\n    <symbolinfo name=\"timelapse\" entity=\"e422\"/>\n    <symbolinfo name=\"timeline\" entity=\"e922\"/>\n    <symbolinfo name=\"timer\" entity=\"e425\"/>\n    <symbolinfo name=\"timer_10\" entity=\"e423\"/>\n    <symbolinfo name=\"timer_10_alt_1\" entity=\"efbf\"/>\n    <symbolinfo name=\"timer_10_select\" entity=\"f07a\"/>\n    <symbolinfo name=\"timer_3\" entity=\"e424\"/>\n    <symbolinfo name=\"timer_3_alt_1\" entity=\"efc0\"/>\n    <symbolinfo name=\"timer_3_select\" entity=\"f07b\"/>\n    <symbolinfo name=\"timer_off\" entity=\"e426\"/>\n    <symbolinfo name=\"tips_and_updates\" entity=\"e79a\"/>\n    <symbolinfo name=\"tire_repair\" entity=\"ebc8\"/>\n    <symbolinfo name=\"title\" entity=\"e264\"/>\n    <symbolinfo name=\"toast\" entity=\"efc1\"/>\n    <symbolinfo name=\"toc\" entity=\"e8de\"/>\n    <symbolinfo name=\"today\" entity=\"e8df\"/>\n    <symbolinfo name=\"toggle_off\" entity=\"e9f5\"/>\n    <symbolinfo name=\"toggle_on\" entity=\"e9f6\"/>\n    <symbolinfo name=\"token\" entity=\"ea25\"/>\n    <symbolinfo name=\"toll\" entity=\"e8e0\"/>\n    <symbolinfo name=\"tonality\" entity=\"e427\"/>\n    <symbolinfo name=\"toolbar\" entity=\"e9f7\"/>\n    <symbolinfo name=\"tools_flat_head\" entity=\"f8cb\"/>\n    <symbolinfo name=\"tools_installation_kit\" entity=\"e2ab\"/>\n    <symbolinfo name=\"tools_ladder\" entity=\"e2cb\"/>\n    <symbolinfo name=\"tools_level\" entity=\"e77b\"/>\n    <symbolinfo name=\"tools_phillips\" entity=\"f8cc\"/>\n    <symbolinfo name=\"tools_pliers_wire_stripper\" entity=\"e2aa\"/>\n    <symbolinfo name=\"tools_power_drill\" entity=\"e1e9\"/>\n    <symbolinfo name=\"tools_wrench\" entity=\"f8cd\"/>\n    <symbolinfo name=\"tooltip\" entity=\"e9f8\"/>\n    <symbolinfo name=\"top_panel_close\" entity=\"f733\"/>\n    <symbolinfo name=\"top_panel_open\" entity=\"f732\"/>\n    <symbolinfo name=\"topic\" entity=\"f1c8\"/>\n    <symbolinfo name=\"tornado\" entity=\"e199\"/>\n    <symbolinfo name=\"total_dissolved_solids\" entity=\"f877\"/>\n    <symbolinfo name=\"touch_app\" entity=\"e913\"/>\n    <symbolinfo name=\"touchpad_mouse\" entity=\"f687\"/>\n    <symbolinfo name=\"tour\" entity=\"ef75\"/>\n    <symbolinfo name=\"toys\" entity=\"e332\"/>\n    <symbolinfo name=\"toys_fan\" entity=\"f887\"/>\n    <symbolinfo name=\"track_changes\" entity=\"e8e1\"/>\n    <symbolinfo name=\"traffic\" entity=\"e565\"/>\n    <symbolinfo name=\"trail_length\" entity=\"eb5e\"/>\n    <symbolinfo name=\"trail_length_medium\" entity=\"eb63\"/>\n    <symbolinfo name=\"trail_length_short\" entity=\"eb6d\"/>\n    <symbolinfo name=\"train\" entity=\"e570\"/>\n    <symbolinfo name=\"tram\" entity=\"e571\"/>\n    <symbolinfo name=\"transcribe\" entity=\"f8ec\"/>\n    <symbolinfo name=\"transfer_within_a_station\" entity=\"e572\"/>\n    <symbolinfo name=\"transform\" entity=\"e428\"/>\n    <symbolinfo name=\"transgender\" entity=\"e58d\"/>\n    <symbolinfo name=\"transit_enterexit\" entity=\"e579\"/>\n    <symbolinfo name=\"translate\" entity=\"e8e2\"/>\n    <symbolinfo name=\"transportation\" entity=\"e21d\"/>\n    <symbolinfo name=\"travel\" entity=\"ef93\"/>\n    <symbolinfo name=\"travel_explore\" entity=\"e2db\"/>\n    <symbolinfo name=\"trending_down\" entity=\"e8e3\"/>\n    <symbolinfo name=\"trending_flat\" entity=\"e8e4\"/>\n    <symbolinfo name=\"trending_up\" entity=\"e8e5\"/>\n    <symbolinfo name=\"trip_origin\" entity=\"e57b\"/>\n    <symbolinfo name=\"trolley\" entity=\"f86b\"/>\n    <symbolinfo name=\"trophy\" entity=\"ea23\"/>\n    <symbolinfo name=\"troubleshoot\" entity=\"e1d2\"/>\n    <symbolinfo name=\"try\" entity=\"f07c\"/>\n    <symbolinfo name=\"tsunami\" entity=\"ebd8\"/>\n    <symbolinfo name=\"tsv\" entity=\"e6d6\"/>\n    <symbolinfo name=\"tty\" entity=\"f1aa\"/>\n    <symbolinfo name=\"tune\" entity=\"e429\"/>\n    <symbolinfo name=\"tungsten\" entity=\"f07d\"/>\n    <symbolinfo name=\"turn_left\" entity=\"eba6\"/>\n    <symbolinfo name=\"turn_right\" entity=\"ebab\"/>\n    <symbolinfo name=\"turn_sharp_left\" entity=\"eba7\"/>\n    <symbolinfo name=\"turn_sharp_right\" entity=\"ebaa\"/>\n    <symbolinfo name=\"turn_slight_left\" entity=\"eba4\"/>\n    <symbolinfo name=\"turn_slight_right\" entity=\"eb9a\"/>\n    <symbolinfo name=\"turned_in\" entity=\"e8e7\"/>\n    <symbolinfo name=\"turned_in_not\" entity=\"e8e7\"/>\n    <symbolinfo name=\"tv\" entity=\"e63b\"/>\n    <symbolinfo name=\"tv_gen\" entity=\"e830\"/>\n    <symbolinfo name=\"tv_guide\" entity=\"e1dc\"/>\n    <symbolinfo name=\"tv_off\" entity=\"e647\"/>\n    <symbolinfo name=\"tv_options_edit_channels\" entity=\"e1dd\"/>\n    <symbolinfo name=\"tv_remote\" entity=\"f5d9\"/>\n    <symbolinfo name=\"tv_signin\" entity=\"e71b\"/>\n    <symbolinfo name=\"tv_with_assistant\" entity=\"e785\"/>\n    <symbolinfo name=\"two_wheeler\" entity=\"e9f9\"/>\n    <symbolinfo name=\"type_specimen\" entity=\"f8f0\"/>\n    <symbolinfo name=\"u_turn_left\" entity=\"eba1\"/>\n    <symbolinfo name=\"u_turn_right\" entity=\"eba2\"/>\n    <symbolinfo name=\"ulna_radius\" entity=\"f89d\"/>\n    <symbolinfo name=\"ulna_radius_alt\" entity=\"f89e\"/>\n    <symbolinfo name=\"umbrella\" entity=\"f1ad\"/>\n    <symbolinfo name=\"unarchive\" entity=\"e169\"/>\n    <symbolinfo name=\"undo\" entity=\"e166\"/>\n    <symbolinfo name=\"unfold_less\" entity=\"e5d6\"/>\n    <symbolinfo name=\"unfold_less_double\" entity=\"f8cf\"/>\n    <symbolinfo name=\"unfold_more\" entity=\"e5d7\"/>\n    <symbolinfo name=\"unfold_more_double\" entity=\"f8d0\"/>\n    <symbolinfo name=\"ungroup\" entity=\"f731\"/>\n    <symbolinfo name=\"universal_currency_alt\" entity=\"e734\"/>\n    <symbolinfo name=\"unknown_2\" entity=\"e6a2\"/>\n    <symbolinfo name=\"unknown_5\" entity=\"e6a5\"/>\n    <symbolinfo name=\"unknown_document\" entity=\"f804\"/>\n    <symbolinfo name=\"unknown_med\" entity=\"eabd\"/>\n    <symbolinfo name=\"unpublished\" entity=\"f236\"/>\n    <symbolinfo name=\"unsubscribe\" entity=\"e0eb\"/>\n    <symbolinfo name=\"upcoming\" entity=\"f07e\"/>\n    <symbolinfo name=\"update\" entity=\"e923\"/>\n    <symbolinfo name=\"update_disabled\" entity=\"e075\"/>\n    <symbolinfo name=\"upgrade\" entity=\"f0fb\"/>\n    <symbolinfo name=\"upload\" entity=\"f09b\"/>\n    <symbolinfo name=\"upload_file\" entity=\"e9fc\"/>\n    <symbolinfo name=\"urology\" entity=\"e137\"/>\n    <symbolinfo name=\"usb\" entity=\"e1e0\"/>\n    <symbolinfo name=\"usb_off\" entity=\"e4fa\"/>\n    <symbolinfo name=\"vaccines\" entity=\"e138\"/>\n    <symbolinfo name=\"valve\" entity=\"e224\"/>\n    <symbolinfo name=\"vape_free\" entity=\"ebc6\"/>\n    <symbolinfo name=\"vaping_rooms\" entity=\"ebcf\"/>\n    <symbolinfo name=\"variables\" entity=\"f851\"/>\n    <symbolinfo name=\"ventilator\" entity=\"e139\"/>\n    <symbolinfo name=\"verified\" entity=\"ef76\"/>\n    <symbolinfo name=\"verified_user\" entity=\"f013\"/>\n    <symbolinfo name=\"vertical_align_bottom\" entity=\"e258\"/>\n    <symbolinfo name=\"vertical_align_center\" entity=\"e259\"/>\n    <symbolinfo name=\"vertical_align_top\" entity=\"e25a\"/>\n    <symbolinfo name=\"vertical_distribute\" entity=\"e076\"/>\n    <symbolinfo name=\"vertical_shades\" entity=\"ec0e\"/>\n    <symbolinfo name=\"vertical_shades_closed\" entity=\"ec0d\"/>\n    <symbolinfo name=\"vertical_split\" entity=\"e949\"/>\n    <symbolinfo name=\"vibration\" entity=\"e62d\"/>\n    <symbolinfo name=\"video_call\" entity=\"e070\"/>\n    <symbolinfo name=\"video_camera_back\" entity=\"f07f\"/>\n    <symbolinfo name=\"video_camera_front\" entity=\"f080\"/>\n    <symbolinfo name=\"video_camera_front_off\" entity=\"f83b\"/>\n    <symbolinfo name=\"video_chat\" entity=\"f8a0\"/>\n    <symbolinfo name=\"video_file\" entity=\"eb87\"/>\n    <symbolinfo name=\"video_label\" entity=\"e071\"/>\n    <symbolinfo name=\"video_library\" entity=\"e04a\"/>\n    <symbolinfo name=\"video_search\" entity=\"efc6\"/>\n    <symbolinfo name=\"video_settings\" entity=\"ea75\"/>\n    <symbolinfo name=\"video_stable\" entity=\"f081\"/>\n    <symbolinfo name=\"videocam\" entity=\"e04b\"/>\n    <symbolinfo name=\"videocam_off\" entity=\"e04c\"/>\n    <symbolinfo name=\"videogame_asset\" entity=\"e338\"/>\n    <symbolinfo name=\"videogame_asset_off\" entity=\"e500\"/>\n    <symbolinfo name=\"view_agenda\" entity=\"e8e9\"/>\n    <symbolinfo name=\"view_array\" entity=\"e8ea\"/>\n    <symbolinfo name=\"view_carousel\" entity=\"e8eb\"/>\n    <symbolinfo name=\"view_column\" entity=\"e8ec\"/>\n    <symbolinfo name=\"view_column_2\" entity=\"f847\"/>\n    <symbolinfo name=\"view_comfy\" entity=\"e42a\"/>\n    <symbolinfo name=\"view_comfy_alt\" entity=\"eb73\"/>\n    <symbolinfo name=\"view_compact\" entity=\"e42b\"/>\n    <symbolinfo name=\"view_compact_alt\" entity=\"eb74\"/>\n    <symbolinfo name=\"view_cozy\" entity=\"eb75\"/>\n    <symbolinfo name=\"view_day\" entity=\"e8ed\"/>\n    <symbolinfo name=\"view_headline\" entity=\"e8ee\"/>\n    <symbolinfo name=\"view_in_ar\" entity=\"efc9\"/>\n    <symbolinfo name=\"view_in_ar_new\" entity=\"efc9\"/>\n    <symbolinfo name=\"view_in_ar_off\" entity=\"f61b\"/>\n    <symbolinfo name=\"view_kanban\" entity=\"eb7f\"/>\n    <symbolinfo name=\"view_list\" entity=\"e8ef\"/>\n    <symbolinfo name=\"view_module\" entity=\"e8f0\"/>\n    <symbolinfo name=\"view_quilt\" entity=\"e8f1\"/>\n    <symbolinfo name=\"view_sidebar\" entity=\"f114\"/>\n    <symbolinfo name=\"view_stream\" entity=\"e8f2\"/>\n    <symbolinfo name=\"view_timeline\" entity=\"eb85\"/>\n    <symbolinfo name=\"view_week\" entity=\"e8f3\"/>\n    <symbolinfo name=\"vignette\" entity=\"e435\"/>\n    <symbolinfo name=\"villa\" entity=\"e586\"/>\n    <symbolinfo name=\"visibility\" entity=\"e8f4\"/>\n    <symbolinfo name=\"visibility_lock\" entity=\"f653\"/>\n    <symbolinfo name=\"visibility_off\" entity=\"e8f5\"/>\n    <symbolinfo name=\"vital_signs\" entity=\"e650\"/>\n    <symbolinfo name=\"vitals\" entity=\"e13b\"/>\n    <symbolinfo name=\"voice_chat\" entity=\"e62e\"/>\n    <symbolinfo name=\"voice_over_off\" entity=\"e94a\"/>\n    <symbolinfo name=\"voice_selection\" entity=\"f58a\"/>\n    <symbolinfo name=\"voicemail\" entity=\"e0d9\"/>\n    <symbolinfo name=\"volcano\" entity=\"ebda\"/>\n    <symbolinfo name=\"volume_down\" entity=\"e04d\"/>\n    <symbolinfo name=\"volume_down_alt\" entity=\"e79c\"/>\n    <symbolinfo name=\"volume_mute\" entity=\"e04e\"/>\n    <symbolinfo name=\"volume_off\" entity=\"e04f\"/>\n    <symbolinfo name=\"volume_up\" entity=\"e050\"/>\n    <symbolinfo name=\"volunteer_activism\" entity=\"ea70\"/>\n    <symbolinfo name=\"voting_chip\" entity=\"f852\"/>\n    <symbolinfo name=\"vpn_key\" entity=\"e0da\"/>\n    <symbolinfo name=\"vpn_key_alert\" entity=\"f6cc\"/>\n    <symbolinfo name=\"vpn_key_off\" entity=\"eb7a\"/>\n    <symbolinfo name=\"vpn_lock\" entity=\"e62f\"/>\n    <symbolinfo name=\"vr180_create2d\" entity=\"efca\"/>\n    <symbolinfo name=\"vr180_create2d_off\" entity=\"f571\"/>\n    <symbolinfo name=\"vrpano\" entity=\"f082\"/>\n    <symbolinfo name=\"wall_art\" entity=\"efcb\"/>\n    <symbolinfo name=\"wall_lamp\" entity=\"e2b4\"/>\n    <symbolinfo name=\"wallet\" entity=\"f8ff\"/>\n    <symbolinfo name=\"wallpaper\" entity=\"e1bc\"/>\n    <symbolinfo name=\"wallpaper_slideshow\" entity=\"f672\"/>\n    <symbolinfo name=\"ward\" entity=\"e13c\"/>\n    <symbolinfo name=\"warehouse\" entity=\"ebb8\"/>\n    <symbolinfo name=\"warning\" entity=\"f083\"/>\n    <symbolinfo name=\"warning_amber\" entity=\"f083\"/>\n    <symbolinfo name=\"warning_off\" entity=\"f7ad\"/>\n    <symbolinfo name=\"wash\" entity=\"f1b1\"/>\n    <symbolinfo name=\"watch\" entity=\"e334\"/>\n    <symbolinfo name=\"watch_button_press\" entity=\"f6aa\"/>\n    <symbolinfo name=\"watch_later\" entity=\"efd6\"/>\n    <symbolinfo name=\"watch_off\" entity=\"eae3\"/>\n    <symbolinfo name=\"watch_screentime\" entity=\"f6ae\"/>\n    <symbolinfo name=\"watch_wake\" entity=\"f6a9\"/>\n    <symbolinfo name=\"water\" entity=\"f084\"/>\n    <symbolinfo name=\"water_bottle\" entity=\"f69d\"/>\n    <symbolinfo name=\"water_bottle_large\" entity=\"f69e\"/>\n    <symbolinfo name=\"water_damage\" entity=\"f203\"/>\n    <symbolinfo name=\"water_do\" entity=\"f870\"/>\n    <symbolinfo name=\"water_drop\" entity=\"e798\"/>\n    <symbolinfo name=\"water_ec\" entity=\"f875\"/>\n    <symbolinfo name=\"water_full\" entity=\"f6d6\"/>\n    <symbolinfo name=\"water_heater\" entity=\"e284\"/>\n    <symbolinfo name=\"water_lock\" entity=\"f6ad\"/>\n    <symbolinfo name=\"water_loss\" entity=\"f6d5\"/>\n    <symbolinfo name=\"water_lux\" entity=\"f874\"/>\n    <symbolinfo name=\"water_medium\" entity=\"f6d4\"/>\n    <symbolinfo name=\"water_orp\" entity=\"f878\"/>\n    <symbolinfo name=\"water_ph\" entity=\"f87a\"/>\n    <symbolinfo name=\"water_pump\" entity=\"f5d8\"/>\n    <symbolinfo name=\"water_voc\" entity=\"f87b\"/>\n    <symbolinfo name=\"waterfall_chart\" entity=\"ea00\"/>\n    <symbolinfo name=\"waves\" entity=\"e176\"/>\n    <symbolinfo name=\"waving_hand\" entity=\"e766\"/>\n    <symbolinfo name=\"wb_auto\" entity=\"e42c\"/>\n    <symbolinfo name=\"wb_cloudy\" entity=\"f15c\"/>\n    <symbolinfo name=\"wb_incandescent\" entity=\"e42e\"/>\n    <symbolinfo name=\"wb_iridescent\" entity=\"f07d\"/>\n    <symbolinfo name=\"wb_shade\" entity=\"ea01\"/>\n    <symbolinfo name=\"wb_sunny\" entity=\"e430\"/>\n    <symbolinfo name=\"wb_twilight\" entity=\"e1c6\"/>\n    <symbolinfo name=\"wc\" entity=\"e63d\"/>\n    <symbolinfo name=\"weather_hail\" entity=\"f67f\"/>\n    <symbolinfo name=\"weather_mix\" entity=\"f60b\"/>\n    <symbolinfo name=\"weather_snowy\" entity=\"e2cd\"/>\n    <symbolinfo name=\"web\" entity=\"e051\"/>\n    <symbolinfo name=\"web_asset\" entity=\"e069\"/>\n    <symbolinfo name=\"web_asset_off\" entity=\"ef47\"/>\n    <symbolinfo name=\"web_stories\" entity=\"e595\"/>\n    <symbolinfo name=\"webhook\" entity=\"eb92\"/>\n    <symbolinfo name=\"weekend\" entity=\"e16b\"/>\n    <symbolinfo name=\"weight\" entity=\"e13d\"/>\n    <symbolinfo name=\"west\" entity=\"f1e6\"/>\n    <symbolinfo name=\"whatshot\" entity=\"e80e\"/>\n    <symbolinfo name=\"wheelchair_pickup\" entity=\"f1ab\"/>\n    <symbolinfo name=\"where_to_vote\" entity=\"e177\"/>\n    <symbolinfo name=\"widgets\" entity=\"e1bd\"/>\n    <symbolinfo name=\"width\" entity=\"f730\"/>\n    <symbolinfo name=\"width_full\" entity=\"f8f5\"/>\n    <symbolinfo name=\"width_normal\" entity=\"f8f6\"/>\n    <symbolinfo name=\"width_wide\" entity=\"f8f7\"/>\n    <symbolinfo name=\"wifi\" entity=\"e63e\"/>\n    <symbolinfo name=\"wifi_1_bar\" entity=\"e4ca\"/>\n    <symbolinfo name=\"wifi_2_bar\" entity=\"e4d9\"/>\n    <symbolinfo name=\"wifi_add\" entity=\"f7a8\"/>\n    <symbolinfo name=\"wifi_calling\" entity=\"ef77\"/>\n    <symbolinfo name=\"wifi_calling_1\" entity=\"f0f6\"/>\n    <symbolinfo name=\"wifi_calling_2\" entity=\"f0f6\"/>\n    <symbolinfo name=\"wifi_calling_3\" entity=\"f0f6\"/>\n    <symbolinfo name=\"wifi_channel\" entity=\"eb6a\"/>\n    <symbolinfo name=\"wifi_find\" entity=\"eb31\"/>\n    <symbolinfo name=\"wifi_home\" entity=\"f671\"/>\n    <symbolinfo name=\"wifi_lock\" entity=\"e1e1\"/>\n    <symbolinfo name=\"wifi_notification\" entity=\"f670\"/>\n    <symbolinfo name=\"wifi_off\" entity=\"e648\"/>\n    <symbolinfo name=\"wifi_password\" entity=\"eb6b\"/>\n    <symbolinfo name=\"wifi_protected_setup\" entity=\"f0fc\"/>\n    <symbolinfo name=\"wifi_proxy\" entity=\"f7a7\"/>\n    <symbolinfo name=\"wifi_tethering\" entity=\"e1e2\"/>\n    <symbolinfo name=\"wifi_tethering_error\" entity=\"ead9\"/>\n    <symbolinfo name=\"wifi_tethering_off\" entity=\"f087\"/>\n    <symbolinfo name=\"wind_power\" entity=\"ec0c\"/>\n    <symbolinfo name=\"window\" entity=\"f088\"/>\n    <symbolinfo name=\"window_closed\" entity=\"e77e\"/>\n    <symbolinfo name=\"window_open\" entity=\"e78c\"/>\n    <symbolinfo name=\"window_sensor\" entity=\"e2bb\"/>\n    <symbolinfo name=\"wine_bar\" entity=\"f1e8\"/>\n    <symbolinfo name=\"woman\" entity=\"e13e\"/>\n    <symbolinfo name=\"woman_2\" entity=\"f8e7\"/>\n    <symbolinfo name=\"work\" entity=\"e943\"/>\n    <symbolinfo name=\"work_alert\" entity=\"f5f7\"/>\n    <symbolinfo name=\"work_history\" entity=\"ec09\"/>\n    <symbolinfo name=\"work_off\" entity=\"e942\"/>\n    <symbolinfo name=\"work_outline\" entity=\"e943\"/>\n    <symbolinfo name=\"work_update\" entity=\"f5f8\"/>\n    <symbolinfo name=\"workflow\" entity=\"ea04\"/>\n    <symbolinfo name=\"workspace_premium\" entity=\"e7af\"/>\n    <symbolinfo name=\"workspaces\" entity=\"ea0f\"/>\n    <symbolinfo name=\"workspaces_outline\" entity=\"ea0f\"/>\n    <symbolinfo name=\"wounds_injuries\" entity=\"e13f\"/>\n    <symbolinfo name=\"wrap_text\" entity=\"e25b\"/>\n    <symbolinfo name=\"wrist\" entity=\"f69c\"/>\n    <symbolinfo name=\"wrong_location\" entity=\"ef78\"/>\n    <symbolinfo name=\"wysiwyg\" entity=\"f1c3\"/>\n    <symbolinfo name=\"yard\" entity=\"f089\"/>\n    <symbolinfo name=\"your_trips\" entity=\"eb2b\"/>\n    <symbolinfo name=\"youtube_activity\" entity=\"f85a\"/>\n    <symbolinfo name=\"youtube_searched_for\" entity=\"e8fa\"/>\n    <symbolinfo name=\"zone_person_alert\" entity=\"e781\"/>\n    <symbolinfo name=\"zone_person_idle\" entity=\"e77a\"/>\n    <symbolinfo name=\"zone_person_urgent\" entity=\"e788\"/>\n    <symbolinfo name=\"zoom_in\" entity=\"e8ff\"/>\n    <symbolinfo name=\"zoom_in_map\" entity=\"eb2d\"/>\n    <symbolinfo name=\"zoom_out\" entity=\"e900\"/>\n    <symbolinfo name=\"zoom_out_map\" entity=\"e56b\"/>\n</xsl:variable>\n\n</xsl:stylesheet>\n","localizations/af-ZA.xml":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n<!--********************************************************************\nCopyright (C) 2014-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- See  xsl/localizations/README.md  for an explanation of this file -->\n\n<!-- af-ZA, Afrikaans (South Africa) -->\n<!-- Dirk Basson, djbasson@sun.ac.za, 2018-03-23 -->\n\n<locale language=\"af-ZA\" direction=\"ltr\"\n        quote-primary=\"english-double\" quote-secondary=\"english-single\">\n    <!-- THEOREM-LIKE blocks -->\n    <!-- The english quotation style above is just a default, it needs adjustment -->\n    <localization string-id='theorem'>Stelling</localization>\n    <localization string-id='corollary'>Gevolg</localization>\n    <localization string-id='lemma'>Hulpstelling</localization> <!-- Or \"Lemma\" as well -->\n    <localization string-id='algorithm'>Algoritme</localization>\n    <localization string-id='proposition'>Stelling</localization>\n    <localization string-id='claim'>Aanvoering</localization> <!-- This was a difficult one for me. The most obvious candidate is \"bewering\", but this is already used as a technical term for a mathematical statement. Words like \"veronderstelling\", \"eis\", \"postuleer\" all convey slightly the wrong meaning. \"Aanvoering\" is slightly awkward, but the best I could think of. -D.Basson -->\n    <localization string-id='fact'>Feit</localization>\n    <localization string-id='identity'>Identiteit</localization>\n    <!-- PROOF-LIKE -->\n    <localization string-id='proof'>Bewys</localization>\n    <!-- <localization string-id='argument'>Argument</localization> -->\n    <!-- <localization string-id='justification'>Justification</localization> -->\n    <!-- <localization string-id='reasoning'>Reasoning</localization> -->\n    <!-- <localization string-id='explanation'>Explanation</localization> -->\n    <localization string-id='case'>Geval</localization>\n    <!-- Components of the narrative -->\n    <!-- Mathematical statements without proofs -->\n    <!-- AXIOM-LIKE blocks -->\n    <localization string-id='axiom'>Aksioma</localization>\n    <localization string-id='conjecture'>Vermoede</localization>\n    <localization string-id='principle'>Beginsel</localization>\n    <localization string-id='heuristic'>Heuristiek</localization>\n    <localization string-id='hypothesis'>Hipotese</localization>\n    <localization string-id='assumption'>Aanname</localization>\n    <!-- Definitions -->\n    <localization string-id='definition'>Definisie</localization>\n    <!-- Mathematics -->\n    <localization string-id='equation'>Vergelyking</localization>\n    <localization string-id='displaymath'>Vertoon Wiskunde</localization>\n    <!-- Types of documents, mostly for informational messages -->\n    <localization string-id='volume'>Volume</localization>\n    <localization string-id='book'>Boek</localization>\n    <localization string-id='article'>Artikel</localization>\n    <localization string-id='letter'>Brief</localization>\n    <localization string-id='slideshow'>Skyfie Vertoning</localization>\n    <localization string-id='memo'>Memo</localization>\n    <localization string-id='presentation'>Aanbieding</localization>\n    <!-- Parts of a document -->\n    <localization string-id='frontmatter'>Voorsake</localization> <!-- Can't find this anywhere, so I made it up. -->\n    <localization string-id='part'>Deel</localization>\n    <localization string-id='chapter'>Hoofstuk</localization>\n    <localization string-id='appendix'>Bylaag</localization>\n    <!-- <localization string-id='appendices'>Appendices</localization> -->\n    <localization string-id='section'>Afdeling</localization>\n    <localization string-id='subsection'>Onderafdeling</localization>\n    <localization string-id='subsubsection'>Onderonderafdeling</localization>\n    <localization string-id='slide'>Skyfie</localization>\n    <localization string-id='introduction'>Inleiding</localization>\n    <localization string-id='conclusion'>Slot</localization>\n    <localization string-id='exercises'>Oefeninge</localization>\n    <localization string-id='worksheet'>Werkblad</localization>\n    <!-- <localization string-id='handout'>Handout</localization> -->\n    <localization string-id='reading-questions'>Leesvrae</localization>\n    <localization string-id='solutions'>Oplossings</localization>\n    <localization string-id='glossary'>Woordelys</localization>\n    <localization string-id='references'>Verwysings</localization>\n    <localization string-id='backmatter'>Nasake</localization> <!-- Can't find this anywhere, so I made it up. -->\n    <localization string-id='paragraphs'>Paragrawe</localization>\n    <localization string-id='subparagraph'>Onderparagrawe</localization>\n    <!-- Adjustments to titles of divisions -->\n    <!-- <localization string-id='group'>Group</localization> -->\n    <!-- Components of the narrative -->\n    <!-- REMARK-LIKE blocks -->\n    <localization string-id='remark'>Opmerking</localization>\n    <localization string-id='convention'>Konvensie</localization>\n    <localization string-id='note'>Nota</localization>\n    <localization string-id='observation'>Waarneming</localization>\n    <localization string-id='warning'>Waarskuwing</localization>\n    <localization string-id='insight'>Insig</localization>\n    <!-- COMPUTATION-LIKE blocks -->\n    <localization string-id='computation'>Berekening</localization>\n    <localization string-id='technology'>Tegnologie</localization>\n    <!-- <localization string-id='data'>Data</localization> -->\n    <!-- ASIDE-LIKE blocks -->\n    <localization string-id='aside'>Ter Syde</localization>\n    <localization string-id='biographical'>Biografiese Ter Syde</localization>\n    <localization string-id='historical'>Geskiedkundige Ter Syde</localization>\n    <!-- EXAMPLE-LIKE blocks -->\n    <localization string-id='example'>Voorbeeld</localization>\n    <localization string-id='question'>Vraag</localization>\n    <localization string-id='problem'>Probleem</localization>\n    <!-- PROJECT-LIKE blocks -->\n    <localization string-id='project'>Projek</localization>\n    <localization string-id='activity'>Aktiwiteit</localization>\n    <localization string-id='exploration'>Verkenning</localization>\n    <localization string-id='task'>Taak</localization>\n    <localization string-id='investigation'>Ondersoek</localization>\n    <localization string-id='assemblage'>Samevatting</localization>\n    <localization string-id='poem'>Gedig</localization>\n    <localization string-id='objectives'>Doelstellings</localization>\n    <localization string-id='objective'>Doelstelling</localization>\n    <localization string-id='outcomes'>Uitkomstes</localization>\n    <localization string-id='outcome'>Uitkoms</localization>\n    <!-- <localization string-id='openquestion'>Open Question</localization> -->\n    <!-- <localization string-id='openproblem'>Open Problem</localization> -->\n    <!-- <localization string-id='openconjecture'>Open Conjecture</localization> -->\n    <!-- <localization string-id='context'>Context</localization> -->\n    <!-- <localization string-id='discussion'>Discussion</localization> -->\n    <!-- <localization string-id='opinion'>Opinion</localization> -->\n    <!-- <localization string-id='status'>Status</localization> -->\n    <!-- <localization string-id='suggestion'>Suggestion</localization> -->\n    <localization string-id='figure'>Figuur</localization>\n    <localization string-id='table'>Tabel</localization>\n    <localization string-id='listing'>Lys</localization>\n    <localization string-id='fn'>Voetnota</localization>\n    <localization string-id='contributor'>Bydraer</localization>\n    <!-- Lists and their items -->\n    <localization string-id='list'>Lys</localization>\n    <localization string-id='li'>Item</localization>\n    <localization string-id='gi'>Term</localization>\n    <localization string-id='p'>Paragraaf</localization>\n    <localization string-id='blockquote'>Aanhaling</localization>\n    <!-- <localization string-id='pre'>Code Block</localization> -->\n    <localization string-id='fragment'>Fragment</localization>\n    <!-- Parts of an exercise and its solution -->\n    <!-- See the en-US file for a detailed explanation of the words for exercises -->\n    <localization string-id='divisionalexercise'>Oefening</localization>\n    <localization string-id='inlineexercise'>Kontrolepunt</localization>\n    <localization string-id='worksheetexercise'>Werkbladoefening</localization>\n    <localization string-id='readingquestion'>Leesvraag</localization>\n    <localization string-id='webwork'>WeBWorK</localization>\n    <localization string-id='hint'>Wenk</localization>\n    <localization string-id='answer'>Antwoord</localization>\n    <localization string-id='solution'>Oplossing</localization>\n    <!-- <localization string-id='subexercises'>Subexercises</localization> -->\n    <localization string-id='exercisegroup'>Oefening Groep</localization>\n    <localization string-id='biblio'>Bibliografiese Inskrywing</localization>\n    <!-- Front matter components -->\n    <localization string-id='toc'>Inhoudsopgawe</localization>\n    <localization string-id='abstract'>Abstrak</localization>\n    <localization string-id='preface'>Voorwoord</localization>\n    <localization string-id='acknowledgement'>Erkennings</localization>\n    <localization string-id='biography'>Skrywer Biografie</localization>\n    <localization string-id='about-author'>Oor die skrywer</localization>\n    <localization string-id='about-authors'>Oor die skrywers</localization>\n    <localization string-id='foreword'>Voorwoord</localization>\n    <localization string-id='dedication'>Toewyding</localization>\n    <localization string-id='colophon'>Kolofon</localization> <!-- I have never heard of an Afrikaans version of colophon. Google Translate gives \"slottitel\" for the Dutch, meaning \"Summary title\". So , I just made this up. -D.Basson -->\n    <!-- Runestone Activities -->\n    <!-- <localization string-id='video'>Video</localization> -->\n    <!-- <localization string-id='program'>Program</localization> -->\n    <!-- Runestone Exercises -->\n    <!-- <localization string-id='true'>True</localization> -->\n    <!-- <localization string-id='false'>False</localization> -->\n    <!-- <localization string-id='or'>Or</localization> -->\n    <!-- <localization string-id='either'>Either</localization> -->\n    <!-- <localization string-id='uncategorized'>Uncategorized</localization> -->\n    <!-- <localization string-id='query'>Query</localization> -->\n    <localization string-id='program-activecode'>ActiveCode</localization>\n    <!-- <localization string-id='scratch-activecode'>Scratch ActiveCode</localization> -->\n    <localization string-id='program-codelens'>CodeLens</localization>\n    <!-- Back matter components -->\n    <localization string-id='index'>Indeks</localization>\n    <localization string-id='jump-to'>Spring na</localization>\n    <!-- Parts of the Index -->\n    <localization string-id='see'>Sien</localization>\n    <localization string-id='also'>Sien ook</localization>\n    <!-- Notation List headings/foot -->\n    <localization string-id='symbol'>Simbool</localization>\n    <localization string-id='description'>Beskrywing</localization>\n    <localization string-id='location'>Plek</localization>\n    <localization string-id='page'>Bladsy</localization>\n    <localization string-id='continued'>Voortgesit op volgende bladsy</localization>\n    <!-- Navigation Interface elements -->\n    <localization string-id='skip-to-content'>Slaan oor na hoofinhoud</localization>\n    <localization string-id='previous'>Vorige</localization>\n    <localization string-id='up'>Op</localization>\n    <localization string-id='next'>Volgende</localization>\n    <localization string-id='previous-short'>Vorig</localization>\n    <localization string-id='up-short'>Op</localization>\n    <localization string-id='next-short'>Volg</localization>\n    <!-- <localization string-id='top'>Top</localization> -->\n    <localization string-id='annotations'>Aantekeninge</localization>\n    <localization string-id='feedback'>Terugvoer</localization>\n    <localization string-id='authored'>Geskryf in</localization>\n    <!-- Search Results display/dialog -->\n    <!-- <localization string-id='search-book'>Search Book</localization> -->\n    <!-- <localization string-id='search-results-heading'>Search Results</localization> -->\n    <!-- <localization string-id='no-search-results'>No results</localization> -->\n    <!-- Parts of memos and letters -->\n    <localization string-id='to'>Aan</localization>\n    <localization string-id='from'>Van</localization>\n    <localization string-id='subject'>Onderwerp</localization>\n    <localization string-id='date'>Datum</localization>\n    <localization string-id='cc'>cc</localization>\n    <localization string-id='enclosure'>bylae</localization>\n    <!-- Various -->\n    <localization string-id='todo'>Om Te Doen</localization>\n    <localization string-id='editor'>Redakteur</localization>\n    <localization string-id='edition'>Uitgawe</localization>\n    <localization string-id='website'>Webtuiste</localization>\n    <localization string-id='copyright'>Kopiereg</localization>\n    <!-- <localization string-id='keywords'>Keywords</localization> -->\n    <!-- HTML clickables (lowercase strings to click on) -->\n    <localization string-id='permalink'>perma-skakel</localization>\n    <localization string-id='incontext'>In Konteks</localization>\n    <!-- <localization string-id='standalone'>Standalone</localization> -->\n    <!-- <localization string-id='embed'>Embed</localization> -->\n    <!-- <localization string-id='embed-this-page'>Embed this page</localization> -->\n    <!-- <localization string-id='copy'>Copy</localization> -->\n    <!-- <localization string-id='profile'>Profile</localization> -->\n    <!-- Following is in ENGLISH and should be translated.  Due to its -->\n    <!-- ubiquitous nature we have not left it undefined.  See the -->\n    <!-- \"en-US\" file for a more complete explanation of its use. -->\n    <!-- Please remove this entire comment when translated.  Thanks. -->\n    <localization string-id='permalink-tooltip'>Copy heading and permalink for</localization>\n    <!-- <localization string-id='calculator'>Calculator</localization> -->\n    <localization string-id='evaluate'>Evalueer</localization>\n    <!-- <localization string-id='code'>Code</localization> -->\n    <!-- <localization string-id='instructions'>Instructions</localization> -->\n    <!-- <localization string-id='correct'>Correct</localization> -->\n    <!-- <localization string-id='incorrect'>Incorrect</localization> -->\n    <!-- <localization string-id='blank'>Blank</localization> -->\n    <!-- <localization string-id='submit'>Submit</localization> -->\n    <!-- <localization string-id='check-responses'>Check Responses</localization> -->\n    <!-- <localization string-id='reveal'>Reveal</localization> -->\n    <!-- <localization string-id='randomize'>Randomize</localization> -->\n    <!-- <localization string-id='activate'>Activate</localization> -->\n    <!-- <localization string-id='reset'>Reset</localization> -->\n    <!-- <localization string-id='array'>array</localization> -->\n    <!-- <localization string-id=\"papersize\">Paper size</localization> -->\n    <!-- <localization string-id=\"printing-options\">Additional printing options</localization> -->\n    <!-- <localization string-id=\"hide-hints\">Hide hints</localization> -->\n    <!-- <localization string-id=\"hide-answers\">Hide answers</localization> -->\n    <!-- <localization string-id=\"hide-solutions\">Hide solutions</localization> -->\n    <!-- <localization string-id=\"print-header\">Print headers</localization> -->\n    <!-- <localization string-id=\"print-footer\">Print footers</localization> -->\n    <!-- <localization string-id=\"first-page\">First page</localization> -->\n    <!-- <localization string-id=\"running\">Running</localization> -->\n    <!-- <localization string-id=\"highlight-workspace\">Highlight workspace</localization> -->\n    <!-- <localization string-id='print'>Print</localization> -->\n    <!-- <localization string-id='print-preview'>Print preview</localization> -->\n    <!-- <localization string-id='close'>Close</localization> -->\n    <!-- <localization string-id='open-new-tab'>Open in new tab</localization> -->\n    <!-- Readability menu items, HTML only, utilized by Javascript -->\n    <!-- <localization string-id='readability-settings'>Readability settings</localization> -->\n    <!-- <localization string-id='readability-line-height'>Line height</localization> -->\n    <!-- <localization string-id='readability-content-font-size'>Content font size</localization> -->\n    <!-- <localization string-id='readability-theme'>Theme</localization> -->\n    <!-- <localization string-id='readability-theme-system'>System</localization> -->\n    <!-- <localization string-id='readability-theme-light'>Light</localization> -->\n    <!-- <localization string-id='readability-theme-dark'>Dark</localization> -->\n    <!-- <localization string-id='readability-assistive-technologies'>Assistive technologies</localization> -->\n    <!-- <localization string-id='readability-expose-permalinks'>Expose permalinks</localization> -->\n    <!-- <localization string-id='reset-all'>Reset All</localization> -->\n</locale>\n","localizations/bg-BG.xml":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n<!--********************************************************************\nCopyright (C) 2014-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- See  xsl/localizations/README.md  for an explanation of this file -->\n\n<!-- bg-BG, Bulgarian (Bulgaria) -->\n<!-- Boyko Bantchev, bantchev@gmail.com, 2019-07-04 -->\n\n<locale language=\"bg-BG\" direction=\"ltr\"\n        quote-primary=\"english-double\" quote-secondary=\"english-single\">\n    <!-- THEOREM-LIKE blocks -->\n    <!-- The english quotation style above is just a default, it needs adjustment -->\n    <localization string-id='theorem'>Теорема</localization>\n    <localization string-id='corollary'>Следствие</localization>\n    <localization string-id='lemma'>Лема</localization>\n    <localization string-id='algorithm'>Алгоритъм</localization>\n    <localization string-id='proposition'>Предложение</localization>\n    <localization string-id='claim'>Твърдение</localization>\n    <localization string-id='fact'>Факт</localization>\n    <localization string-id='identity'>Тъждество</localization>\n    <!-- PROOF-LIKE -->\n    <localization string-id='proof'>Доказателство</localization>\n    <!-- <localization string-id='argument'>Argument</localization> -->\n    <!-- <localization string-id='justification'>Justification</localization> -->\n    <!-- <localization string-id='reasoning'>Reasoning</localization> -->\n    <!-- <localization string-id='explanation'>Explanation</localization> -->\n    <localization string-id='case'>Случай</localization>\n    <!-- Components of the narrative -->\n    <!-- Mathematical statements without proofs -->\n    <!-- AXIOM-LIKE blocks -->\n    <localization string-id='axiom'>Аксиома</localization>\n    <localization string-id='conjecture'>Хипотеза</localization>\n    <localization string-id='principle'>Принцип</localization>\n    <localization string-id='heuristic'>Heuristic</localization>\n    <localization string-id='hypothesis'>Хипотеза</localization>\n    <localization string-id='assumption'>Постулат</localization>\n    <!-- Definitions -->\n    <localization string-id='definition'>Определение</localization>\n    <!-- Mathematics -->\n    <localization string-id='equation'>Уравнение</localization>\n    <localization string-id='displaymath'>Изнесена формула</localization>\n    <!-- Types of documents, mostly for informational messages -->\n    <localization string-id='volume'>Том</localization>\n    <localization string-id='book'>Книга</localization>\n    <localization string-id='article'>Статия</localization>\n    <localization string-id='letter'>Писмо</localization>\n    <!-- <localization string-id='slideshow'>Slideshow</localization> -->\n    <localization string-id='memo'>Паметна записка</localization>\n    <localization string-id='presentation'>Презентация</localization>\n    <!-- Parts of a document -->\n    <localization string-id='frontmatter'>Титулни страници</localization>\n    <localization string-id='part'>Част</localization>\n    <localization string-id='chapter'>Глава</localization>\n    <localization string-id='appendix'>Приложение</localization>\n    <!-- <localization string-id='appendices'>Appendices</localization> -->\n    <localization string-id='section'>Параграф</localization>\n    <localization string-id='subsection'>Точка</localization>\n    <localization string-id='subsubsection'>Подточка</localization>\n    <!-- <localization string-id='slide'>Slide</localization> -->\n    <localization string-id='introduction'>Увод</localization>\n    <localization string-id='conclusion'>Заключение</localization>\n    <localization string-id='exercises'>Упражнения</localization>\n    <localization string-id='worksheet'>Worksheet</localization>\n    <localization string-id='handout'>Handout</localization>\n    <localization string-id='reading-questions'>Reading Questions</localization>\n    <localization string-id='solutions'>Решения</localization>\n    <localization string-id='glossary'>Речник на термините</localization>\n    <localization string-id='references'>Библиография</localization>\n    <localization string-id='backmatter'>Издателско каре</localization>\n    <localization string-id='paragraphs'>Paragraphs</localization>\n    <localization string-id='subparagraph'>Subparagraph</localization>\n    <!-- Adjustments to titles of divisions -->\n    <!-- <localization string-id='group'>Group</localization> -->\n    <!-- Components of the narrative -->\n    <!-- REMARK-LIKE blocks -->\n    <localization string-id='remark'>Remark</localization>\n    <localization string-id='convention'>Convention</localization>\n    <localization string-id='note'>Забележка</localization>\n    <!-- <localization string-id='observation'>Observation</localization> -->\n    <!-- <localization string-id='warning'>Warning</localization> -->\n    <!-- <localization string-id='insight'>Insight</localization> -->\n    <!-- COMPUTATION-LIKE blocks -->\n    <!-- <localization string-id='computation'>Computation</localization> -->\n    <!-- <localization string-id='technology'>Technology</localization> -->\n    <!-- <localization string-id='data'>Data</localization> -->\n    <!-- ASIDE-LIKE blocks -->\n    <localization string-id='aside'>Странична бележка</localization>\n    <localization string-id='biographical'>Библиографична бележка</localization>\n    <localization string-id='historical'>Историческа бележка</localization>\n    <!-- EXAMPLE-LIKE blocks -->\n    <localization string-id='example'>Пример</localization>\n    <localization string-id='question'>Въпрос</localization>\n    <localization string-id='problem'>Задача</localization>\n    <!-- PROJECT-LIKE blocks -->\n    <localization string-id='project'>Задание</localization>\n    <localization string-id='activity'>Дейност</localization>\n    <localization string-id='exploration'>Проучване</localization>\n    <localization string-id='task'>Задача</localization>\n    <localization string-id='investigation'>Изследване</localization>\n    <localization string-id='assemblage'>Сборник</localization>\n    <localization string-id='poem'>Стихотворение</localization>\n    <localization string-id='objectives'>Цели</localization>\n    <localization string-id='objective'>Цел</localization>\n    <localization string-id='outcomes'>Резултати</localization>\n    <localization string-id='outcome'>Резултат</localization>\n    <!-- <localization string-id='openquestion'>Open Question</localization> -->\n    <!-- <localization string-id='openproblem'>Open Problem</localization> -->\n    <!-- <localization string-id='openconjecture'>Open Conjecture</localization> -->\n    <!-- <localization string-id='context'>Context</localization> -->\n    <!-- <localization string-id='discussion'>Discussion</localization> -->\n    <!-- <localization string-id='opinion'>Opinion</localization> -->\n    <!-- <localization string-id='status'>Status</localization> -->\n    <!-- <localization string-id='suggestion'>Suggestion</localization> -->\n    <localization string-id='figure'>Фигура</localization>\n    <localization string-id='table'>Таблица</localization>\n    <localization string-id='listing'>Списък</localization>\n    <localization string-id='fn'>Бележка под линия</localization>\n    <localization string-id='contributor'>Contributor</localization>\n    <!-- Lists and their items -->\n    <localization string-id='list'>Списък</localization>\n    <localization string-id='li'>Точка</localization>\n    <localization string-id='gi'>Термин</localization>\n    <localization string-id='p'>Абзац</localization>\n    <localization string-id='blockquote'>Цитат</localization>\n    <!-- <localization string-id='pre'>Code Block</localization> -->\n    <!-- <localization string-id='fragment'>Fragment</localization> -->\n    <!-- Parts of an exercise and its solution -->\n    <!-- See the en-US file for a detailed explanation of the words for exercises -->\n    <localization string-id='divisionalexercise'>Упражнение</localization>\n    <localization string-id='inlineexercise'>Checkpoint</localization>\n    <localization string-id='worksheetexercise'>Worksheet Exercise</localization>\n    <localization string-id='readingquestion'>Reading Question</localization>\n    <localization string-id='webwork'>WeBWorK</localization>\n    <localization string-id='hint'>Подсказка</localization>\n    <localization string-id='answer'>Отговор</localization>\n    <localization string-id='solution'>Решение</localization>\n    <!-- <localization string-id='subexercises'>Subexercises</localization> -->\n    <localization string-id='exercisegroup'>Exercise Group</localization>\n    <localization string-id='biblio'>Bibliographic Entry</localization>\n    <!-- Front matter components -->\n    <localization string-id='toc'>Съдържание</localization>\n    <localization string-id='abstract'>Резюме</localization> <!-- за книга е по-добре „Анотация“ -->\n    <localization string-id='preface'>Предговор</localization> <!-- от автора -->\n    <localization string-id='acknowledgement'>Благодарности</localization>\n    <localization string-id='biography'>Биография на автора</localization>\n    <localization string-id='about-author'>За автора</localization>\n    <localization string-id='about-authors'>За авторите</localization>\n    <localization string-id='foreword'>Предговор</localization> <!-- от другиго -->\n    <localization string-id='dedication'>Посвещение</localization>\n    <localization string-id='colophon'>Библиографско каре</localization>\n    <!-- Runestone Activities -->\n    <!-- <localization string-id='video'>Video</localization> -->\n    <!-- <localization string-id='program'>Program</localization> -->\n    <!-- Runestone Exercises -->\n    <!-- <localization string-id='true'>True</localization> -->\n    <!-- <localization string-id='false'>False</localization> -->\n    <!-- <localization string-id='or'>Or</localization> -->\n    <!-- <localization string-id='either'>Either</localization> -->\n    <!-- <localization string-id='uncategorized'>Uncategorized</localization> -->\n    <!-- <localization string-id='query'>Query</localization> -->\n    <localization string-id='program-activecode'>ActiveCode</localization>\n    <!-- <localization string-id='scratch-activecode'>Scratch ActiveCode</localization> -->\n    <localization string-id='program-codelens'>CodeLens</localization>\n    <!-- Back matter components -->\n    <localization string-id='index'>Азбучен показалец</localization>\n    <localization string-id='jump-to'>Jump to:</localization>\n    <!-- Parts of the Index -->\n    <localization string-id='see'>Виж</localization>\n    <localization string-id='also'>Виж също</localization>\n    <!-- Notation List headings/foot -->\n    <localization string-id='symbol'>Означение</localization>\n    <localization string-id='description'>Описание</localization>\n    <localization string-id='location'>Местоположение</localization>\n    <localization string-id='page'>Страница</localization>\n    <localization string-id='continued'>Продължава на следващата страница</localization>\n    <!-- Navigation Interface elements -->\n    <localization string-id='skip-to-content'>Главна</localization>\n    <localization string-id='previous'>Предишна</localization>\n    <localization string-id='up'>Нагоре</localization>\n    <localization string-id='next'>Следваща</localization>\n    <localization string-id='previous-short'>Пред</localization>\n    <localization string-id='up-short'>Наг</localization>\n    <localization string-id='next-short'>След</localization>\n    <!-- <localization string-id='top'>Top</localization> -->\n    <localization string-id='annotations'>Annotations</localization>\n    <localization string-id='feedback'>Feedback</localization>\n    <localization string-id='authored'>Направено с</localization>\n    <!-- Search Results display/dialog -->\n    <!-- <localization string-id='search-book'>Search Book</localization> -->\n    <!-- <localization string-id='search-results-heading'>Search Results</localization> -->\n    <!-- <localization string-id='no-search-results'>No results</localization> -->\n    <!-- Parts of memos and letters -->\n    <localization string-id='to'>До</localization>\n    <localization string-id='from'>От</localization>\n    <localization string-id='subject'>Тема</localization>\n    <localization string-id='date'>Дата</localization>\n    <localization string-id='cc'>Също до</localization>\n    <localization string-id='enclosure'>Прикачено</localization>\n    <!-- Various -->\n    <localization string-id='todo'>To Do</localization>\n    <localization string-id='editor'>Editor</localization>\n    <localization string-id='edition'>Edition</localization>\n    <localization string-id='website'>Website</localization>\n    <localization string-id='copyright'>Copyright</localization>\n    <!-- <localization string-id='keywords'>Keywords</localization> -->\n    <!-- HTML clickables (lowercase strings to click on) -->\n    <localization string-id='permalink'>permalink</localization>\n    <localization string-id='incontext'>In Context</localization>\n    <!-- <localization string-id='standalone'>Standalone</localization> -->\n    <!-- <localization string-id='embed'>Embed</localization> -->\n    <!-- <localization string-id='embed-this-page'>Embed this page</localization> -->\n    <!-- <localization string-id='copy'>Copy</localization> -->\n    <!-- <localization string-id='profile'>Profile</localization> -->\n    <!-- Following is in ENGLISH and should be translated.  Due to its -->\n    <!-- ubiquitous nature we have not left it undefined.  See the -->\n    <!-- \"en-US\" file for a more complete explanation of its use. -->\n    <!-- Please remove this entire comment when translated.  Thanks. -->\n    <localization string-id='permalink-tooltip'>Copy heading and permalink for</localization>\n    <!-- <localization string-id='calculator'>Calculator</localization> -->\n    <localization string-id='evaluate'>Evaluate</localization>\n    <!-- <localization string-id='code'>Code</localization> -->\n    <!-- <localization string-id='instructions'>Instructions</localization> -->\n    <!-- <localization string-id='correct'>Correct</localization> -->\n    <!-- <localization string-id='incorrect'>Incorrect</localization> -->\n    <!-- <localization string-id='blank'>Blank</localization> -->\n    <!-- <localization string-id='submit'>Submit</localization> -->\n    <!-- <localization string-id='check-responses'>Check Responses</localization> -->\n    <!-- <localization string-id='reveal'>Reveal</localization> -->\n    <!-- <localization string-id='randomize'>Randomize</localization> -->\n    <!-- <localization string-id='activate'>Activate</localization> -->\n    <!-- <localization string-id='reset'>Reset</localization> -->\n    <!-- <localization string-id='array'>array</localization> -->\n    <!-- <localization string-id=\"papersize\">Paper size</localization> -->\n    <!-- <localization string-id=\"printing-options\">Additional printing options</localization> -->\n    <!-- <localization string-id=\"hide-hints\">Hide hints</localization> -->\n    <!-- <localization string-id=\"hide-answers\">Hide answers</localization> -->\n    <!-- <localization string-id=\"hide-solutions\">Hide solutions</localization> -->\n    <!-- <localization string-id=\"print-header\">Print headers</localization> -->\n    <!-- <localization string-id=\"print-footer\">Print footers</localization> -->\n    <!-- <localization string-id=\"first-page\">First page</localization> -->\n    <!-- <localization string-id=\"running\">Running</localization> -->\n    <!-- <localization string-id=\"highlight-workspace\">Highlight workspace</localization> -->\n    <!-- <localization string-id='print'>Print</localization> -->\n    <!-- <localization string-id='print-preview'>Print preview</localization> -->\n    <!-- <localization string-id='close'>Close</localization> -->\n    <!-- <localization string-id='open-new-tab'>Open in new tab</localization> -->\n    <!-- Readability menu items, HTML only, utilized by Javascript -->\n    <!-- <localization string-id='readability-settings'>Readability settings</localization> -->\n    <!-- <localization string-id='readability-line-height'>Line height</localization> -->\n    <!-- <localization string-id='readability-content-font-size'>Content font size</localization> -->\n    <!-- <localization string-id='readability-theme'>Theme</localization> -->\n    <!-- <localization string-id='readability-theme-system'>System</localization> -->\n    <!-- <localization string-id='readability-theme-light'>Light</localization> -->\n    <!-- <localization string-id='readability-theme-dark'>Dark</localization> -->\n    <!-- <localization string-id='readability-assistive-technologies'>Assistive technologies</localization> -->\n    <!-- <localization string-id='readability-expose-permalinks'>Expose permalinks</localization> -->\n    <!-- <localization string-id='reset-all'>Reset All</localization> -->\n</locale>\n","localizations/ca-ES.xml":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n<!--********************************************************************\nCopyright (C) 2014-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- See  xsl/localizations/README.md  for an explanation of this file -->\n\n<!-- ca-ES, Catalan (Spain) -->\n<!-- Jordi Saludes, jordi.saludes@upc.edu, 2021-07-13 -->\n\n<locale language=\"ca-ES\" direction=\"ltr\"\n        quote-primary=\"english-double\" quote-secondary=\"english-single\">\n    <!-- THEOREM-LIKE blocks -->\n    <!-- The english quotation style above is just a default, it needs adjustment -->\n    <localization string-id='theorem'>Teorema</localization>\n    <localization string-id='corollary'>Corol·lari</localization>\n    <localization string-id='lemma'>Lema</localization>\n    <localization string-id='algorithm'>Algorisme</localization>\n    <localization string-id='proposition'>Proposició</localization>\n    <localization string-id='claim'>Postulat</localization>\n    <localization string-id='fact'>Fet</localization>\n    <localization string-id='identity'>Identitat</localization>\n    <!-- PROOF-LIKE -->\n    <localization string-id='proof'>Demostració</localization>\n    <!-- <localization string-id='argument'>Argument</localization> -->\n    <!-- <localization string-id='justification'>Justification</localization> -->\n    <!-- <localization string-id='reasoning'>Reasoning</localization> -->\n    <!-- <localization string-id='explanation'>Explanation</localization> -->\n    <localization string-id='case'>Cas</localization>\n    <!-- Components of the narrative -->\n    <!-- Mathematical statements without proofs -->\n    <!-- AXIOM-LIKE blocks -->\n    <localization string-id='axiom'>Axioma</localization>\n    <localization string-id='conjecture'>Conjectura</localization>\n    <localization string-id='principle'>Principi</localization>\n    <localization string-id='heuristic'>Heurística</localization>\n    <localization string-id='hypothesis'>Hipótesi</localization>\n    <localization string-id='assumption'>Hipótesi</localization>\n    <!-- Definitions -->\n    <localization string-id='definition'>Definició</localization>\n    <!-- Mathematics -->\n    <localization string-id='equation'>Equació</localization>\n    <localization string-id='displaymath'>Ecuació destacada</localization>\n    <!-- Types of documents, mostly for informational messages -->\n    <localization string-id='volume'>Volum</localization>\n    <localization string-id='book'>Llibre</localization>\n    <localization string-id='article'>Article</localization>\n    <localization string-id='letter'>Carta</localization>\n    <!-- <localization string-id='slideshow'>Slideshow</localization> -->\n    <localization string-id='memo'>Memorándum</localization>\n    <localization string-id='presentation'>Presentació</localization>\n    <!-- Parts of a document -->\n    <localization string-id='frontmatter'>Págines preliminars</localization>\n    <localization string-id='part'>Part</localization>\n    <localization string-id='chapter'>Capítol</localization>\n    <localization string-id='appendix'>Apéndix</localization>\n    <localization string-id='appendices'>Apèndixs</localization>\n    <localization string-id='section'>Secció</localization>\n    <localization string-id='subsection'>Subsecció</localization>\n    <localization string-id='subsubsection'>Subsubsecció</localization>\n    <localization string-id='slide'>Diapositiva</localization>\n    <localization string-id='introduction'>Introducció</localization>\n    <localization string-id='conclusion'>Conclusió</localization>\n    <localization string-id='exercises'>Exercicis</localization>\n    <localization string-id='worksheet'>Full de treball</localization>\n    <!-- <localization string-id='handout'>Handout</localization> -->\n    <localization string-id='reading-questions'>Preguntes de comprensió lectora</localization>\n    <localization string-id='solutions'>Solucions</localization>\n    <localization string-id='glossary'>Glossari</localization>\n    <localization string-id='references'>Referències</localization>\n    <!-- Translation needed for Spain Spanish and Catalan -->\n    <localization string-id='backmatter'>Material posterior</localization>\n    <localization string-id='paragraphs'>Paràgraf</localization>\n    <localization string-id='subparagraph'>Subparàgraf</localization>\n    <!-- Adjustments to titles of divisions -->\n    <!-- <localization string-id='group'>Group</localization> -->\n    <!-- Components of the narrative -->\n    <!-- REMARK-LIKE blocks -->\n    <localization string-id='remark'>Nota</localization>\n    <localization string-id='convention'>Convenció</localization>\n    <localization string-id='note'>Nota</localization>\n    <localization string-id='observation'>Observació</localization>\n    <localization string-id='warning'>Advertiment</localization>\n    <!-- <localization string-id='insight'>Insight</localization> -->\n    <!-- COMPUTATION-LIKE blocks -->\n    <localization string-id='computation'>Computació</localization>\n    <localization string-id='technology'>Tecnologia</localization>\n    <!-- <localization string-id='data'>Data</localization> -->\n    <!-- ASIDE-LIKE blocks -->\n    <!-- <localization string-id='aside'>Aside</localization> -->\n    <!-- <localization string-id='biographical'>Biographical Aside</localization> -->\n    <!-- <localization string-id='historical'>Historical Aside</localization> -->\n    <!-- EXAMPLE-LIKE blocks -->\n    <localization string-id='example'>Exemple</localization>\n    <localization string-id='question'>Pregunta</localization>\n    <localization string-id='problem'>Problema</localization>\n    <!-- PROJECT-LIKE blocks -->\n    <localization string-id='project'>Projecte</localization>\n    <localization string-id='activity'>Activitat</localization>\n    <localization string-id='exploration'>Exploració</localization>\n    <localization string-id='task'>Tasca</localization>\n    <localization string-id='investigation'>Recerca</localization>\n    <!-- <localization string-id='assemblage'>Assemblage</localization> -->\n    <!-- <localization string-id='poem'>Poem</localization> -->\n    <!-- <localization string-id='objectives'>Objectives</localization> -->\n    <!-- <localization string-id='objective'>Objective</localization> -->\n    <!-- <localization string-id='outcomes'>Outcomes</localization> -->\n    <!-- <localization string-id='outcome'>Outcome</localization> -->\n    <!-- <localization string-id='openquestion'>Open Question</localization> -->\n    <!-- <localization string-id='openproblem'>Open Problem</localization> -->\n    <!-- <localization string-id='openconjecture'>Open Conjecture</localization> -->\n    <!-- <localization string-id='context'>Context</localization> -->\n    <!-- <localization string-id='discussion'>Discussion</localization> -->\n    <!-- <localization string-id='opinion'>Opinion</localization> -->\n    <!-- <localization string-id='status'>Status</localization> -->\n    <!-- <localization string-id='suggestion'>Suggestion</localization> -->\n    <localization string-id='figure'>Figura</localization>\n    <localization string-id='table'>Quadre</localization>\n    <localization string-id='listing'>Llistat</localization>\n    <localization string-id='fn'>Nota al peu</localization>\n    <!-- Translation needed for Spain Spanish -->\n    <!-- <localization string-id='contributor'>Contributor</localization> -->\n    <!-- Lists and their items -->\n    <!-- Translations needed for Spain Spanish -->\n    <localization string-id='list'>Llista</localization>\n    <localization string-id='li'>Ítem</localization>\n    <localization string-id='gi'>Terme</localization>\n    <localization string-id='p'>Paràgraf</localization>\n    <localization string-id='blockquote'>Cita</localization>\n    <!-- <localization string-id='pre'>Code Block</localization> -->\n    <localization string-id='fragment'>Fragment</localization>\n    <!-- Parts of an exercise and its solution -->\n    <!-- See the en-US file for a detailed explanation of the words for exercises -->\n    <localization string-id='divisionalexercise'>Exercici</localization>\n    <!-- Translation needed for Spain Spanish -->\n    <!-- See en-US file for distinctions here, do not repeat previous translation -->\n    <localization string-id='inlineexercise'>Punt de control</localization>\n    <!-- <localization string-id='worksheetexercise'>Worksheet Exercise</localization> -->\n    <!-- <localization string-id='readingquestion'>Reading Question</localization> -->\n    <localization string-id='webwork'>WeBWorK</localization>\n    <localization string-id='hint'>Pista</localization>\n    <localization string-id='answer'>Resposta</localization>\n    <localization string-id='solution'>Solució</localization>\n    <!-- Translation needed for Spain Spanish -->\n    <!-- <localization string-id='subexercises'>Subexercises</localization> -->\n    <!-- <localization string-id='exercisegroup'>Exercise Group</localization> -->\n    <!-- <localization string-id='biblio'>Bibliographic Entry</localization> -->\n    <!-- Front matter components -->\n    <localization string-id='toc'>Índex</localization>\n    <localization string-id='abstract'>Resum</localization>\n    <localization string-id='preface'>Prefaci</localization>\n    <localization string-id='acknowledgement'>Agraïments</localization>\n    <localization string-id='biography'>Biografia de l'autor</localization>\n    <localization string-id='about-author'>Sobre l'autor</localization>\n    <localization string-id='about-authors'>Sobre els autors</localization>\n    <localization string-id='foreword'>Pròleg</localization>\n    <localization string-id='dedication'>Dedicatòria</localization>\n    <localization string-id='colophon'>Colofó</localization>\n    <!-- Runestone Activities -->\n    <!-- <localization string-id='video'>Video</localization> -->\n    <!-- <localization string-id='program'>Program</localization> -->\n    <!-- Runestone Exercises -->\n    <!-- <localization string-id='true'>True</localization> -->\n    <!-- <localization string-id='false'>False</localization> -->\n    <!-- <localization string-id='or'>Or</localization> -->\n    <!-- <localization string-id='either'>Either</localization> -->\n    <!-- <localization string-id='uncategorized'>Uncategorized</localization> -->\n    <!-- <localization string-id='query'>Query</localization> -->\n    <localization string-id='program-activecode'>ActiveCode</localization>\n    <!-- <localization string-id='scratch-activecode'>Scratch ActiveCode</localization> -->\n    <localization string-id='program-codelens'>CodeLens</localization>\n    <!-- Back matter components -->\n    <localization string-id='index'>Índex alfabètico</localization>\n    <localization string-id='jump-to'>Passeu a:</localization>\n    <!-- Parts of the Index -->\n    <localization string-id='see'>Vegeu</localization>\n    <localization string-id='also'>Vegeu també</localization>\n    <!-- Notation List headings/foot -->\n    <localization string-id='symbol'>Símbol</localization>\n    <localization string-id='description'>Descripció</localization>\n    <localization string-id='location'>Ubicació</localization>\n    <localization string-id='page'>Página</localization>\n    <localization string-id='continued'>Continua a la página següent</localization>\n    <!-- Navigation Interface elements -->\n    <localization string-id='skip-to-content'>Salta al contingut principal</localization>\n    <localization string-id='previous'>Anterior</localization>\n    <localization string-id='up'>Amunt</localization>\n    <localization string-id='next'>Següent</localization>\n    <!-- TODO: SHORTEN THESE -->\n    <localization string-id='previous-short'>Anterior</localization>\n    <localization string-id='up-short'>Amunt</localization>\n    <localization string-id='next-short'>Següent</localization>\n    <!-- <localization string-id='top'>Top</localization> -->\n    <localization string-id='annotations'>Anotacions</localization>\n    <localization string-id='feedback'>Comentari</localization>\n    <localization string-id='authored'>Fet amb PreTeXt</localization>\n    <!-- Search Results display/dialog -->\n    <!-- <localization string-id='search-book'>Search Book</localization> -->\n    <!-- <localization string-id='search-results-heading'>Search Results</localization> -->\n    <!-- <localization string-id='no-search-results'>No results</localization> -->\n    <!-- Parts of memos and letters -->\n    <localization string-id='to'>A</localization>\n    <localization string-id='from'>De</localization>\n    <localization string-id='subject'>Assumpte</localization>\n    <localization string-id='date'>Data</localization>\n    <localization string-id='cc'>Còpia a</localization>\n    <localization string-id='enclosure'>Adjunt</localization>\n    <!-- Various -->\n    <localization string-id='todo'>A fer</localization>\n    <localization string-id='editor'>Editor</localization>\n    <localization string-id='edition'>Edició</localization>\n    <!-- <localization string-id='website'>Website</localization> -->\n    <localization string-id='copyright'>Drets d'autor</localization>\n    <!-- <localization string-id='keywords'>Keywords</localization> -->\n    <!-- HTML clickables (lowercase strings to click on) -->\n    <localization string-id='permalink'>enllaç permanent</localization>\n    <localization string-id='incontext'>En Context</localization>\n    <!-- <localization string-id='standalone'>Standalone</localization> -->\n    <!-- <localization string-id='embed'>Embed</localization> -->\n    <!-- <localization string-id='embed-this-page'>Embed this page</localization> -->\n    <!-- <localization string-id='copy'>Copy</localization> -->\n    <!-- <localization string-id='profile'>Profile</localization> -->\n    <!-- Following is in ENGLISH and should be translated.  Due to its -->\n    <!-- ubiquitous nature we have not left it undefined.  See the -->\n    <!-- \"en-US\" file for a more complete explanation of its use. -->\n    <!-- Please remove this entire comment when translated.  Thanks. -->\n    <localization string-id='permalink-tooltip'>Copy heading and permalink for</localization>\n    <!-- <localization string-id='calculator'>Calculator</localization> -->\n    <!-- This needs to be defined to *something* (English) -->\n    <!-- Translate at first opportunity, please -->\n    <localization string-id='evaluate'>Avaluar</localization>\n    <!-- <localization string-id='code'>Code</localization> -->\n    <!-- <localization string-id='instructions'>Instructions</localization> -->\n    <!-- <localization string-id='correct'>Correct</localization> -->\n    <!-- <localization string-id='incorrect'>Incorrect</localization> -->\n    <!-- <localization string-id='blank'>Blank</localization> -->\n    <!-- <localization string-id='submit'>Submit</localization> -->\n    <!-- <localization string-id='check-responses'>Check Responses</localization> -->\n    <!-- <localization string-id='reveal'>Reveal</localization> -->\n    <!-- <localization string-id='randomize'>Randomize</localization> -->\n    <!-- <localization string-id='activate'>Activate</localization> -->\n    <!-- <localization string-id='reset'>Reset</localization> -->\n    <!-- <localization string-id='array'>array</localization> -->\n    <!-- <localization string-id=\"papersize\">Paper size</localization> -->\n    <!-- <localization string-id=\"printing-options\">Additional printing options</localization> -->\n    <!-- <localization string-id=\"hide-hints\">Hide hints</localization> -->\n    <!-- <localization string-id=\"hide-answers\">Hide answers</localization> -->\n    <!-- <localization string-id=\"hide-solutions\">Hide solutions</localization> -->\n    <!-- <localization string-id=\"print-header\">Print headers</localization> -->\n    <!-- <localization string-id=\"print-footer\">Print footers</localization> -->\n    <!-- <localization string-id=\"first-page\">First page</localization> -->\n    <!-- <localization string-id=\"running\">Running</localization> -->\n    <!-- <localization string-id=\"highlight-workspace\">Highlight workspace</localization> -->\n    <!-- <localization string-id='print'>Print</localization> -->\n    <!-- <localization string-id='print-preview'>Print preview</localization> -->\n    <!-- <localization string-id='close'>Close</localization> -->\n    <!-- <localization string-id='open-new-tab'>Open in new tab</localization> -->\n    <!-- Readability menu items, HTML only, utilized by Javascript -->\n    <!-- <localization string-id='readability-settings'>Readability settings</localization> -->\n    <!-- <localization string-id='readability-line-height'>Line height</localization> -->\n    <!-- <localization string-id='readability-content-font-size'>Content font size</localization> -->\n    <!-- <localization string-id='readability-theme'>Theme</localization> -->\n    <!-- <localization string-id='readability-theme-system'>System</localization> -->\n    <!-- <localization string-id='readability-theme-light'>Light</localization> -->\n    <!-- <localization string-id='readability-theme-dark'>Dark</localization> -->\n    <!-- <localization string-id='readability-assistive-technologies'>Assistive technologies</localization> -->\n    <!-- <localization string-id='readability-expose-permalinks'>Expose permalinks</localization> -->\n    <!-- <localization string-id='reset-all'>Reset All</localization> -->\n</locale>\n","localizations/cs-CZ.xml":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n<!--********************************************************************\nCopyright (C) 2014-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- See  xsl/localizations/README.md  for an explanation of this file -->\n\n<!-- cs-CZ, Czech (Czechia) -->\n<!-- Jiri Lebl, lebl@okstate.edu, 2023-05-21   -->\n\n<locale language=\"cs-CZ\" direction=\"ltr\"\n        quote-primary=\"down-up-double\" quote-secondary=\"down-up-single\">\n    <!-- THEOREM-LIKE blocks -->\n    <!-- The english quotation style above is just a default, it needs adjustment -->\n    <localization string-id='theorem'>Teorém</localization>\n    <localization string-id='corollary'>Důsledek</localization>\n    <localization string-id='lemma'>Lemma</localization>\n    <localization string-id='algorithm'>Algoritmus</localization>\n    <localization string-id='proposition'>Věta</localization>\n    <localization string-id='claim'>Tvrzení</localization>\n    <localization string-id='fact'>Fakt</localization>\n    <localization string-id='identity'>Rovnost</localization>\n    <!-- PROOF-LIKE -->\n    <localization string-id='proof'>Důkaz</localization>\n    <localization string-id='argument'>Argument</localization>\n    <localization string-id='justification'>Odůvodnění</localization>\n    <localization string-id='reasoning'>Argumentace</localization>\n    <localization string-id='explanation'>Vysvětlení</localization>\n    <localization string-id='case'>Případ</localization>\n    <!-- Components of the narrative -->\n    <!-- Mathematical statements without proofs -->\n    <!-- AXIOM-LIKE blocks -->\n    <localization string-id='axiom'>Axiom</localization>\n    <localization string-id='conjecture'>Domněnka</localization>\n    <localization string-id='principle'>Princip</localization>\n    <localization string-id='heuristic'>Heurestika</localization>\n    <localization string-id='hypothesis'>Hypotéza</localization>\n    <localization string-id='assumption'>Předpoklad</localization>\n    <!-- Definitions -->\n    <localization string-id='definition'>Definice</localization>\n    <!-- Mathematics -->\n    <localization string-id='equation'>Rovnice</localization>\n    <localization string-id='displaymath'>Zobrazená matematika</localization>\n    <!-- Types of documents, mostly for informational messages -->\n    <localization string-id='volume'>Díl</localization>\n    <localization string-id='book'>Kniha</localization>\n    <localization string-id='article'>Článek</localization>\n    <localization string-id='letter'>Dopis</localization>\n    <localization string-id='slideshow'>Prezentace</localization>\n    <localization string-id='memo'>Sdělení</localization>\n    <localization string-id='presentation'>Prezentace</localization>\n    <!-- Parts of a document -->\n    <localization string-id='frontmatter'>Úvodní část</localization>\n    <localization string-id='part'>Část</localization>\n    <localization string-id='chapter'>Kapitola</localization>\n    <localization string-id='appendix'>Dodatek</localization>\n    <localization string-id='appendices'>Dodatky</localization>\n    <localization string-id='section'>Sekce</localization>\n    <localization string-id='subsection'>Podsekce</localization>\n    <localization string-id='subsubsection'>Podpodsekce</localization>\n    <localization string-id='slide'>Slajd</localization>\n    <localization string-id='introduction'>Úvod</localization>\n    <localization string-id='conclusion'>Závěr</localization>\n    <localization string-id='exercises'>Cvičení</localization>\n    <localization string-id='worksheet'>Pracovní list</localization>\n    <localization string-id='handout'>Handout</localization>\n    <localization string-id='reading-questions'>Otázky ze čtení</localization>\n    <localization string-id='solutions'>Řešení</localization>\n    <localization string-id='glossary'>Vysvětlivky</localization>\n    <localization string-id='references'>Odkazy</localization>\n    <localization string-id='backmatter'>Závěrečná část</localization>\n    <localization string-id='paragraphs'>Odstavce</localization>\n    <localization string-id='subparagraph'>Pododstavec</localization>\n    <!-- Adjustments to titles of divisions -->\n    <localization string-id='group'>Skupina</localization>\n    <!-- Components of the narrative -->\n    <!-- REMARK-LIKE blocks -->\n    <localization string-id='remark'>Poznámka</localization>\n    <localization string-id='convention'>Konvence</localization>\n    <localization string-id='note'>Poznámka</localization>\n    <localization string-id='observation'>Postřeh</localization>\n    <localization string-id='warning'>Varování</localization>\n    <localization string-id='insight'>Nahléd</localization>\n    <!-- COMPUTATION-LIKE blocks -->\n    <localization string-id='computation'>Výpočet</localization>\n    <localization string-id='technology'>Technologie</localization>\n    <localization string-id='data'>Data</localization>\n    <!-- ASIDE-LIKE blocks -->\n    <localization string-id='aside'>Poznámka stranou</localization>\n    <localization string-id='biographical'>Biografická poznámka</localization>\n    <localization string-id='historical'>Historická poznámka</localization>\n    <!-- EXAMPLE-LIKE blocks -->\n    <localization string-id='example'>Příklad</localization>\n    <localization string-id='question'>Otázka</localization>\n    <localization string-id='problem'>Problém</localization>\n    <!-- PROJECT-LIKE blocks -->\n    <localization string-id='project'>Projekt</localization>\n    <localization string-id='activity'>Aktivita</localization>\n    <localization string-id='exploration'>Průzkum</localization>\n    <localization string-id='task'>Úkol</localization>\n    <localization string-id='investigation'>Výzkum</localization>\n    <localization string-id='assemblage'>Soustava</localization>\n    <localization string-id='poem'>Báseň</localization>\n    <localization string-id='objectives'>Cíle</localization>\n    <localization string-id='objective'>Cíl</localization>\n    <localization string-id='outcomes'>Výsledky</localization>\n    <localization string-id='outcome'>Výsledek</localization>\n    <localization string-id='openquestion'>Nevyřešená otázka</localization>\n    <localization string-id='openproblem'>Nevyřešený problém</localization>\n    <localization string-id='openconjecture'>Nevyřešená domněnka</localization>\n    <localization string-id='context'>Kontext</localization>\n    <localization string-id='discussion'>Diskuse</localization>\n    <localization string-id='opinion'>Názor</localization>\n    <localization string-id='status'>Status</localization>\n    <localization string-id='suggestion'>Návrh</localization>\n    <localization string-id='figure'>Obrázek</localization>\n    <localization string-id='table'>Tabulka</localization>\n    <localization string-id='listing'>Výpis</localization>\n    <localization string-id='fn'>Vysvětlivka</localization>\n    <localization string-id='contributor'>Přispěvatel</localization>\n    <!-- Lists and their items -->\n    <localization string-id='list'>Seznam</localization>\n    <localization string-id='li'>Bod</localization>\n    <localization string-id='gi'>Termín</localization>\n    <localization string-id='p'>Odstavec</localization>\n    <localization string-id='blockquote'>Citát</localization>\n    <localization string-id='pre'>Blok kódu</localization>\n    <localization string-id='fragment'>Fragment</localization>\n    <!-- Parts of an exercise and its solution -->\n    <!-- See the en-US file for a detailed explanation of the words for exercises -->\n    <localization string-id='divisionalexercise'>Cvičení</localization>\n    <!-- Translation needed for Czech Czech -->\n    <!-- See en-US file for distinctions here, do not repeat previous translation -->\n    <localization string-id='inlineexercise'>Zkouška</localization>\n    <localization string-id='worksheetexercise'>Cvičení pracovního listu</localization>\n    <localization string-id='readingquestion'>Otázka ze čtení</localization>\n    <localization string-id='webwork'>WeBWorK</localization>\n    <localization string-id='hint'>Nápověda</localization>\n    <localization string-id='answer'>Odpověď</localization>\n    <localization string-id='solution'>Řešení</localization>\n    <localization string-id='subexercises'>Dílčí cvičení</localization>\n    <localization string-id='exercisegroup'>Skupina cvičení</localization>\n    <localization string-id='biblio'>Bibliografický údaj</localization>\n    <!-- Front matter components -->\n    <localization string-id='toc'>Obsah</localization>\n    <localization string-id='abstract'>Abstrakt</localization>\n    <localization string-id='preface'>Předmluva</localization>\n    <localization string-id='acknowledgement'>Poděkování</localization>\n    <localization string-id='biography'>Životopis autora</localization>\n    <localization string-id='about-author'>O autoru</localization>\n    <localization string-id='about-authors'>O autorech</localization>\n    <localization string-id='foreword'>Předmluva</localization>\n    <localization string-id='dedication'>Věnování</localization>\n    <localization string-id='colophon'>Kolofon</localization>\n    <!-- Runestone Activities -->\n    <localization string-id='video'>Video</localization>\n    <localization string-id='program'>Program</localization>\n    <!-- Runestone Exercises -->\n    <localization string-id='true'>Pravda</localization>\n    <localization string-id='false'>Nepravda</localization>\n    <localization string-id='or'>Nebo</localization>\n    <localization string-id='either'>Buď</localization>\n    <localization string-id='uncategorized'>Nezařazeno</localization>\n    <localization string-id='query'>Otázka</localization>\n    <localization string-id='program-activecode'>ActiveCode</localization>\n    <!-- <localization string-id='scratch-activecode'>Scratch ActiveCode</localization> -->\n    <localization string-id='program-codelens'>CodeLens</localization>\n    <!-- Back matter components -->\n    <localization string-id='index'>Rejstřík</localization>\n    <localization string-id='jump-to'>Skoč na:</localization>\n    <!-- Parts of the Index -->\n    <localization string-id='see'>Viz</localization>\n    <localization string-id='also'>Viz také</localization>\n    <!-- Notation List headings/foot -->\n    <localization string-id='symbol'>Symbol</localization>\n    <localization string-id='description'>Popis</localization>\n    <localization string-id='location'>Pozice</localization>\n    <localization string-id='page'>Stránka</localization>\n    <localization string-id='continued'>Pokračuje na další straně</localization>\n    <!-- Navigation Interface elements -->\n    <localization string-id='skip-to-content'>Přeskočit na hlavní obsah</localization>\n    <localization string-id='previous'>Předchozí</localization>\n    <localization string-id='up'>Nahoru</localization>\n    <localization string-id='next'>Další</localization>\n    <localization string-id='previous-short'>Zpět</localization>\n    <localization string-id='up-short'>Výš</localization>\n    <localization string-id='next-short'>Dál</localization>\n    <!-- <localization string-id='top'>Top</localization> -->\n    <localization string-id='annotations'>Anotace</localization>\n    <localization string-id='feedback'>Odezva</localization>\n    <localization string-id='authored'>Napsáno v PreTeXt</localization>\n    <!-- Search Results display/dialog -->\n    <!-- <localization string-id='search-book'>Search Book</localization> -->\n    <localization string-id='search-results-heading'>Výsledky hledání</localization>\n    <localization string-id='no-search-results'>Žádné výsledky</localization>\n    <!-- Parts of memos and letters -->\n    <localization string-id='to'>Komu</localization>\n    <localization string-id='from'>Od</localization>\n    <localization string-id='subject'>Předmět</localization>\n    <localization string-id='date'>Datum</localization>\n    <localization string-id='cc'>Kopie</localization>\n    <localization string-id='enclosure'>Příloha</localization>\n    <!-- Various -->\n    <localization string-id='todo'>To Do</localization>\n    <localization string-id='editor'>Editor</localization>\n    <localization string-id='edition'>Edice</localization>\n    <localization string-id='website'>Webová stránka</localization>\n    <localization string-id='copyright'>Copyright</localization>\n    <localization string-id='keywords'>Kličová slova</localization>\n    <!-- HTML clickables (lowercase strings to click on) -->\n    <localization string-id='permalink'>permalink</localization>\n    <localization string-id='incontext'>V Souvislosti</localization>\n    <!-- <localization string-id='standalone'>Standalone</localization> -->\n    <!-- <localization string-id='embed'>Embed</localization> -->\n    <!-- <localization string-id='embed-this-page'>Embed this page</localization> -->\n    <!-- <localization string-id='copy'>Copy</localization> -->\n    <!-- <localization string-id='profile'>Profile</localization> -->\n    <!-- Following is in ENGLISH and should be translated.  Due to its -->\n    <!-- ubiquitous nature we have not left it undefined.  See the -->\n    <!-- \"en-US\" file for a more complete explanation of its use. -->\n    <!-- Please remove this entire comment when translated.  Thanks. -->\n    <localization string-id='permalink-tooltip'>Copy heading and permalink for</localization>\n    <!-- <localization string-id='calculator'>Calculator</localization> -->\n    <!-- This needs to be defined to *something* (English) -->\n    <!-- Translate at first opportunity, please -->\n    <localization string-id='evaluate'>Ohodnotit</localization>\n    <!-- <localization string-id='code'>Code</localization> -->\n    <localization string-id='instructions'>Instrukce</localization>\n    <localization string-id='correct'>Správně</localization>\n    <localization string-id='incorrect'>Nesprávně</localization>\n    <localization string-id='blank'>Prázdné</localization>\n    <localization string-id='submit'>Podat</localization>\n    <localization string-id='check-responses'>Zkontrolvat odpovědi</localization>\n    <localization string-id='reveal'>Odkrýt</localization>\n    <localization string-id='randomize'>Randomizovat</localization>\n    <localization string-id='activate'>Aktivovat</localization>\n    <localization string-id='reset'>Reset</localization>\n    <localization string-id='array'>pole</localization>\n    <localization string-id=\"papersize\">Velikost papíru</localization>\n    <localization string-id=\"printing-options\">Další možnosti tisku</localization>\n    <localization string-id=\"hide-hints\">Zakrýt nápovědu</localization>\n    <localization string-id=\"hide-answers\">Zakrýt odpovědi</localization>\n    <localization string-id=\"hide-solutions\">Zakrýt řešení</localization>\n    <localization string-id=\"print-header\">Tisknout záhlaví</localization>\n    <localization string-id=\"print-footer\">Tisknout zápatí</localization>\n    <localization string-id=\"first-page\">První strana</localization>\n    <localization string-id=\"running\">Živé</localization>\n    <localization string-id=\"highlight-workspace\">Zvýraznit pracovní plochu</localization>\n    <localization string-id='print'>Tisk</localization>\n    <localization string-id='print-preview'>Náhled tisku</localization>\n    <localization string-id='close'>Zavřít</localization>\n    <localization string-id='open-new-tab'>Otevřít v nové kartě</localization>\n    <!-- Readability menu items, HTML only, utilized by Javascript -->\n    <!-- <localization string-id='readability-settings'>Readability settings</localization> -->\n    <!-- <localization string-id='readability-line-height'>Line height</localization> -->\n    <!-- <localization string-id='readability-content-font-size'>Content font size</localization> -->\n    <!-- <localization string-id='readability-theme'>Theme</localization> -->\n    <!-- <localization string-id='readability-theme-system'>System</localization> -->\n    <!-- <localization string-id='readability-theme-light'>Light</localization> -->\n    <!-- <localization string-id='readability-theme-dark'>Dark</localization> -->\n    <!-- <localization string-id='readability-assistive-technologies'>Assistive technologies</localization> -->\n    <!-- <localization string-id='readability-expose-permalinks'>Expose permalinks</localization> -->\n    <!-- <localization string-id='reset-all'>Reset All</localization> -->\n</locale>\n","localizations/de-DE.xml":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n<!--********************************************************************\nCopyright (C) 2014-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- See  xsl/localizations/README.md  for an explanation of this file -->\n\n<!-- de-DE, German (Germany) -->\n<!-- Karl-Dieter Crisman, kcrisman@gmail.com, 2020-06-01   -->\n\n<locale language=\"de-DE\" direction=\"ltr\"\n        quote-primary=\"down-up-double\" quote-secondary=\"down-up-single\">\n    <!-- THEOREM-LIKE blocks -->\n    <localization string-id='theorem'>Satz</localization>\n    <localization string-id='corollary'>Korollar</localization>\n    <localization string-id='lemma'>Hilfssatz</localization>\n    <localization string-id='algorithm'>Algorithmus</localization>\n    <localization string-id='proposition'>Proposition</localization>\n    <localization string-id='claim'>Behauptung</localization>\n    <localization string-id='fact'>Fakt</localization>\n    <localization string-id='identity'>Identität</localization>\n    <!-- PROOF-LIKE -->\n    <localization string-id='proof'>Beweis</localization>\n    <!-- <localization string-id='argument'>Argument</localization> -->\n    <!-- <localization string-id='justification'>Justification</localization> -->\n    <!-- <localization string-id='reasoning'>Reasoning</localization> -->\n    <!-- <localization string-id='explanation'>Explanation</localization> -->\n    <localization string-id='case'>Fall</localization>\n    <!-- Components of the narrative -->\n    <!-- Mathematical statements without proofs -->\n    <!-- AXIOM-LIKE blocks -->\n    <localization string-id='axiom'>Axiom</localization>\n    <localization string-id='conjecture'>Vermutung</localization>\n    <localization string-id='principle'>Prinzip</localization>\n    <!-- <localization string-id='heuristic'>Heuristic</localization> -->\n    <localization string-id='hypothesis'>Hypothese</localization>\n    <localization string-id='assumption'>Voraussetzung</localization>\n    <!-- Definitions -->\n    <localization string-id='definition'>Definition</localization>\n    <!-- Mathematics -->\n    <localization string-id='equation'>Gleichung</localization>\n    <!-- <localization string-id='displaymath'>Display Mathematics</localization> -->\n    <!-- Types of documents, mostly for informational messages -->\n    <localization string-id='volume'>Band</localization>\n    <localization string-id='book'>Buch</localization>\n    <localization string-id='article'>Artikel</localization>\n    <localization string-id='letter'>Brief</localization>\n    <!-- <localization string-id='slideshow'>Slideshow</localization> -->\n    <localization string-id='memo'>Memo</localization> <!-- oder Memorandum? -->\n    <localization string-id='presentation'>Vortrag</localization>\n    <!-- Parts of a document -->\n    <!-- <localization string-id='frontmatter'>Front Matter</localization> -->\n    <localization string-id='part'>Teil</localization>\n    <localization string-id='chapter'>Kapitel</localization>\n    <localization string-id='appendix'>Anhang</localization>\n    <!-- <localization string-id='appendices'>Appendices</localization> -->\n    <localization string-id='section'>Abschnitt</localization>\n    <localization string-id='subsection'>Unterabschnitt</localization>\n    <localization string-id='subsubsection'>Unterunterabschnitt</localization>\n    <!-- <localization string-id='slide'>Slide</localization> -->\n    <localization string-id='introduction'>Einleitung</localization>\n    <localization string-id='conclusion'>Schluss</localization>\n    <localization string-id='exercises'>Übungen</localization>\n    <localization string-id='worksheet'>Arbeitsblatt</localization>\n    <!-- <localization string-id='handout'>Handout</localization> -->\n    <localization string-id='reading-questions'>Lesefragen</localization>\n    <localization string-id='solutions'>Lösungen</localization>\n    <!-- Wörterverzeichnis scheint viel weniger benutzt zu sein, s. Google ngram -->\n    <localization string-id='glossary'>Glossar</localization>\n    <!-- oder Bibliographie wird auch benutzt -->\n    <localization string-id='references'>Literaturverzeichnis</localization>\n    <!-- <localization string-id='backmatter'>Back Matter</localization> -->\n    <localization string-id='paragraphs'>Absätze</localization>\n    <localization string-id='subparagraph'>Unterabsatz</localization>\n    <!-- Adjustments to titles of divisions -->\n    <!-- <localization string-id='group'>Group</localization> -->\n    <!-- Components of the narrative -->\n    <!-- REMARK-LIKE blocks -->\n    <localization string-id='remark'>Bemerkung</localization>\n    <!-- <localization string-id='convention'>Convention</localization> -->\n    <localization string-id='note'>Vermerk</localization>\n    <!-- Bemerkung versus Anmerkung - I have reserved Anmerkung for footnote -->\n    <localization string-id='observation'>Bemerkung</localization>\n    <localization string-id='warning'>Warnung</localization>\n    <!-- <localization string-id='insight'>Insight</localization> -->\n    <!-- COMPUTATION-LIKE blocks -->\n    <!-- <localization string-id='computation'>Computation</localization> -->\n    <localization string-id='technology'>Technologie</localization>\n    <!-- <localization string-id='data'>Data</localization> -->\n    <!-- ASIDE-LIKE blocks -->\n    <!-- <localization string-id='aside'>Aside</localization> -->\n    <!-- <localization string-id='biographical'>Biographical Aside</localization> -->\n    <!-- <localization string-id='historical'>Historical Aside</localization> -->\n    <!-- EXAMPLE-LIKE blocks -->\n    <localization string-id='example'>Beispiel</localization>\n    <localization string-id='question'>Frage</localization>\n    <localization string-id='problem'>Problem</localization>\n    <!-- PROJECT-LIKE blocks -->\n    <!-- <localization string-id='project'>Project</localization> -->\n    <!-- <localization string-id='activity'>Activity</localization> -->\n    <!-- <localization string-id='exploration'>Exploration</localization> -->\n    <localization string-id='task'>Aufgabe</localization>\n    <!-- <localization string-id='investigation'>Investigation</localization> -->\n    <!-- <localization string-id='assemblage'>Assemblage</localization> -->\n    <localization string-id='poem'>Gedicht</localization>\n    <!-- <localization string-id='objectives'>Objectives</localization> -->\n    <!-- <localization string-id='objective'>Objective</localization> -->\n    <!-- <localization string-id='outcomes'>Outcomes</localization> -->\n    <!-- <localization string-id='outcome'>Outcome</localization> -->\n    <!-- <localization string-id='openquestion'>Open Question</localization> -->\n    <!-- <localization string-id='openproblem'>Open Problem</localization> -->\n    <!-- <localization string-id='openconjecture'>Open Conjecture</localization> -->\n    <!-- <localization string-id='context'>Context</localization> -->\n    <!-- <localization string-id='discussion'>Discussion</localization> -->\n    <!-- <localization string-id='opinion'>Opinion</localization> -->\n    <!-- <localization string-id='status'>Status</localization> -->\n    <!-- <localization string-id='suggestion'>Suggestion</localization> -->\n    <localization string-id='figure'>Figur</localization> <!-- Duden 4b für Figur -->\n    <localization string-id='table'>Tabelle</localization>\n    <!-- <localization string-id='listing'>Listing</localization> -->\n    <localization string-id='fn'>Anmerkung</localization>\n    <!-- <localization string-id='contributor'>Contributor</localization> -->\n    <!-- Lists and their items -->\n    <localization string-id='list'>Liste</localization>\n    <!-- <localization string-id='li'>Item</localization> -->\n    <!-- <localization string-id='gi'>Term</localization> -->\n    <localization string-id='p'>Absatz</localization>\n    <localization string-id='blockquote'>Zitat</localization>\n    <!-- <localization string-id='pre'>Code Block</localization> -->\n    <!-- <localization string-id='fragment'>Fragment</localization> -->\n    <!-- Parts of an exercise and its solution -->\n    <!-- See the en-US file for a detailed explanation of the words for exercises -->\n    <localization string-id='divisionalexercise'>Übung</localization>\n    <!-- <localization string-id='inlineexercise'>Checkpoint</localization> -->\n    <localization string-id='worksheetexercise'>Arbeitsübung</localization>\n    <localization string-id='readingquestion'>Lesefrage</localization>\n    <localization string-id='webwork'>WeBWorK</localization>\n    <localization string-id='hint'>Andeutung</localization>\n    <localization string-id='answer'>Antwort</localization>\n    <localization string-id='solution'>Lösung</localization>\n    <!-- <localization string-id='subexercises'>Subexercises</localization> -->\n    <localization string-id='exercisegroup'>Übungsgruppe</localization>\n    <!-- <localization string-id='biblio'>Bibliographic Entry</localization> -->\n    <!-- Front matter components -->\n    <!-- this one is tough because for short version like in navigation bar Inhalt is fine, but long one in print probably Inhaltsverzeichnis -->\n    <localization string-id='toc'>Inhalt</localization>\n    <localization string-id='abstract'>Zusammenfassung</localization> <!-- or is Abstrakt used? -->\n    <localization string-id='preface'>Einleitung</localization>\n    <!-- <localization string-id='acknowledgement'>Acknowledgements</localization> -->\n    <!-- <localization string-id='biography'>Author Biography</localization> -->\n    <!-- <localization string-id='about-author'>About the Author</localization> -->\n    <!-- <localization string-id='about-authors'>About the Authors</localization> -->\n    <localization string-id='foreword'>Vorwort</localization>\n    <!-- <localization string-id='dedication'>Dedication</localization> -->\n    <!-- <localization string-id='colophon'>Colophon</localization> -->\n    <!-- Runestone Activities -->\n    <!-- <localization string-id='video'>Video</localization> -->\n    <!-- <localization string-id='program'>Program</localization> -->\n    <!-- Runestone Exercises -->\n    <!-- <localization string-id='true'>True</localization> -->\n    <!-- <localization string-id='false'>False</localization> -->\n    <!-- <localization string-id='or'>Or</localization> -->\n    <!-- <localization string-id='either'>Either</localization> -->\n    <!-- <localization string-id='uncategorized'>Uncategorized</localization> -->\n    <!-- <localization string-id='query'>Query</localization> -->\n    <localization string-id='program-activecode'>ActiveCode</localization>\n    <!-- <localization string-id='scratch-activecode'>Scratch ActiveCode</localization> -->\n    <localization string-id='program-codelens'>CodeLens</localization>\n    <!-- Back matter components -->\n    <!-- oder auch Index, siehe http://www.d-indexer.org/frag/grundsatz.html#index -->\n    <localization string-id='index'>Register</localization>\n    <!-- <localization string-id='jump-to'>Jump to:</localization> -->\n    <!-- Parts of the Index -->\n    <!-- see https://online.liverpooluniversitypress.co.uk/doi/pdf/10.3828/indexer.2006.21 for lots more info on peculiarities of German indexing we cannot hope to follow -->\n    <localization string-id='see'>siehe</localization>\n    <localization string-id='also'>siehe auch</localization>\n    <!-- Notation List headings/foot -->\n    <localization string-id='symbol'>Symbol</localization>\n    <localization string-id='description'>Beschreibung</localization>\n    <localization string-id='location'>Stelle</localization>\n    <localization string-id='page'>Seite</localization>\n    <localization string-id='continued'>Nächste Seite weiter</localization>\n    <!-- Navigation Interface elements -->\n    <localization string-id='skip-to-content'>Weiter zum Hauptinhalt</localization>\n    <!-- I am not at all sure of the state of the art on this convention -->\n    <localization string-id='previous'>Zurück</localization>\n    <localization string-id='up'>Oben</localization>\n    <localization string-id='next'>Weiter</localization>\n    <!-- I am even less sure here - can one really shorten \"Weiter\"? -->\n    <localization string-id='previous-short'>Zu</localization>\n    <localization string-id='up-short'>Ob</localization>\n    <localization string-id='next-short'>We</localization>\n    <!-- <localization string-id='top'>Top</localization> -->\n    <!-- <localization string-id='annotations'>Annotations</localization> -->\n    <!-- <localization string-id='feedback'>Feedback</localization> -->\n    <localization string-id='authored'>Mit PreTeXt gebaut</localization>\n    <!-- Search Results display/dialog -->\n    <!-- <localization string-id='search-book'>Search Book</localization> -->\n    <!-- <localization string-id='search-results-heading'>Search Results</localization> -->\n    <!-- <localization string-id='no-search-results'>No results</localization> -->\n    <!-- Parts of memos and letters -->\n    <localization string-id='to'>An</localization>\n    <localization string-id='from'>Von</localization>\n    <!-- <localization string-id='subject'>Subject</localization> -->\n    <!-- <localization string-id='date'>Date</localization> -->\n    <!-- <localization string-id='cc'>cc</localization> -->\n    <!-- <localization string-id='enclosure'>encl</localization> -->\n    <!-- Various -->\n    <!-- <localization string-id='todo'>To Do</localization> -->\n    <!-- Herausgeber seems more at publisher, but not always -->\n    <localization string-id='editor'>Redakteur</localization>\n    <localization string-id='edition'>Auflage</localization>\n    <localization string-id='website'>Website</localization>\n    <localization string-id='copyright'>Urheberrechte</localization>\n    <!-- <localization string-id='keywords'>Keywords</localization> -->\n    <!-- HTML clickables (lowercase strings to click on) -->\n    <localization string-id='permalink'>Permalink</localization>\n    <localization string-id='incontext'>Im Zusammenhang</localization>\n    <!-- <localization string-id='standalone'>Standalone</localization> -->\n    <!-- <localization string-id='embed'>Embed</localization> -->\n    <!-- <localization string-id='embed-this-page'>Embed this page</localization> -->\n    <!-- <localization string-id='copy'>Copy</localization> -->\n    <!-- <localization string-id='profile'>Profile</localization> -->\n    <localization string-id='permalink-tooltip'>Kopiere Bezeichnung und Link zu</localization>\n    <!-- <localization string-id='calculator'>Calculator</localization> -->\n    <!-- Though at least one Sage cell installation uses Auswerten instead -->\n    <localization string-id='evaluate'>Ausführen</localization>\n    <!-- <localization string-id='code'>Code</localization> -->\n    <!-- <localization string-id='instructions'>Instructions</localization> -->\n    <!-- <localization string-id='correct'>Correct</localization> -->\n    <!-- <localization string-id='incorrect'>Incorrect</localization> -->\n    <!-- <localization string-id='blank'>Blank</localization> -->\n    <!-- <localization string-id='submit'>Submit</localization> -->\n    <!-- <localization string-id='check-responses'>Check Responses</localization> -->\n    <!-- <localization string-id='reveal'>Reveal</localization> -->\n    <!-- <localization string-id='randomize'>Randomize</localization> -->\n    <!-- <localization string-id='activate'>Activate</localization> -->\n    <!-- <localization string-id='reset'>Reset</localization> -->\n    <!-- <localization string-id='array'>array</localization> -->\n    <!-- <localization string-id=\"papersize\">Paper size</localization> -->\n    <!-- <localization string-id=\"printing-options\">Additional printing options</localization> -->\n    <!-- <localization string-id=\"hide-hints\">Hide hints</localization> -->\n    <!-- <localization string-id=\"hide-answers\">Hide answers</localization> -->\n    <!-- <localization string-id=\"hide-solutions\">Hide solutions</localization> -->\n    <!-- <localization string-id=\"print-header\">Print headers</localization> -->\n    <!-- <localization string-id=\"print-footer\">Print footers</localization> -->\n    <!-- <localization string-id=\"first-page\">First page</localization> -->\n    <!-- <localization string-id=\"running\">Running</localization> -->\n    <!-- <localization string-id=\"highlight-workspace\">Highlight workspace</localization> -->\n    <!-- <localization string-id='print'>Print</localization> -->\n    <!-- <localization string-id='print-preview'>Print preview</localization> -->\n    <!-- <localization string-id='close'>Close</localization> -->\n    <!-- <localization string-id='open-new-tab'>Open in new tab</localization> -->\n    <!-- Readability menu items, HTML only, utilized by Javascript -->\n    <!-- <localization string-id='readability-settings'>Readability settings</localization> -->\n    <!-- <localization string-id='readability-line-height'>Line height</localization> -->\n    <!-- <localization string-id='readability-content-font-size'>Content font size</localization> -->\n    <!-- <localization string-id='readability-theme'>Theme</localization> -->\n    <!-- <localization string-id='readability-theme-system'>System</localization> -->\n    <!-- <localization string-id='readability-theme-light'>Light</localization> -->\n    <!-- <localization string-id='readability-theme-dark'>Dark</localization> -->\n    <!-- <localization string-id='readability-assistive-technologies'>Assistive technologies</localization> -->\n    <!-- <localization string-id='readability-expose-permalinks'>Expose permalinks</localization> -->\n    <!-- <localization string-id='reset-all'>Reset All</localization> -->\n</locale>\n","localizations/en-US.xml":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n<!--********************************************************************\nCopyright (C) 2014-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- See  xsl/localizations/README.md  for an explanation of this file -->\n\n<!-- en-US, English (United States) -->\n<!-- Robert A. Beezer, beezer@pugetsound.edu, 2014-08-11   -->\n\n<!-- RULES for keeping a translation in sync with this en-US file,    -->\n<!-- which is the template.  (Comments here are documentation; see    -->\n<!-- also  README.md.)                                                -->\n<!--                                                                  -->\n<!-- * Provide the same \"localization\" elements in the same order     -->\n<!--   as en-US.  Strip the comments from any two files and the       -->\n<!--   lists of string-ids should be identical and identically        -->\n<!--   ordered.                                                       -->\n<!-- * For a string you do not translate, leave the en-US line in     -->\n<!--   place, commented out, one element per comment line, indented   -->\n<!--   to match, so it is easy to find and fill in later.             -->\n<!-- * Keep the short heading comments that label groups of strings   -->\n<!--   (e.g. \"AXIOM-LIKE blocks\", \"Various\").  Do not copy the        -->\n<!--   longer explanatory comments; that documentation lives only     -->\n<!--   in en-US.                                                      -->\n<!-- * Do add comments of your own that record tricky translation     -->\n<!--   choices.  Those are kept.                                      -->\n\n<!-- Every localization should specify the direction of the language, -->\n<!-- there is no assumed default.  Left-to-right is \"ltr\" and         -->\n<!-- right-to-left is \"rtl\".  Provide these exactly as written since  -->\n<!-- they can migrate untouched into output (e.g. HTML).              -->\n\n<!-- Every localization should specify two \"styles\" for how       -->\n<!-- primary/outer quote marks are given (double quotes in        -->\n<!-- English) and how secondary/inner quote marks are given       -->\n<!-- (single quotes in English).  Here are the extant styles      -->\n<!-- and crude Unicode versions of how they might look:           -->\n<!--                                                              -->\n<!--     english-single          ‘word’                           -->\n<!--     english-double          “word”                           -->\n<!--     angle-single            ‹word›                           -->\n<!--     angle-double            «word»                           -->\n<!--     angle-single-space      ‹ word ›                         -->\n<!--     angle-double-space      « word »                         -->\n<!--     down-up-single          ‚word’                           -->\n<!--     down-up-double          „word”                           -->\n<!--                                                              -->\n<!-- Maintainers: please use the  pretext-dev  group to discuss   -->\n<!-- what is best for your language.  If a style exists, then it  -->\n<!-- is just a simple edit of the default English values.  New    -->\n<!-- styles require Unicode values and LaTeX macros to be         -->\n<!-- implemented, work which RAB can do easily.  Examples in the  -->\n<!-- sample article can be updated with new languages/countries,  -->\n<!-- or created with iconic quotes from the specific language.    -->\n<!-- The table at Wikipedia is not a bad thing to consult, even   -->\n<!-- if it seems to have some inaccuracies.                       -->\n<!--                                                              -->\n<!--     https://en.wikipedia.org/wiki/Quotation_mark             -->\n\n<locale language=\"en-US\" direction=\"ltr\"\n        quote-primary=\"english-double\" quote-secondary=\"english-single\">\n\n    <!-- THEOREM-LIKE blocks -->\n    <!-- Environments which have proofs, plus proofs themselves -->\n    <localization string-id='theorem'>Theorem</localization>\n    <localization string-id='corollary'>Corollary</localization>\n    <localization string-id='lemma'>Lemma</localization>\n    <localization string-id='algorithm'>Algorithm</localization>\n    <localization string-id='proposition'>Proposition</localization>\n    <localization string-id='claim'>Claim</localization>\n    <localization string-id='fact'>Fact</localization>\n    <localization string-id='identity'>Identity</localization>\n    <!-- PROOF-LIKE -->\n    <!-- We know these five names for PROOF-LIKE have subtle shades of meaning. -->\n    <!-- Provide a good translation for \"proof\" itself, and do your best with   -->\n    <!-- the others.  It is highly likely authors will rename one or more of    -->\n    <!-- the others.                                                            -->\n    <localization string-id='proof'>Proof</localization>\n    <localization string-id='argument'>Argument</localization>\n    <localization string-id='justification'>Justification</localization>\n    <localization string-id='reasoning'>Reasoning</localization>\n    <localization string-id='explanation'>Explanation</localization>\n    <!-- used for a (logical) portion of a proof -->\n    <localization string-id='case'>Case</localization>\n    <!-- Components of the narrative -->\n    <!-- Mathematical statements without proofs -->\n    <!-- AXIOM-LIKE blocks -->\n    <localization string-id='axiom'>Axiom</localization>\n    <localization string-id='conjecture'>Conjecture</localization>\n    <localization string-id='principle'>Principle</localization>\n    <localization string-id='heuristic'>Heuristic</localization>\n    <localization string-id='hypothesis'>Hypothesis</localization>\n    <localization string-id='assumption'>Assumption</localization>\n    <!-- Definitions -->\n    <localization string-id='definition'>Definition</localization>\n    <!--Mathematics -->\n    <!-- \"equation\" is a string signaling one line of displayed mathematics         -->\n    <!-- \"displaymath\" is a string signaling several lines of displayed mathematics -->\n    <!-- The first is for elements like \"me\", \"men\", and \"mrow\"                     -->\n    <!-- The second is for elements like \"md\" and \"mdn\"                             -->\n    <localization string-id='equation'>Equation</localization>\n    <localization string-id='displaymath'>Display Mathematics</localization>\n    <!-- Types of documents, mostly for informational messages -->\n    <localization string-id='volume'>Volume</localization>\n    <localization string-id='book'>Book</localization>\n    <localization string-id='article'>Article</localization>\n    <localization string-id='letter'>Letter</localization>\n    <localization string-id='slideshow'>Slideshow</localization>\n    <localization string-id='memo'>Memo</localization>\n    <localization string-id='presentation'>Presentation</localization>\n    <!-- Parts of a document -->\n    <!-- \"part\" will also be used for a \"stage\" of a WeBWorK problem -->\n    <localization string-id='frontmatter'>Front Matter</localization>\n    <localization string-id='part'>Part</localization>\n    <localization string-id='chapter'>Chapter</localization>\n    <localization string-id='appendix'>Appendix</localization>\n    <!-- Next is the plural of Appendix, used to identify a group of appendix -->\n    <localization string-id='appendices'>Appendices</localization>\n    <localization string-id='section'>Section</localization>\n    <localization string-id='subsection'>Subsection</localization>\n    <localization string-id='subsubsection'>Subsubsection</localization>\n    <!-- A \"slide\" is a screenful of a presentation (Powerpoint, Beamer) -->\n    <localization string-id='slide'>Slide</localization>\n    <localization string-id='introduction'>Introduction</localization>\n    <localization string-id='conclusion'>Conclusion</localization>\n    <localization string-id='exercises'>Exercises</localization>\n    <localization string-id='worksheet'>Worksheet</localization>\n    <localization string-id='handout'>Handout</localization>\n    <localization string-id='reading-questions'>Reading Questions</localization>\n    <localization string-id='solutions'>Solutions</localization>\n    <localization string-id='glossary'>Glossary</localization>\n    <localization string-id='references'>References</localization>\n    <localization string-id='backmatter'>Back Matter</localization>\n    <!-- paragraph is deprecated, getting plural correct is not super critical, just in messages -->\n    <localization string-id='paragraphs'>Paragraphs</localization>\n    <localization string-id='subparagraph'>Subparagraph</localization>\n    <!-- Adjustments to titles of divisions -->\n    <!-- When the a \"worksheet\" or \"exercises\" is marked as being  -->\n    <!-- \"group work\" the default title gets prefaced with \"Group\". -->\n    <localization string-id='group'>Group</localization>\n    <!-- Components of the narrative -->\n    <!-- REMARK-LIKE blocks -->\n    <!-- \"note\" is used within \"biblio\", likely to change -->\n    <localization string-id='remark'>Remark</localization>\n    <localization string-id='convention'>Convention</localization>\n    <localization string-id='note'>Note</localization>\n    <localization string-id='observation'>Observation</localization>\n    <localization string-id='warning'>Warning</localization>\n    <localization string-id='insight'>Insight</localization>\n    <!-- COMPUTATION-LIKE blocks -->\n    <localization string-id='computation'>Computation</localization>\n    <localization string-id='technology'>Technology</localization>\n    <localization string-id='data'>Data</localization>\n    <!-- ASIDE-LIKE blocks -->\n    <localization string-id='aside'>Aside</localization>\n    <localization string-id='biographical'>Biographical Aside</localization>\n    <localization string-id='historical'>Historical Aside</localization>\n    <!-- EXAMPLE-LIKE blocks -->\n    <localization string-id='example'>Example</localization>\n    <localization string-id='question'>Question</localization>\n    <localization string-id='problem'>Problem</localization>\n    <!-- PROJECT-LIKE blocks -->\n    <localization string-id='project'>Project</localization>\n    <localization string-id='activity'>Activity</localization>\n    <localization string-id='exploration'>Exploration</localization>\n    <localization string-id='task'>Task</localization>\n    <localization string-id='investigation'>Investigation</localization>\n    <!-- assemblages are collections of minimally structured material -->\n    <localization string-id='assemblage'>Assemblage</localization>\n    <localization string-id='poem'>Poem</localization>\n    <!-- Objectives is the block, objective is a list item within -->\n    <localization string-id='objectives'>Objectives</localization>\n    <localization string-id='objective'>Objective</localization>\n    <!-- Outcomes is the block, outcome is a list item within (different) -->\n    <!-- These two words need to be different, to avoid ambiguous cross-references -->\n    <localization string-id='outcomes'>Outcomes</localization>\n    <localization string-id='outcome'>Outcome</localization>\n    <!-- \"Open\" means unsolved, a research question/problem -->\n    <localization string-id='openquestion'>Open Question</localization>\n    <localization string-id='openproblem'>Open Problem</localization>\n    <localization string-id='openconjecture'>Open Conjecture</localization>\n    <!-- \"discussion\" on open problems -->\n    <localization string-id='context'>Context</localization>\n    <localization string-id='discussion'>Discussion</localization>\n    <localization string-id='opinion'>Opinion</localization>\n    <localization string-id='status'>Status</localization>\n    <localization string-id='suggestion'>Suggestion</localization>\n    <!--  -->\n    <localization string-id='figure'>Figure</localization>\n    <localization string-id='table'>Table</localization>\n    <localization string-id='listing'>Listing</localization>\n    <localization string-id='fn'>Footnote</localization>\n    <localization string-id='contributor'>Contributor</localization>\n    <!-- Lists and their items -->\n    <localization string-id='list'>List</localization>\n    <localization string-id='li'>Item</localization>\n    <!-- A term (word) defined in a glossary item -->\n    <localization string-id='gi'>Term</localization>\n    <!-- A regular paragraph, not the old sectioning structure -->\n    <localization string-id='p'>Paragraph</localization>\n    <localization string-id='blockquote'>Quotation</localization>\n    <!-- The \"pre\" element is short for \"preformatted text\".  PreTeXt uses it -->\n    <!-- more as paragraph, rendered in monospace, with newlines respected. -->\n    <localization string-id='pre'>Code Block</localization>\n    <!-- Literate programming, a chunk of computer code -->\n    <localization string-id='fragment'>Fragment</localization>\n    <!-- Parts of an exercise and its solution -->\n    <!-- An \"exercise\", at any level, within an \"exercises\" division is a          -->\n    <!-- \"divisional\" exercise and the string employed is 'divisionalexercise'.    -->\n    <!-- An \"exercise\" whose parent is a division (chapter, section, etc) we       -->\n    <!-- call an \"inline exercise\" and the string employed is 'inlineexercise'.    -->\n    <!-- And an \"exercise\" in a \"worksheet\" is a 'worksheetexercise'.              -->\n    <!-- And an \"exercise\" in a \"reading-questions\" is a 'readingquestion'.         -->\n    <!-- It is important to use different translations so that a text with         -->\n    <!-- different types of exercises do not have ambiguous cross-references       -->\n    <!-- (there is an example of this at the start of one of the later             -->\n    <!-- sections of the sample article).                                          -->\n    <!--                                                                           -->\n    <!-- In English, an \"Exercise\" is something you do that has a beneficial       -->\n    <!-- outcome, such as \"I am going to the gym to exercise.\"  A \"Checkpoint\"     -->\n    <!-- is something you must do before you do something else.  Another use of    -->\n    <!-- the term is a location on a roadway where you must stop for the      -->\n    <!-- police to do an inspection. A worksheet is a collection of activities or  -->\n    <!-- problems, typically printed on paper, which might be used in a classroom. -->\n    <localization string-id='divisionalexercise'>Exercise</localization>\n    <localization string-id='inlineexercise'>Checkpoint</localization>\n    <localization string-id='worksheetexercise'>Worksheet Exercise</localization>\n    <localization string-id='readingquestion'>Reading Question</localization>\n    <localization string-id='webwork'>WeBWorK</localization>\n    <localization string-id='hint'>Hint</localization>\n    <localization string-id='answer'>Answer</localization>\n    <localization string-id='solution'>Solution</localization>\n    <!-- A subdivision of an \"exercises\" section -->\n    <localization string-id='subexercises'>Subexercises</localization>\n    <!-- A group of divisional exercises (with introduction and conclusion) -->\n    <localization string-id='exercisegroup'>Exercise Group</localization>\n    <!-- Bibliographic items (note is distinct from sidebar \"Annotations\" below) -->\n    <localization string-id='biblio'>Bibliographic Entry</localization>\n    <!-- Front matter components -->\n    <localization string-id='toc'>Contents</localization>\n    <localization string-id='abstract'>Abstract</localization>\n    <localization string-id='preface'>Preface</localization>\n    <localization string-id='acknowledgement'>Acknowledgements</localization>\n    <localization string-id='biography'>Author Biography</localization>\n    <!-- singular and plural titles for biography subdivision -->\n    <localization string-id='about-author'>About the Author</localization>\n    <localization string-id='about-authors'>About the Authors</localization>\n    <localization string-id='foreword'>Foreword</localization>\n    <localization string-id='dedication'>Dedication</localization>\n    <localization string-id='colophon'>Colophon</localization>\n    <!-- Runestone Activities -->\n    <!-- These terms will appear in student activity/engagement -->\n    <!-- reports for an instructor of a Runestone course.       -->\n    <!-- Normally they will not be apparent to a reader.        -->\n    <localization string-id='video'>Video</localization>\n    <localization string-id='program'>Program</localization>\n    <!-- Runestone Exercises -->\n    <!-- These terms will appear in static versions of  -->\n    <!-- Runestone exercises, such as a True/False question. -->\n    <localization string-id='true'>True</localization>\n    <localization string-id='false'>False</localization>\n    <localization string-id='or'>Or</localization>\n    <localization string-id='either'>Either</localization>\n    <localization string-id='uncategorized'>Uncategorized</localization>\n    <localization string-id='query'>Query</localization>\n    <!-- \"ActiveCode\" and \"CodeLens\" are Runestone-constructs -->\n    <!-- and so really *should not* be translated.            -->\n    <localization string-id='program-activecode'>ActiveCode</localization>\n    <localization string-id='scratch-activecode'>Scratch ActiveCode</localization>\n    <localization string-id='program-codelens'>CodeLens</localization>\n    <!-- Back matter components -->\n    <!-- index-part is deprecated, but not abandoned          -->\n    <!-- NB: repurpose translations, maybe move appendix here -->\n    <localization string-id='index'>Index</localization>\n    <localization string-id='jump-to'>Jump to:</localization>\n    <!-- Parts of the Index -->\n    <localization string-id='see'>See</localization>\n    <localization string-id='also'>See also</localization>\n    <!-- Notation List headings/foot -->\n    <localization string-id='symbol'>Symbol</localization>\n    <localization string-id='description'>Description</localization>\n    <localization string-id='location'>Location</localization>\n    <localization string-id='page'>Page</localization>\n    <localization string-id='continued'>Continued on next page</localization>\n    <!-- Navigation Interface elements -->\n    <!-- Assistive \"skip to content\" link -->\n    <localization string-id='skip-to-content'>Skip to main content</localization>\n    <localization string-id='previous'>Previous</localization>\n    <localization string-id='up'>Up</localization>\n    <localization string-id='next'>Next</localization>\n    <!-- Keep these short, so buttons are not overly wide, 4 characters maximum -->\n    <localization string-id='previous-short'>Prev</localization>\n    <localization string-id='up-short'>Up</localization>\n    <localization string-id='next-short'>Next</localization>\n    <localization string-id='top'>Top</localization>\n    <!-- NB: Use toc from above for both headings and navigation sidebar-->\n    <localization string-id='annotations'>Annotations</localization>\n    <localization string-id='feedback'>Feedback</localization>\n    <!-- This phrase should suggest that PreTeXt is the source -->\n    <!-- language that makes a particular output possible      -->\n    <localization string-id='authored'>Authored in PreTeXt</localization>\n    <!-- Search Results display/dialog -->\n    <!-- The result of a search as part of HTML output will throw up       -->\n    <!-- an overlay window with the search results.  \"Search Results\"      -->\n    <!-- is like a heading.  It renders like \"Search Results: algorithm\".  -->\n    <!-- When a reader uses a term that produces no results (perhaps they  -->\n    <!-- misspell the search term) then they get a message to that effect. -->\n    <!-- Capitalize \"Search Results\" - used as a heading, no punctuation   -->\n    <localization string-id='search-book'>Search Book</localization>\n    <localization string-id='search-results-heading'>Search Results</localization>\n    <!-- Short phrase, no punctuation -->\n    <localization string-id='no-search-results'>No results</localization>\n   <!-- Parts of memos and letters -->\n    <localization string-id='to'>To</localization>\n    <localization string-id='from'>From</localization>\n    <localization string-id='subject'>Subject</localization>\n    <localization string-id='date'>Date</localization>\n    <localization string-id='cc'>cc</localization>\n    <localization string-id='enclosure'>encl</localization>\n    <!-- Various -->\n    <localization string-id='todo'>To Do</localization>\n    <localization string-id='editor'>Editor</localization>\n    <localization string-id='edition'>Edition</localization>\n    <localization string-id='website'>Website</localization>\n    <localization string-id='copyright'>Copyright</localization>\n    <localization string-id='keywords'>Keywords</localization>\n    <!-- HTML clickables (lowercase strings to click on) -->\n    <localization string-id='permalink'>permalink</localization>\n    <localization string-id='incontext'>In Context</localization>\n    <!-- Static representations of audio, video, and interactive  -->\n    <!-- elements link to the HTML version.  \"standalone\" is for  -->\n    <!-- the dedicated page, \"embed\" is for the embeddable iframe -->\n    <localization string-id='standalone'>Standalone</localization>\n    <localization string-id='embed'>Embed</localization>\n    <localization string-id='embed-this-page'>Embed this page</localization>\n    <localization string-id='copy'>Copy</localization>\n    <localization string-id='profile'>Profile</localization>\n    <!-- A permalink icon in HTML output will have a tooltip (on hover) -->\n    <!-- that says something like                                       -->\n    <!--                                                                -->\n    <!--    Copy heading and permalink for Theorem 5.8 The Chain Rule   -->\n    <!--    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                              -->\n    <!--                                                                -->\n    <!-- The indicated portion will be localized.  \"heading\" might be   -->\n    <!-- replaced by \"description\" if that is easier to translate.      -->\n    <localization string-id='permalink-tooltip'>Copy heading and permalink for</localization>\n    <localization string-id='calculator'>Calculator</localization>\n    <!-- Sage Cell evaluate button      -->\n    <!-- eg, \"Evaluate (Maxima)\"        -->\n    <!-- 2017-05-14: 'code' is obsolete -->\n    <!-- This needs to be defined to *something* (always)       -->\n    <!-- else whatever crud ends up on the button kills the cell -->\n    <localization string-id='evaluate'>Evaluate</localization>\n    <!-- <localization string-id='code'>Code</localization> -->\n    <!-- How to run an interactive widget, sliders, checkboxes, etc -->\n    <localization string-id='instructions'>Instructions</localization>\n    <!-- Interactive exercise feedback messages                   -->\n    <!-- These might be part of a feedback message for submitting -->\n    <!-- an answer, e.g. \"Correct!\" or \"Correct: 50%\".            -->\n    <localization string-id='correct'>Correct</localization>\n    <localization string-id='incorrect'>Incorrect</localization>\n    <!-- To signal that a reader left an answer blank             -->\n    <localization string-id='blank'>Blank</localization>\n    <!-- Submit or check responses                                -->\n    <localization string-id='submit'>Submit</localization>\n    <localization string-id='check-responses'>Check Responses</localization>\n    <!-- Reveal correct answers                                   -->\n    <localization string-id='reveal'>Reveal</localization>\n    <!-- Randomize parameters for a randomizable exercise         -->\n    <localization string-id='randomize'>Randomize</localization>\n    <!-- Activate an interactive (from a static preview)          -->\n    <localization string-id='activate'>Activate</localization>\n    <!-- Reset an interactive to its original state               -->\n    <localization string-id='reset'>Reset</localization>\n    <!-- Describe an array of fill-in-the-blanks, say for a matrix -->\n    <localization string-id='array'>array</localization>\n    <!-- \"paper size\" toggle title                                -->\n    <localization string-id=\"papersize\">Paper size</localization>\n    <!-- Additional printing options -->\n    <localization string-id=\"printing-options\">Additional printing options</localization>\n    <!-- \"hide hint/answer/solutions\" toggle title                         -->\n    <localization string-id=\"hide-hints\">Hide hints</localization>\n    <localization string-id=\"hide-answers\">Hide answers</localization>\n    <localization string-id=\"hide-solutions\">Hide solutions</localization>\n    <!-- \"header/footer\" toggle title                         -->\n    <localization string-id=\"print-header\">Print headers</localization>\n    <localization string-id=\"print-footer\">Print footers</localization>\n    <localization string-id=\"first-page\">First page</localization>\n    <localization string-id=\"running\">Running</localization>\n    <!-- \"highlight workspace\" toggle title                         -->\n    <localization string-id=\"highlight-workspace\">Highlight workspace</localization>\n    <!-- Print page button text                                   -->\n    <localization string-id='print'>Print</localization>\n    <!-- Print preview tooltip/title text                         -->\n    <localization string-id='print-preview'>Print preview</localization>\n    <!-- Close something interactive                              -->\n    <localization string-id='close'>Close</localization>\n    <localization string-id='open-new-tab'>Open in new tab</localization>\n    <!-- Readability menu items, HTML only, utilized by Javascript -->\n    <localization string-id='readability-settings'>Readability settings</localization>\n    <localization string-id='readability-line-height'>Line height</localization>\n    <localization string-id='readability-content-font-size'>Content font size</localization>\n    <localization string-id='readability-theme'>Theme</localization>\n    <localization string-id='readability-theme-system'>System</localization>\n    <localization string-id='readability-theme-light'>Light</localization>\n    <localization string-id='readability-theme-dark'>Dark</localization>\n    <localization string-id='readability-assistive-technologies'>Assistive technologies</localization>\n    <localization string-id='readability-expose-permalinks'>Expose permalinks</localization>\n    <localization string-id='reset-all'>Reset All</localization>\n</locale>\n","localizations/es-ES.xml":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n<!--********************************************************************\nCopyright (C) 2014-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- See  xsl/localizations/README.md  for an explanation of this file -->\n\n<!-- es-ES, Spanish (Spain) -->\n<!-- Juan José Torrens, jjtorrens@unavarra.es, 2014-10-27 -->\n<!-- Julian Pfeifle, julian.pfeifle@upc.edu, 2020-05-28 -->\n<!-- Christian Chávez, christian.chavez@usherbrooke.ca, 2025-12-20 -->\n\n\n<locale language=\"es-ES\" direction=\"ltr\"\n        quote-primary=\"english-double\" quote-secondary=\"english-single\">\n    <!-- THEOREM-LIKE blocks -->\n    <!-- The english quotation style above is just a default, it needs adjustment -->\n    <localization string-id='theorem'>Teorema</localization>\n    <localization string-id='corollary'>Corolario</localization>\n    <localization string-id='lemma'>Lema</localization>\n    <localization string-id='algorithm'>Algoritmo</localization>\n    <localization string-id='proposition'>Proposición</localization>\n    <localization string-id='claim'>Postulado</localization>\n    <localization string-id='fact'>Hecho</localization>\n    <localization string-id='identity'>Identidad</localization>\n    <!-- PROOF-LIKE -->\n    <localization string-id='proof'>Demostración</localization>\n    <localization string-id='argument'>Argumento</localization>\n    <localization string-id='justification'>Justificación</localization>\n    <localization string-id='reasoning'>Razonamiento</localization>\n    <localization string-id='explanation'>Explicación</localization>\n    <localization string-id='case'>Caso</localization>\n    <!-- Components of the narrative -->\n    <!-- Mathematical statements without proofs -->\n    <!-- AXIOM-LIKE blocks -->\n    <localization string-id='axiom'>Axioma</localization>\n    <localization string-id='conjecture'>Conjetura</localization>\n    <localization string-id='principle'>Principio</localization>\n    <localization string-id='heuristic'>Heurística</localization>\n    <localization string-id='hypothesis'>Hipótesis</localization>\n    <localization string-id='assumption'>Hipótesis</localization>\n    <!-- Definitions -->\n    <localization string-id='definition'>Definición</localization>\n    <!-- Mathematics -->\n    <localization string-id='equation'>Ecuación</localization>\n    <localization string-id='displaymath'>Ecuación resaltada</localization>\n    <!-- Types of documents, mostly for informational messages -->\n    <localization string-id='volume'>Volumen</localization>\n    <localization string-id='book'>Libro</localization>\n    <localization string-id='article'>Artículo</localization>\n    <localization string-id='letter'>Carta</localization>\n    <localization string-id='slideshow'>Diapositivas</localization>\n    <localization string-id='memo'>Memorándum</localization>\n    <localization string-id='presentation'>Presentación</localization>\n    <!-- Parts of a document -->\n    <localization string-id='frontmatter'>Páginas preliminares</localization>\n    <localization string-id='part'>Parte</localization>\n    <localization string-id='chapter'>Capítulo</localization>\n    <localization string-id='appendix'>Apéndice</localization>\n    <localization string-id='appendices'>Apéndices</localization>\n    <localization string-id='section'>Sección</localization>\n    <localization string-id='subsection'>Subsección</localization>\n    <localization string-id='subsubsection'>Subsubsección</localization>\n    <localization string-id='slide'>Diapositiva</localization>\n    <localization string-id='introduction'>Introducción</localization>\n    <localization string-id='conclusion'>Conclusión</localization>\n    <localization string-id='exercises'>Ejercicios</localization>\n    <localization string-id='worksheet'>Hoja de trabajo</localization>\n    <localization string-id='handout'>Folleto</localization>\n    <localization string-id='reading-questions'>Preguntas de comprensión</localization>\n    <localization string-id='solutions'>Soluciones</localization>\n    <localization string-id='glossary'>Glosario</localization>\n    <localization string-id='references'>Referencias</localization>\n    <localization string-id='backmatter'>Paratexto final</localization>\n    <localization string-id='paragraphs'>Párrafo</localization>\n    <localization string-id='subparagraph'>Subpárrafo</localization>\n    <!-- Adjustments to titles of divisions -->\n    <localization string-id='group'>Grupo</localization>\n    <!-- Components of the narrative -->\n    <!-- REMARK-LIKE blocks -->\n    <localization string-id='remark'>Nota</localization>\n    <localization string-id='convention'>Convención</localization>\n    <localization string-id='note'>Nota</localization>\n    <localization string-id='observation'>Observación</localization>\n    <localization string-id='warning'>Advertencia</localization>\n    <localization string-id='insight'>Perspectiva</localization>\n    <!-- COMPUTATION-LIKE blocks -->\n    <localization string-id='computation'>Computación</localization>\n    <localization string-id='technology'>Tecnología</localization>\n    <localization string-id='data'>Datos</localization>\n    <!-- ASIDE-LIKE blocks -->\n    <localization string-id='aside'>Comentario</localization>\n    <localization string-id='biographical'>Nota biográfica</localization>\n    <localization string-id='historical'>Nota histórica</localization>\n    <!-- EXAMPLE-LIKE blocks -->\n    <localization string-id='example'>Ejemplo</localization>\n    <localization string-id='question'>Pregunta</localization>\n    <localization string-id='problem'>Problema</localization>\n    <!-- PROJECT-LIKE blocks -->\n    <localization string-id='project'>Proyecto</localization>\n    <localization string-id='activity'>Actividad</localization>\n    <localization string-id='exploration'>Exploración</localization>\n    <localization string-id='task'>Tarea</localization>\n    <localization string-id='investigation'>Investigación</localization>\n    <localization string-id='assemblage'>Colección</localization>\n    <localization string-id='poem'>Poema</localization>\n    <localization string-id='objectives'>Objetivos</localization>\n    <localization string-id='objective'>Objetivo</localization>\n    <localization string-id='outcomes'>Resultados</localization>\n    <localization string-id='outcome'>Resultado</localization>\n    <localization string-id='openquestion'>Pregunta abierta</localization>\n    <localization string-id='openproblem'>Problema abierto</localization>\n    <localization string-id='openconjecture'>Conjetura abierta</localization>\n    <localization string-id='context'>Contexto</localization>\n    <localization string-id='discussion'>Discusión</localization>\n    <localization string-id='opinion'>Opinión</localization>\n    <localization string-id='status'>Estado</localization>\n    <localization string-id='suggestion'>Sugerencia</localization>\n    <localization string-id='figure'>Figura</localization>\n    <localization string-id='table'>Cuadro</localization>\n    <localization string-id='listing'>Listado</localization>\n    <localization string-id='fn'>Nota a pie de página</localization>\n    <!-- Translation needed for Spain Spanish -->\n    <localization string-id='contributor'>Contribuyente</localization>\n    <!-- Lists and their items -->\n    <!-- Translations needed for Spain Spanish -->\n    <localization string-id='list'>Lista</localization>\n    <localization string-id='li'>Ítem</localization>\n    <localization string-id='gi'>Término</localization>\n    <localization string-id='p'>Párrafo</localization>\n    <localization string-id='blockquote'>Cita</localization>\n    <localization string-id='pre'>Bloque de código</localization>\n    <localization string-id='fragment'>Fragmento</localization>\n    <!-- Parts of an exercise and its solution -->\n    <!-- See the en-US file for a detailed explanation of the words for exercises -->\n    <localization string-id='divisionalexercise'>Ejercicio</localization>\n    <!-- Translation needed for Spain Spanish -->\n    <!-- See en-US file for distinctions here, do not repeat previous translation -->\n    <localization string-id='inlineexercise'>Punto de control</localization>\n    <localization string-id='worksheetexercise'>Ejercicio de hoja de trabajo</localization>\n    <localization string-id='readingquestion'>Pregunta de lectura</localization>\n    <localization string-id='webwork'>WeBWorK</localization>\n    <localization string-id='hint'>Pista</localization>\n    <localization string-id='answer'>Respuesta</localization>\n    <localization string-id='solution'>Solución</localization>\n    <!-- Translation needed for Spain Spanish -->\n    <localization string-id='subexercises'>Subejercicios</localization>\n    <localization string-id='exercisegroup'>Grupo de ejercicios</localization>\n    <localization string-id='biblio'>Entrada bibliográfica</localization>\n    <!-- Front matter components -->\n    <localization string-id='toc'>Índice</localization>\n    <localization string-id='abstract'>Resumen</localization>\n    <localization string-id='preface'>Prefacio</localization>\n    <localization string-id='acknowledgement'>Agradecimentos</localization>\n    <localization string-id='biography'>Biografía del autor</localization>\n    <localization string-id='about-author'>Sobre el autor</localization>\n    <localization string-id='about-authors'>Sobre los autores</localization>\n    <localization string-id='foreword'>Prólogo</localization>\n    <localization string-id='dedication'>Dedicatoria</localization>\n    <localization string-id='colophon'>Colofón</localization>\n    <!-- Runestone Activities -->\n    <localization string-id='video'>Vídeo</localization>\n    <localization string-id='program'>Programa</localization>\n    <!-- Runestone Exercises -->\n    <localization string-id='true'>Verdadero</localization>\n    <localization string-id='false'>Falso</localization>\n    <localization string-id='or'>O</localization>\n    <localization string-id='either'>Cualquiera</localization>\n    <localization string-id='uncategorized'>Sin categoría</localization>\n    <localization string-id='query'>Consulta</localization>\n    <localization string-id='program-activecode'>ActiveCode</localization>\n    <!-- <localization string-id='scratch-activecode'>Scratch ActiveCode</localization> -->\n    <localization string-id='program-codelens'>CodeLens</localization>\n    <!-- Back matter components -->\n    <localization string-id='index'>Índice alfabético</localization>\n    <localization string-id='jump-to'>Ir a:</localization>\n    <!-- Parts of the Index -->\n    <localization string-id='see'>Véase</localization>\n    <localization string-id='also'>Véase también</localization>\n    <!-- Notation List headings/foot -->\n    <localization string-id='symbol'>Símbolo</localization>\n    <localization string-id='description'>Descripción</localization>\n    <localization string-id='location'>Ubicación</localization>\n    <localization string-id='page'>Página</localization>\n    <localization string-id='continued'>Continúa en la página siguiente</localization>\n    <!-- Navigation Interface elements -->\n    <localization string-id='skip-to-content'>Salta al contenido principal</localization>\n    <localization string-id='previous'>Anterior</localization>\n    <localization string-id='up'>Arriba</localization>\n    <localization string-id='next'>Siguiente</localization>\n    <!-- TODO: SHORTEN THESE -->\n    <localization string-id='previous-short'>Ant.</localization>\n    <localization string-id='up-short'>Subir</localization>\n    <localization string-id='next-short'>Sig.</localization>\n    <!-- <localization string-id='top'>Top</localization> -->\n    <localization string-id='annotations'>Anotaciones</localization>\n    <localization string-id='feedback'>Comentario</localization>\n    <localization string-id='authored'>Realizado con PreTeXt</localization>\n    <!-- Search Results display/dialog -->\n    <!-- <localization string-id='search-book'>Search Book</localization> -->\n    <localization string-id='search-results-heading'>Resultados de la búsqueda</localization>\n    <localization string-id='no-search-results'>Sin resultados</localization>\n    <!-- Parts of memos and letters -->\n    <localization string-id='to'>A</localization>\n    <localization string-id='from'>De</localization>\n    <localization string-id='subject'>Asunto</localization>\n    <localization string-id='date'>Fecha</localization>\n    <localization string-id='cc'>Copia a</localization>\n    <localization string-id='enclosure'>Adjunto</localization>\n    <!-- Various -->\n    <localization string-id='todo'>Para hacer</localization>\n    <localization string-id='editor'>Editor</localization>\n    <localization string-id='edition'>Edición</localization>\n    <localization string-id='website'>Sitio web</localization>\n    <localization string-id='copyright'>Derechos de autor</localization>\n    <localization string-id='keywords'>Palabras clave</localization>\n    <!-- HTML clickables (lowercase strings to click on) -->\n    <localization string-id='permalink'>enlace permanente</localization>\n    <localization string-id='incontext'>En Contexto</localization>\n    <!-- <localization string-id='standalone'>Standalone</localization> -->\n    <!-- <localization string-id='embed'>Embed</localization> -->\n    <!-- <localization string-id='embed-this-page'>Embed this page</localization> -->\n    <!-- <localization string-id='copy'>Copy</localization> -->\n    <!-- <localization string-id='profile'>Profile</localization> -->\n    <!-- Following is in ENGLISH and should be translated.  Due to its -->\n    <!-- ubiquitous nature we have not left it undefined.  See the -->\n    <!-- \"en-US\" file for a more complete explanation of its use. -->\n    <!-- Please remove this entire comment when translated.  Thanks. -->\n    <localization string-id='permalink-tooltip'>Copiar encabezado y enlace permanente para</localization>\n    <!-- <localization string-id='calculator'>Calculator</localization> -->\n    <!-- This needs to be defined to *something* (English) -->\n    <!-- Translate at first opportunity, please -->\n    <localization string-id='evaluate'>Evaluar</localization>\n    <!-- <localization string-id='code'>Code</localization> -->\n    <localization string-id='instructions'>Instrucciones</localization>\n    <localization string-id='correct'>Correcto</localization>\n    <localization string-id='incorrect'>Incorrecto</localization>\n    <localization string-id='blank'>En blanco</localization>\n    <localization string-id='submit'>Enviar</localization>\n    <localization string-id='check-responses'>Comprobar respuestas</localization>\n    <localization string-id='reveal'>Revelar</localization>\n    <localization string-id='randomize'>Aleatorizar</localization>\n    <localization string-id='activate'>Activar</localization>\n    <localization string-id='reset'>Reiniciar</localization>\n    <localization string-id='array'>Arreglo</localization>\n    <localization string-id=\"papersize\">Tamaño del papel</localization>\n    <localization string-id=\"printing-options\">Opciones de impresión adicionales</localization>\n    <localization string-id=\"hide-hints\">Ocultar pistas</localization>\n    <localization string-id=\"hide-answers\">Ocultar respuestas</localization>\n    <localization string-id=\"hide-solutions\">Ocultar soluciones</localization>\n    <localization string-id=\"print-header\">Imprimir encabezados</localization>\n    <localization string-id=\"print-footer\">Imprimir pies de página</localization>\n    <localization string-id=\"first-page\">Primera página</localization>\n    <localization string-id=\"running\">En ejecución</localization>\n    <localization string-id=\"highlight-workspace\">Resaltar espacio de trabajo</localization>\n    <localization string-id='print'>Imprimir</localization>\n    <localization string-id='print-preview'>Vista previa de impresión</localization>\n    <localization string-id='close'>Cerrar</localization>\n    <!-- <localization string-id='open-new-tab'>Open in new tab</localization> -->\n    <!-- Readability menu items, HTML only, utilized by Javascript -->\n    <!-- <localization string-id='readability-settings'>Readability settings</localization> -->\n    <!-- <localization string-id='readability-line-height'>Line height</localization> -->\n    <!-- <localization string-id='readability-content-font-size'>Content font size</localization> -->\n    <!-- <localization string-id='readability-theme'>Theme</localization> -->\n    <!-- <localization string-id='readability-theme-system'>System</localization> -->\n    <!-- <localization string-id='readability-theme-light'>Light</localization> -->\n    <!-- <localization string-id='readability-theme-dark'>Dark</localization> -->\n    <!-- <localization string-id='readability-assistive-technologies'>Assistive technologies</localization> -->\n    <!-- <localization string-id='readability-expose-permalinks'>Expose permalinks</localization> -->\n    <!-- <localization string-id='reset-all'>Reset All</localization> -->\n</locale>\n","localizations/fi-FI.xml":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n<!--********************************************************************\nCopyright (C) 2014-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- See  xsl/localizations/README.md  for an explanation of this file -->\n\n<!-- fi-FI, Finnish (Finland) -->\n<!-- Lasse M. Manninen lasse.m.manninen@gmail.com   -->\n\n<locale language=\"fi-FI\" direction=\"ltr\"\n        quote-primary=\"english-double\" quote-secondary=\"english-single\">\n    <!-- THEOREM-LIKE blocks -->\n    <!-- The english quotation style above is just a default, it needs adjustment -->\n    <localization string-id='theorem'>Lause</localization>\n    <localization string-id='corollary'>Seuraus</localization>\n    <localization string-id='lemma'>Lemma</localization>\n    <localization string-id='algorithm'>Algoritmi</localization>\n    <localization string-id='proposition'>Propositio</localization>\n    <localization string-id='claim'>Väite</localization>\n    <localization string-id='fact'>Fakta</localization>\n    <localization string-id='identity'>Identiteetti</localization>\n    <!-- PROOF-LIKE -->\n    <localization string-id='proof'>Todistus</localization>\n    <!-- <localization string-id='argument'>Argument</localization> -->\n    <!-- <localization string-id='justification'>Justification</localization> -->\n    <!-- <localization string-id='reasoning'>Reasoning</localization> -->\n    <!-- <localization string-id='explanation'>Explanation</localization> -->\n    <localization string-id='case'>Tapaus</localization>\n    <!-- Components of the narrative -->\n    <!-- Mathematical statements without proofs -->\n    <!-- AXIOM-LIKE blocks -->\n    <localization string-id='axiom'>Aksiooma</localization>\n    <localization string-id='conjecture'>Konjektuuri</localization>\n    <localization string-id='principle'>Periaate</localization>\n    <localization string-id='heuristic'>Heuristiikka</localization>\n    <localization string-id='hypothesis'>Hypoteesi</localization>\n    <localization string-id='assumption'>Oletus</localization>\n    <!-- Definitions -->\n    <localization string-id='definition'>Määritelmä</localization>\n    <!-- Mathematics -->\n    <localization string-id='equation'>Yhtälö</localization>\n    <localization string-id='displaymath'>Rivitetty yhtälö</localization>\n    <!-- Types of documents, mostly for informational messages -->\n    <localization string-id='volume'>Osa</localization>\n    <localization string-id='book'>Kirja</localization>\n    <localization string-id='article'>Artikkeli</localization>\n    <localization string-id='letter'>Kirje</localization>\n    <localization string-id='slideshow'>Diaesitys</localization>\n    <localization string-id='memo'>Muistio</localization>\n    <localization string-id='presentation'>Esitelmä</localization>\n    <!-- Parts of a document -->\n    <localization string-id='frontmatter'>Nimiösivut</localization>\n    <localization string-id='part'>Osa</localization>\n    <localization string-id='chapter'>Luku</localization>\n    <localization string-id='appendix'>Liite</localization>\n    <localization string-id='appendices'>Liitteet</localization>\n    <localization string-id='section'>Alaluku</localization>\n    <localization string-id='subsection'>Alaluku</localization>\n    <localization string-id='subsubsection'>Alaluku</localization>\n    <localization string-id='slide'>Dia</localization>\n    <localization string-id='introduction'>Johdanto</localization>\n    <localization string-id='conclusion'>Päätäntä</localization>\n    <localization string-id='exercises'>Harjoitustehtävät</localization>\n    <localization string-id='worksheet'>Tehtävämoniste</localization>\n    <!-- <localization string-id='handout'>Handout</localization> -->\n    <localization string-id='reading-questions'>Luetun ymmärtäminen</localization>\n    <localization string-id='solutions'>Ratkaisut</localization>\n    <localization string-id='glossary'>Sanasto</localization>\n    <localization string-id='references'>Lähdeluettelo</localization>\n    <localization string-id='backmatter'>Lisäykset</localization>\n    <localization string-id='paragraphs'>Kappaleet</localization>\n    <localization string-id='subparagraph'>Alakappale</localization>\n    <!-- Adjustments to titles of divisions -->\n    <!-- <localization string-id='group'>Group</localization> -->\n    <!-- Components of the narrative -->\n    <!-- REMARK-LIKE blocks -->\n    <localization string-id='remark'>Huomautus</localization>\n    <localization string-id='convention'>Konventio</localization>\n    <localization string-id='note'>Huomautus</localization>\n    <localization string-id='observation'>Havainto</localization>\n    <localization string-id='warning'>Varoitus</localization>\n    <localization string-id='insight'>Oivallus</localization>\n    <!-- COMPUTATION-LIKE blocks -->\n    <localization string-id='computation'>Lasku</localization>\n    <localization string-id='technology'>Teknologia</localization>\n    <!-- <localization string-id='data'>Data</localization> -->\n    <!-- ASIDE-LIKE blocks -->\n    <localization string-id='aside'>Sivuhuomautus</localization>\n    <localization string-id='biographical'>Elämäkerrallinen sivuhuomautus</localization>\n    <localization string-id='historical'>Historiallinen sivuhuomautus</localization>\n    <!-- EXAMPLE-LIKE blocks -->\n    <localization string-id='example'>Esimerkki</localization>\n    <localization string-id='question'>Kysymys</localization>\n    <localization string-id='problem'>Ongelma</localization>\n    <!-- PROJECT-LIKE blocks -->\n    <localization string-id='project'>Projekti</localization>\n    <localization string-id='activity'>Aktiviteetti</localization>\n    <localization string-id='exploration'>Tutkimus</localization>\n    <localization string-id='task'>Tehtävä</localization>\n    <localization string-id='investigation'>Tutkimus</localization>\n    <localization string-id='assemblage'>Kokoelma</localization>\n    <localization string-id='poem'>Runo</localization>\n    <localization string-id='objectives'>Tavoitteet</localization>\n    <localization string-id='objective'>Tavoite</localization>\n    <localization string-id='outcomes'>Lopputulokset</localization>\n    <localization string-id='outcome'>Lopputulos</localization>\n    <!-- <localization string-id='openquestion'>Open Question</localization> -->\n    <!-- <localization string-id='openproblem'>Open Problem</localization> -->\n    <!-- <localization string-id='openconjecture'>Open Conjecture</localization> -->\n    <!-- <localization string-id='context'>Context</localization> -->\n    <!-- <localization string-id='discussion'>Discussion</localization> -->\n    <!-- <localization string-id='opinion'>Opinion</localization> -->\n    <!-- <localization string-id='status'>Status</localization> -->\n    <!-- <localization string-id='suggestion'>Suggestion</localization> -->\n    <localization string-id='figure'>Kuva</localization>\n    <localization string-id='table'>Taulukko</localization>\n    <localization string-id='listing'>Lista</localization>\n    <localization string-id='fn'>Alaviite</localization>\n    <localization string-id='contributor'>Edistäjä</localization>\n    <!-- Lists and their items -->\n    <localization string-id='list'>Lista</localization>\n    <localization string-id='li'>Nimike</localization>\n    <localization string-id='gi'>Termi</localization>\n    <localization string-id='p'>Kappale</localization>\n    <localization string-id='blockquote'>Lainaus</localization>\n    <!-- <localization string-id='pre'>Code Block</localization> -->\n    <localization string-id='fragment'>Koodinpala</localization>\n    <!-- Parts of an exercise and its solution -->\n    <localization string-id='divisionalexercise'>Harjoitustehtävä</localization>\n    <localization string-id='inlineexercise'>Harjoitus</localization>\n    <localization string-id='worksheetexercise'>Tehtävämonisteen tehtävä</localization>\n    <localization string-id='readingquestion'>Luetunymmärtämistehtävä</localization>\n    <localization string-id='webwork'>WeBWorK</localization>\n    <localization string-id='hint'>Vihje</localization>\n    <localization string-id='answer'>Vastaus</localization>\n    <localization string-id='solution'>Ratkaisu</localization>\n    <!-- <localization string-id='subexercises'>Subexercises</localization> -->\n    <localization string-id='exercisegroup'>Tehtäväsetti</localization>\n    <localization string-id='biblio'>Bibliografinen nimike</localization>\n    <!-- Front matter components -->\n    <localization string-id='toc'>Sisällys</localization>\n    <localization string-id='abstract'>Tiivistelmä</localization>\n    <localization string-id='preface'>Johdanto</localization>\n    <localization string-id='acknowledgement'>Kiitokset</localization>\n    <localization string-id='biography'>Kirjoittajan tausta</localization>\n    <localization string-id='about-author'>Kirjoittajasta</localization>\n    <localization string-id='about-authors'>Kirjoittajista</localization>\n    <localization string-id='foreword'>Esipuhe</localization>\n    <localization string-id='dedication'>Omistus</localization>\n    <localization string-id='colophon'>Kolofoni</localization>\n    <!-- Runestone Activities -->\n    <!-- <localization string-id='video'>Video</localization> -->\n    <!-- <localization string-id='program'>Program</localization> -->\n    <!-- Runestone Exercises -->\n    <!-- <localization string-id='true'>True</localization> -->\n    <!-- <localization string-id='false'>False</localization> -->\n    <!-- <localization string-id='or'>Or</localization> -->\n    <!-- <localization string-id='either'>Either</localization> -->\n    <!-- <localization string-id='uncategorized'>Uncategorized</localization> -->\n    <!-- <localization string-id='query'>Query</localization> -->\n    <localization string-id='program-activecode'>ActiveCode</localization>\n    <!-- <localization string-id='scratch-activecode'>Scratch ActiveCode</localization> -->\n    <localization string-id='program-codelens'>CodeLens</localization>\n    <!-- Back matter components -->\n    <localization string-id='index'>Hakemisto</localization>\n    <localization string-id='jump-to'>Mene kohtaan:</localization>\n    <!-- Parts of the Index -->\n    <localization string-id='see'>Ks.</localization>\n    <localization string-id='also'>Ks. myös</localization>\n    <!-- Notation List headings/foot -->\n    <localization string-id='symbol'>Symboli</localization>\n    <localization string-id='description'>Kuvaus</localization>\n    <localization string-id='location'>Paikka</localization>\n    <localization string-id='page'>Sivu</localization>\n    <localization string-id='continued'>Jatkuu seuraavalla sivulla</localization>\n    <!-- Navigation Interface elements -->\n    <localization string-id='skip-to-content'>Siirry pääasiaan</localization>\n    <localization string-id='previous'>Edellinen</localization>\n    <localization string-id='up'>Ylös</localization>\n    <localization string-id='next'>Seuraava</localization>\n    <localization string-id='previous-short'>Ed</localization>\n    <localization string-id='up-short'>Yl</localization>\n    <localization string-id='next-short'>Seur</localization>\n    <!-- <localization string-id='top'>Top</localization> -->\n    <localization string-id='annotations'>Huomautukset</localization>\n    <localization string-id='feedback'>Palaute</localization>\n    <localization string-id='authored'>Tuotettu PreTeXtillä</localization>\n    <!-- Search Results display/dialog -->\n    <!-- <localization string-id='search-book'>Search Book</localization> -->\n    <!-- <localization string-id='search-results-heading'>Search Results</localization> -->\n    <!-- <localization string-id='no-search-results'>No results</localization> -->\n    <!-- Parts of memos and letters -->\n    <localization string-id='to'>Vastaanottaja</localization>\n    <localization string-id='from'>Lähettäjä</localization>\n    <localization string-id='subject'>Aihe</localization>\n    <localization string-id='date'>Pvm</localization>\n    <localization string-id='cc'>cc</localization>\n    <localization string-id='enclosure'>liite</localization>\n    <!-- Various -->\n    <localization string-id='todo'>To Do</localization>\n    <localization string-id='editor'>Toimittaja</localization>\n    <localization string-id='edition'>Painos</localization>\n    <localization string-id='website'>Nettisivu</localization>\n    <localization string-id='copyright'>Tekijänoikeus</localization>\n    <!-- <localization string-id='keywords'>Keywords</localization> -->\n    <!-- HTML clickables (lowercase strings to click on) -->\n    <localization string-id='permalink'>linkki</localization>\n    <localization string-id='incontext'>In Context</localization>\n    <!-- <localization string-id='standalone'>Standalone</localization> -->\n    <!-- <localization string-id='embed'>Embed</localization> -->\n    <!-- <localization string-id='embed-this-page'>Embed this page</localization> -->\n    <!-- <localization string-id='copy'>Copy</localization> -->\n    <!-- <localization string-id='profile'>Profile</localization> -->\n    <!-- Following is in ENGLISH and should be translated.  Due to its -->\n    <!-- ubiquitous nature we have not left it undefined.  See the -->\n    <!-- \"en-US\" file for a more complete explanation of its use. -->\n    <!-- Please remove this entire comment when translated.  Thanks. -->\n    <localization string-id='permalink-tooltip'>Copy heading and permalink for</localization>\n    <!-- <localization string-id='calculator'>Calculator</localization> -->\n    <localization string-id='evaluate'>Aja</localization>\n    <!-- <localization string-id='code'>Code</localization> -->\n    <!-- <localization string-id='instructions'>Instructions</localization> -->\n    <!-- <localization string-id='correct'>Correct</localization> -->\n    <!-- <localization string-id='incorrect'>Incorrect</localization> -->\n    <!-- <localization string-id='blank'>Blank</localization> -->\n    <!-- <localization string-id='submit'>Submit</localization> -->\n    <!-- <localization string-id='check-responses'>Check Responses</localization> -->\n    <!-- <localization string-id='reveal'>Reveal</localization> -->\n    <!-- <localization string-id='randomize'>Randomize</localization> -->\n    <!-- <localization string-id='activate'>Activate</localization> -->\n    <!-- <localization string-id='reset'>Reset</localization> -->\n    <!-- <localization string-id='array'>array</localization> -->\n    <!-- <localization string-id=\"papersize\">Paper size</localization> -->\n    <!-- <localization string-id=\"printing-options\">Additional printing options</localization> -->\n    <!-- <localization string-id=\"hide-hints\">Hide hints</localization> -->\n    <!-- <localization string-id=\"hide-answers\">Hide answers</localization> -->\n    <!-- <localization string-id=\"hide-solutions\">Hide solutions</localization> -->\n    <!-- <localization string-id=\"print-header\">Print headers</localization> -->\n    <!-- <localization string-id=\"print-footer\">Print footers</localization> -->\n    <!-- <localization string-id=\"first-page\">First page</localization> -->\n    <!-- <localization string-id=\"running\">Running</localization> -->\n    <!-- <localization string-id=\"highlight-workspace\">Highlight workspace</localization> -->\n    <!-- <localization string-id='print'>Print</localization> -->\n    <!-- <localization string-id='print-preview'>Print preview</localization> -->\n    <!-- <localization string-id='close'>Close</localization> -->\n    <!-- <localization string-id='open-new-tab'>Open in new tab</localization> -->\n    <!-- Readability menu items, HTML only, utilized by Javascript -->\n    <!-- <localization string-id='readability-settings'>Readability settings</localization> -->\n    <!-- <localization string-id='readability-line-height'>Line height</localization> -->\n    <!-- <localization string-id='readability-content-font-size'>Content font size</localization> -->\n    <!-- <localization string-id='readability-theme'>Theme</localization> -->\n    <!-- <localization string-id='readability-theme-system'>System</localization> -->\n    <!-- <localization string-id='readability-theme-light'>Light</localization> -->\n    <!-- <localization string-id='readability-theme-dark'>Dark</localization> -->\n    <!-- <localization string-id='readability-assistive-technologies'>Assistive technologies</localization> -->\n    <!-- <localization string-id='readability-expose-permalinks'>Expose permalinks</localization> -->\n    <!-- <localization string-id='reset-all'>Reset All</localization> -->\n</locale>\n","localizations/fr-CA.xml":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n<!--********************************************************************\nCopyright (C) 2016-2026  Robert A. Beezer\nThis file is part of PreTeXt.\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- See  xsl/localizations/README.md  for an explanation of this file -->\n\n<!-- fr-CA, French (Canada) -->\n<!-- based on initial fr-FR translation -->\n<!-- Jean-Sébastien Turcotte, js.turcotte@cgodin.qc.ca, 2021-02-19-->\n<!-- Added missing fr-CA translations by Christian Chávez, christian.chavez@usherbrooke.ca, 2025-12-20-->\n\n<!-- If/when a new string-id gets translated in French for the first time, it should also be translated into fr-FR -->\n<!-- Quotation styles per Jean-Sébastien Turcotte on pretext-dev: -->\n<!-- primary angle-double-space, secondary english-single.        -->\n<locale language=\"fr-CA\" direction=\"ltr\"\n        quote-primary=\"angle-double-space\" quote-secondary=\"english-single\">\n    <!-- THEOREM-LIKE blocks -->\n    <localization string-id='theorem'>Théorème</localization>\n    <localization string-id='corollary'>Corollaire</localization>\n    <localization string-id='lemma'>Lemme</localization>\n    <localization string-id='algorithm'>Algorithme</localization>\n    <localization string-id='proposition'>Proposition</localization>\n    <localization string-id='claim'>Affirmation</localization>\n    <localization string-id='fact'>Fait</localization>\n    <localization string-id='identity'>Identité</localization>\n    <!-- PROOF-LIKE -->\n    <localization string-id='proof'>Démonstration</localization>\n    <localization string-id='argument'>Argument</localization>\n    <localization string-id='justification'>Justification</localization>\n    <localization string-id='reasoning'>Raisonnement</localization>\n    <localization string-id='explanation'>Explication</localization>\n    <localization string-id='case'>Cas</localization>\n    <!-- Components of the narrative -->\n    <!-- Mathematical statements without proofs -->\n    <!-- AXIOM-LIKE blocks -->\n    <localization string-id='axiom'>Axiome</localization>\n    <localization string-id='conjecture'>Conjecture</localization>\n    <localization string-id='principle'>Principe</localization>\n    <localization string-id='heuristic'>Heuristique</localization>\n    <localization string-id='hypothesis'>Hypothèse</localization>\n    <localization string-id='assumption'>Supposition</localization>\n    <!-- Definitions -->\n    <localization string-id='definition'>Définition</localization>\n    <!-- Mathematics -->\n    <localization string-id='equation'>Équation</localization>\n    <localization string-id='displaymath'>Mathématiques en évidence</localization>\n    <!-- Types of documents, mostly for informational messages -->\n    <localization string-id='volume'>Volume</localization>\n    <localization string-id='book'>Livre</localization>\n    <localization string-id='article'>Article</localization>\n    <localization string-id='letter'>Lettre</localization>\n    <localization string-id='slideshow'>Présentation</localization>\n    <localization string-id='memo'>Mémo</localization>\n    <localization string-id='presentation'>Présentation</localization>\n    <!-- Parts of a document -->\n    <localization string-id='frontmatter'>Pages Liminaires</localization>\n    <localization string-id='part'>Partie</localization>\n    <localization string-id='chapter'>Chapitre</localization>\n    <localization string-id='appendix'>Appendice</localization>\n    <localization string-id='appendices'>Appendices</localization>\n    <localization string-id='section'>Section</localization>\n    <localization string-id='subsection'>Sous-section</localization>\n    <localization string-id='subsubsection'>Sous sous-section</localization>\n    <localization string-id='slide'>Diapositive</localization>\n    <localization string-id='introduction'>Introduction</localization>\n    <localization string-id='conclusion'>Conclusion</localization>\n    <localization string-id='exercises'>Exercices</localization>\n    <localization string-id='worksheet'>Feuille d'activités</localization> <!-- Harmonisation avec worksheetexercise -->\n    <localization string-id='handout'>Document</localization>\n    <localization string-id='reading-questions'>Questions de compréhension de la lecture</localization> <!-- Peut-être un peu long /might be a bit too long -->\n    <localization string-id='solutions'>Solutions</localization>\n    <localization string-id='glossary'>Glossaire</localization>\n    <localization string-id='references'>Références</localization>\n    <localization string-id='backmatter'>Annexes</localization>\n    <localization string-id='paragraphs'>Paragraphes</localization> <!-- checked -->\n    <localization string-id='subparagraph'>Sous-paragraphe</localization> <!-- checked -->\n    <!-- Adjustments to titles of divisions -->\n    <localization string-id='group'>Groupe</localization>\n    <!-- Components of the narrative -->\n    <!-- REMARK-LIKE blocks -->\n    <localization string-id='remark'>Remarque</localization>\n    <localization string-id='convention'>Convention</localization>\n    <localization string-id='note'>Note</localization>\n    <localization string-id='observation'>Observation</localization>\n    <localization string-id='warning'>Mise en garde</localization>\n    <localization string-id='insight'>Aperçu</localization>\n    <!-- COMPUTATION-LIKE blocks -->\n    <localization string-id='computation'>Calcul</localization>\n    <localization string-id='technology'>Technologie</localization>\n    <localization string-id='data'>Données</localization>\n    <!-- ASIDE-LIKE blocks -->\n    <localization string-id='aside'>Digression</localization>\n    <localization string-id='biographical'>Note biographique</localization> <!-- Knowingly differs from fr-FR, which uses \"digression\" instead of \"note\" -->\n    <localization string-id='historical'>Note historique</localization> <!-- Knowingly differs from fr-FR, which uses \"digression\" instead of \"note\" -->\n    <!-- EXAMPLE-LIKE blocks -->\n    <localization string-id='example'>Exemple</localization> <!-- checked -->\n    <localization string-id='question'>Question</localization>\n    <localization string-id='problem'>Problème</localization>\n    <!-- PROJECT-LIKE blocks -->\n    <localization string-id='project'>Projet</localization>\n    <localization string-id='activity'>Activité</localization>\n    <localization string-id='exploration'>Exploration</localization>\n    <localization string-id='task'>Tâche</localization>\n    <localization string-id='investigation'>Enquête</localization>\n    <localization string-id='assemblage'>Assemblage</localization>\n    <localization string-id='poem'>Poème</localization>\n    <localization string-id='objectives'>Objectifs</localization>\n    <localization string-id='objective'>Objectif</localization>\n    <localization string-id='outcomes'>Résultats</localization>\n    <localization string-id='outcome'>Résultat</localization>\n    <localization string-id='openquestion'>Question ouverte</localization>\n    <localization string-id='openproblem'>Problème ouvert</localization>\n    <localization string-id='openconjecture'>Conjecture ouverte</localization>\n    <localization string-id='context'>Contexte</localization>\n    <localization string-id='discussion'>Discussion</localization>\n    <localization string-id='opinion'>Opinion</localization>\n    <localization string-id='status'>Statut</localization>\n    <localization string-id='suggestion'>Suggestion</localization>\n    <localization string-id='figure'>Figure</localization>\n    <localization string-id='table'>Table</localization>\n    <localization string-id='listing'>Listing</localization>\n    <localization string-id='fn'>Note de bas de page</localization> <!-- checked -->\n    <localization string-id='contributor'>Contribution de</localization>\n    <!-- Lists and their items -->\n    <localization string-id='list'>Liste</localization>\n    <localization string-id='li'>Point</localization>\n    <localization string-id='gi'>Terme</localization>\n    <localization string-id='p'>Paragraphe</localization>\n    <localization string-id='blockquote'>Citation</localization>\n    <localization string-id='pre'>Bloc de code</localization>\n    <localization string-id='fragment'>Fragment</localization>\n    <!-- Parts of an exercise and its solution -->\n    <!-- See the en-US file for a detailed explanation of the words for exercises -->\n    <localization string-id='divisionalexercise'>Exercice</localization>\n    <!-- Translation needed for France French -->\n    <!-- See en-US file for distinctions here, do not repeat previous translation -->\n    <localization string-id='inlineexercise'>Mise au point</localization>\n    <localization string-id='worksheetexercise'>Activité</localization> <!-- base upon en-US, a worksheet is a bunch of activities -->\n    <localization string-id='readingquestion'>Question de compréhension</localization>\n    <localization string-id='webwork'>WeBWorK</localization>\n    <localization string-id='hint'>Indice</localization> <!-- Knowingly differs from fr-FR, which uses \"Indication\" instead -->\n    <localization string-id='answer'>Réponse</localization>\n    <localization string-id='solution'>Solution</localization>\n    <localization string-id='subexercises'>Sous-exercices</localization>\n    <localization string-id='exercisegroup'>Groupe d'exercices</localization>\n    <localization string-id='biblio'>Entrée bibliographique</localization>\n    <!-- Front matter components -->\n    <localization string-id='toc'>Table des matières</localization>\n    <localization string-id='abstract'>Résumé</localization>\n    <localization string-id='preface'>Préface</localization>\n    <localization string-id='acknowledgement'>Remerciements</localization>\n    <localization string-id='biography'>Biographie</localization>\n    <localization string-id='about-author'>À propos de l'auteur</localization>\n    <localization string-id='about-authors'>À propos des auteurs</localization>\n    <localization string-id='foreword'>Avant-propos</localization>\n    <localization string-id='dedication'>Dédicace</localization>\n    <localization string-id='colophon'>Colophon</localization>\n    <!-- Runestone Activities -->\n    <localization string-id='video'>Vidéo</localization>\n    <localization string-id='program'>Programme</localization>\n    <!-- Runestone Exercises -->\n    <localization string-id='true'>Vrai</localization>\n    <localization string-id='false'>Faux</localization>\n    <localization string-id='or'>Ou</localization>\n    <localization string-id='either'>Soit</localization>\n    <localization string-id='uncategorized'>Non catégorisé</localization>\n    <localization string-id='query'>Requête</localization>\n    <localization string-id='program-activecode'>ActiveCode</localization>\n    <!-- <localization string-id='scratch-activecode'>Scratch ActiveCode</localization> -->\n    <localization string-id='program-codelens'>CodeLens</localization>\n    <!-- Back matter components -->\n    <localization string-id='index'>Index</localization>\n    <localization string-id='jump-to'>Aller à :</localization>\n    <!-- Parts of the Index -->\n    <localization string-id='see'>Visiter</localization>\n    <localization string-id='also'>Voir aussi</localization>\n    <!-- Notation List headings/foot -->\n    <localization string-id='symbol'>Symbole</localization>\n    <localization string-id='description'>Description</localization>\n    <localization string-id='location'>Emplacement</localization>\n    <localization string-id='page'>Page</localization>\n    <localization string-id='continued'>Suite à la page suivante</localization>\n    <!-- Navigation Interface elements -->\n    <localization string-id='skip-to-content'>Sauter au contenu</localization>\n    <localization string-id='previous'>Précédent</localization> <!-- buttons for HTML navigation -->\n    <localization string-id='up'>Haut</localization>\n    <localization string-id='next'>Suivant</localization>\n    <localization string-id='previous-short'>Préc.</localization> <!-- buttons for HTML navigation -->\n    <localization string-id='up-short'>Haut</localization>\n    <localization string-id='next-short'>Suiv.</localization>\n    <!-- <localization string-id='top'>Top</localization> -->\n    <localization string-id='annotations'>Annotations</localization> <!-- does not get printed -->\n    <localization string-id='feedback'>Commentaires</localization> <!-- e.g., in case there is a link for feedback.  Will appear in HTML. -->\n    <localization string-id='authored'>Rédigé avec PreTeXt</localization> <!-- e.g., authored in PreTeXt.  Will appear in HTML. -->\n    <!-- Search Results display/dialog -->\n    <!-- <localization string-id='search-book'>Search Book</localization> -->\n    <localization string-id='search-results-heading'>Résultats de la recherche</localization>\n    <localization string-id='no-search-results'>Aucun résultat</localization>\n    <!-- Parts of memos and letters -->\n    <localization string-id='to'>À</localization>\n    <localization string-id='from'>De</localization>\n    <localization string-id='subject'>Sujet</localization>\n    <localization string-id='date'>Date</localization>\n    <localization string-id='cc'>Copie</localization>\n    <localization string-id='enclosure'>Pièce jointe</localization>\n    <!-- Various -->\n    <localization string-id='todo'>À Faire</localization>\n    <localization string-id='editor'>Éditeur</localization>\n    <localization string-id='edition'>Édition</localization>\n    <localization string-id='website'>Site Web</localization>\n    <localization string-id='copyright'>Copyright</localization>\n    <localization string-id='keywords'>Mots-clés</localization>\n    <!-- HTML clickables (lowercase strings to click on) -->\n    <localization string-id='permalink'>permalien</localization>\n    <localization string-id='incontext'>Contexte</localization>\n    <!-- <localization string-id='standalone'>Standalone</localization> -->\n    <!-- <localization string-id='embed'>Embed</localization> -->\n    <!-- <localization string-id='embed-this-page'>Embed this page</localization> -->\n    <!-- <localization string-id='copy'>Copy</localization> -->\n    <!-- <localization string-id='profile'>Profile</localization> -->\n    <localization string-id='permalink-tooltip'>Copier le titre et le lien permanent pour</localization>\n    <!-- <localization string-id='calculator'>Calculator</localization> -->\n    <!-- This needs to be defined to *something* (English) -->\n    <!-- Translate at first opportunity, please -->\n    <localization string-id='evaluate'>Évaluer</localization>\n    <!-- <localization string-id='code'>Code</localization> -->\n    <localization string-id='instructions'>Instructions</localization>\n    <localization string-id='correct'>Correct</localization>\n    <localization string-id='incorrect'>Incorrect</localization>\n    <localization string-id='blank'>Vide</localization>\n    <localization string-id='submit'>Soumettre</localization>\n    <localization string-id='check-responses'>Vérifier les réponses</localization>\n    <localization string-id='reveal'>Dévoiler</localization>\n    <localization string-id='randomize'>Générer une nouvelle version aléatoire</localization>\n    <localization string-id='activate'>Activer</localization>\n    <localization string-id='reset'>Réinitialiser</localization>\n    <localization string-id='array'>Tableau</localization>\n    <localization string-id=\"papersize\">Format de papier</localization>\n    <localization string-id=\"printing-options\">Options d'impression supplémentaires</localization>\n    <localization string-id=\"hide-hints\">Masquer les indices</localization>\n    <localization string-id=\"hide-answers\">Masquer les réponses</localization>\n    <localization string-id=\"hide-solutions\">Masquer les solutions</localization>\n    <localization string-id=\"print-header\">Imprimer les en-têtes</localization>\n    <localization string-id=\"print-footer\">Imprimer les pieds de page</localization>\n    <localization string-id=\"first-page\">Première page</localization>\n    <localization string-id=\"running\">En cours</localization>\n    <localization string-id=\"highlight-workspace\">Mettre en évidence l'espace de travail</localization>\n    <localization string-id='print'>Imprimer</localization>\n    <localization string-id='print-preview'>Aperçu avant impression</localization>\n    <localization string-id='close'>Fermer</localization>\n    <localization string-id='open-new-tab'>Ouvrir dans un nouvel onglet</localization>\n    <!-- Readability menu items, HTML only, utilized by Javascript -->\n    <localization string-id='readability-settings'>Paramètres de lecture</localization>\n    <localization string-id='readability-line-height'>Interligne</localization>\n    <localization string-id='readability-content-font-size'>Taille de police</localization>\n    <localization string-id='readability-theme'>Thème</localization>\n    <localization string-id='readability-theme-system'>Système</localization>\n    <localization string-id='readability-theme-light'>Clair</localization>\n    <localization string-id='readability-theme-dark'>Sombre</localization>\n    <localization string-id='readability-assistive-technologies'>Technologies d'assistance</localization>\n    <localization string-id='readability-expose-permalinks'>Exposer les permaliens</localization>\n    <localization string-id='reset-all'>Options par défaut</localization>\n</locale>\n","localizations/fr-FR.xml":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n<!--********************************************************************\nCopyright (C) 2016-2026  Robert A. Beezer\nThis file is part of PreTeXt.\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- See  xsl/localizations/README.md  for an explanation of this file -->\n\n<!-- fr-FR, French (France) -->\n\n<!-- Thomas W. Judson, judsontw@sfasu.edu, 2016-03-23 -->\n<!-- Julien Giol, julien.giol@gmail.com, 2018-02-05   -->\n<!-- Jean-Sébastien Turcotte, js.turcotte@cgodin.qc.ca, 2021-02-19-->\n\n<!-- If/when a new string-id gets translated in French for the first time, it should also be translated into fr-CA -->\n<locale language=\"fr-FR\" direction=\"ltr\"\n        quote-primary=\"angle-double-space\" quote-secondary=\"english-double\">\n    <!-- THEOREM-LIKE blocks -->\n    <localization string-id='theorem'>Théorème</localization>\n    <localization string-id='corollary'>Corollaire</localization>\n    <localization string-id='lemma'>Lemme</localization>\n    <localization string-id='algorithm'>Algorithme</localization>\n    <localization string-id='proposition'>Proposition</localization>\n    <localization string-id='claim'>Affirmation</localization>\n    <localization string-id='fact'>Fait</localization>\n    <localization string-id='identity'>Identité</localization>\n    <!-- PROOF-LIKE -->\n    <localization string-id='proof'>Démonstration</localization>\n    <localization string-id='argument'>Argument</localization>\n    <localization string-id='justification'>Justification</localization>\n    <localization string-id='reasoning'>Raisonnement</localization>\n    <localization string-id='explanation'>Explication</localization>\n    <localization string-id='case'>Cas</localization>\n    <!-- Components of the narrative -->\n    <!-- Mathematical statements without proofs -->\n    <!-- AXIOM-LIKE blocks -->\n    <localization string-id='axiom'>Axiome</localization>\n    <localization string-id='conjecture'>Conjecture</localization>\n    <localization string-id='principle'>Principe</localization>\n    <localization string-id='heuristic'>Heuristique</localization>\n    <localization string-id='hypothesis'>Hypothèse</localization>\n    <localization string-id='assumption'>Supposition</localization>\n    <!-- Definitions -->\n    <localization string-id='definition'>Définition</localization>\n    <!-- Mathematics -->\n    <localization string-id='equation'>Équation</localization>\n    <localization string-id='displaymath'>Mathématiques en évidence</localization>\n    <!-- Types of documents, mostly for informational messages -->\n    <localization string-id='volume'>Volume</localization>\n    <localization string-id='book'>Livre</localization>\n    <localization string-id='article'>Article</localization>\n    <localization string-id='letter'>Lettre</localization>\n    <localization string-id='slideshow'>Présentation</localization>\n    <localization string-id='memo'>Mémo</localization>\n    <localization string-id='presentation'>Présentation</localization>\n    <!-- Parts of a document -->\n    <localization string-id='frontmatter'>Pages Liminaires</localization>\n    <localization string-id='part'>Partie</localization>\n    <localization string-id='chapter'>Chapitre</localization>\n    <localization string-id='appendix'>Appendice</localization>\n    <localization string-id='appendices'>Appendices</localization>\n    <localization string-id='section'>Section</localization>\n    <localization string-id='subsection'>Sous-section</localization>\n    <localization string-id='subsubsection'>Sous sous-section</localization>\n    <localization string-id='slide'>Diapositive</localization>\n    <localization string-id='introduction'>Introduction</localization>\n    <localization string-id='conclusion'>Conclusion</localization>\n    <localization string-id='exercises'>Exercices</localization>\n    <localization string-id='worksheet'>Feuille d'activités</localization> <!-- À défaut d'un meilleur terme -->\n    <!-- <localization string-id='handout'>Handout</localization> -->\n    <localization string-id='reading-questions'>Questions de compréhension de la lecture</localization> <!-- Peut-être un peu long /might be a bit too long -->\n    <localization string-id='solutions'>Solutions</localization>\n    <localization string-id='glossary'>Glossaire</localization>\n    <localization string-id='references'>Références</localization>\n    <localization string-id='backmatter'>Annexes</localization>\n    <localization string-id='paragraphs'>Paragraphes</localization> <!-- checked -->\n    <localization string-id='subparagraph'>Sous-paragraphe</localization> <!-- checked -->\n    <!-- Adjustments to titles of divisions -->\n    <!-- <localization string-id='group'>Group</localization> -->\n    <!-- Components of the narrative -->\n    <!-- REMARK-LIKE blocks -->\n    <localization string-id='remark'>Remarque</localization>\n    <localization string-id='convention'>Convention</localization>\n    <localization string-id='note'>Note</localization>\n    <localization string-id='observation'>Observation</localization>\n    <localization string-id='warning'>Mise en garde</localization>\n    <!-- <localization string-id='insight'>Insight</localization> -->\n    <!-- COMPUTATION-LIKE blocks -->\n    <localization string-id='computation'>Calcul</localization>\n    <localization string-id='technology'>Technologie</localization>\n    <!-- <localization string-id='data'>Data</localization> -->\n    <!-- ASIDE-LIKE blocks -->\n    <localization string-id='aside'>Digression</localization>\n    <localization string-id='biographical'>Digression biographique</localization>\n    <localization string-id='historical'>Digression historique</localization>\n    <!-- EXAMPLE-LIKE blocks -->\n    <localization string-id='example'>Exemple</localization> <!-- checked -->\n    <localization string-id='question'>Question</localization>\n    <localization string-id='problem'>Problème</localization>\n    <!-- PROJECT-LIKE blocks -->\n    <localization string-id='project'>Projet</localization>\n    <localization string-id='activity'>Activité</localization>\n    <localization string-id='exploration'>Exploration</localization>\n    <localization string-id='task'>Tâche</localization>\n    <localization string-id='investigation'>Enquête</localization>\n    <localization string-id='assemblage'>Assemblage</localization>\n    <localization string-id='poem'>Poème</localization>\n    <localization string-id='objectives'>Objectifs</localization>\n    <localization string-id='objective'>Objectif</localization>\n    <localization string-id='outcomes'>Résultats</localization>\n    <localization string-id='outcome'>Résultat</localization>\n    <!-- <localization string-id='openquestion'>Open Question</localization> -->\n    <!-- <localization string-id='openproblem'>Open Problem</localization> -->\n    <!-- <localization string-id='openconjecture'>Open Conjecture</localization> -->\n    <!-- <localization string-id='context'>Context</localization> -->\n    <!-- <localization string-id='discussion'>Discussion</localization> -->\n    <!-- <localization string-id='opinion'>Opinion</localization> -->\n    <!-- <localization string-id='status'>Status</localization> -->\n    <!-- <localization string-id='suggestion'>Suggestion</localization> -->\n    <localization string-id='figure'>Figure</localization>\n    <localization string-id='table'>Table</localization>\n    <localization string-id='listing'>Listing</localization>\n    <localization string-id='fn'>Note de bas de page</localization> <!-- checked -->\n    <localization string-id='contributor'>Contribution de</localization>\n    <!-- Lists and their items -->\n    <localization string-id='list'>Liste</localization>\n    <localization string-id='li'>Point</localization>\n    <localization string-id='gi'>Terme</localization>\n    <localization string-id='p'>Paragraphe</localization>\n    <localization string-id='blockquote'>Citation</localization>\n    <!-- <localization string-id='pre'>Code Block</localization> -->\n    <!-- <localization string-id='fragment'>Fragment</localization> -->\n    <!-- Parts of an exercise and its solution -->\n    <!-- See the en-US file for a detailed explanation of the words for exercises -->\n    <localization string-id='divisionalexercise'>Exercice</localization>\n    <!-- Translation needed for France French -->\n    <!-- See en-US file for distinctions here, do not repeat previous translation -->\n    <localization string-id='inlineexercise'>Mise au point</localization>\n    <localization string-id='worksheetexercise'>Activité</localization>\n    <localization string-id='readingquestion'>Question de compréhension</localization>\n    <localization string-id='webwork'>WeBWorK</localization>\n    <localization string-id='hint'>Indication</localization>\n    <localization string-id='answer'>Réponse</localization>\n    <localization string-id='solution'>Solution</localization>\n    <!-- <localization string-id='subexercises'>Subexercises</localization> -->\n    <localization string-id='exercisegroup'>Groupe d'exercices</localization>\n    <!-- <localization string-id='biblio'>Bibliographic Entry</localization> -->\n    <!-- Front matter components -->\n    <localization string-id='toc'>Table des matières</localization>\n    <localization string-id='abstract'>Résumé</localization>\n    <localization string-id='preface'>Préface</localization>\n    <localization string-id='acknowledgement'>Remerciements</localization>\n    <localization string-id='biography'>Biographie</localization>\n    <localization string-id='about-author'>À propos de l'auteur</localization>\n    <localization string-id='about-authors'>À propos des auteurs</localization>\n    <localization string-id='foreword'>Avant-propos</localization>\n    <localization string-id='dedication'>Dédicace</localization>\n    <localization string-id='colophon'>Colophon</localization>\n    <!-- Runestone Activities -->\n    <localization string-id='video'>Vidéo</localization>\n    <!-- <localization string-id='program'>Program</localization> -->\n    <!-- Runestone Exercises -->\n    <!-- <localization string-id='true'>True</localization> -->\n    <!-- <localization string-id='false'>False</localization> -->\n    <!-- <localization string-id='or'>Or</localization> -->\n    <!-- <localization string-id='either'>Either</localization> -->\n    <!-- <localization string-id='uncategorized'>Uncategorized</localization> -->\n    <!-- <localization string-id='query'>Query</localization> -->\n    <localization string-id='program-activecode'>ActiveCode</localization>\n    <!-- <localization string-id='scratch-activecode'>Scratch ActiveCode</localization> -->\n    <localization string-id='program-codelens'>CodeLens</localization>\n    <!-- Back matter components -->\n    <localization string-id='index'>Index</localization>\n    <localization string-id='jump-to'>Aller à :</localization>\n    <!-- Parts of the Index -->\n    <localization string-id='see'>Visiter</localization>\n    <localization string-id='also'>Voir Aussi</localization>\n    <!-- Notation List headings/foot -->\n    <localization string-id='symbol'>Symbole</localization>\n    <localization string-id='description'>Description</localization>\n    <localization string-id='location'>Emplacement</localization>\n    <localization string-id='page'>Page</localization>\n    <localization string-id='continued'>Suite à la page suivante</localization>\n    <!-- Navigation Interface elements -->\n    <localization string-id='skip-to-content'>Sauter au contenu</localization>\n    <localization string-id='previous'>Précédent</localization> <!-- buttons for HTML navigation -->\n    <localization string-id='up'>Haut</localization>\n    <localization string-id='next'>Suivant</localization>\n    <!-- TODO: SHORTEN THESE -->\n    <localization string-id='previous-short'>Précédent</localization> <!-- buttons for HTML navigation -->\n    <localization string-id='up-short'>Haut</localization>\n    <localization string-id='next-short'>Suivant</localization>\n    <!-- <localization string-id='top'>Top</localization> -->\n    <localization string-id='annotations'>Annotations</localization> <!-- does not get printed -->\n    <localization string-id='feedback'>Commentaires</localization> <!-- e.g., in case there is a link for feedback.  Will appear in HTML. -->\n    <localization string-id='authored'>Rédigé avec PreTeXt</localization> <!-- e.g., authored in PreTeXt.  Will appear in HTML. -->\n    <!-- Search Results display/dialog -->\n    <!-- <localization string-id='search-book'>Search Book</localization> -->\n    <localization string-id='search-results-heading'>Résultats de la recherche</localization>\n    <localization string-id='no-search-results'>Aucun résultat</localization>\n    <!-- Parts of memos and letters -->\n    <localization string-id='to'>À</localization>\n    <localization string-id='from'>De</localization>\n    <localization string-id='subject'>Sujet</localization>\n    <localization string-id='date'>Date</localization>\n    <localization string-id='cc'>Copie</localization>\n    <localization string-id='enclosure'>Pièce Jointe</localization>\n    <!-- Various -->\n    <localization string-id='todo'>À Faire</localization>\n    <localization string-id='editor'>Éditeur</localization>\n    <localization string-id='edition'>Édition</localization>\n    <localization string-id='website'>Site Web</localization>\n    <localization string-id='copyright'>Copyright</localization>\n    <!-- <localization string-id='keywords'>Keywords</localization> -->\n    <!-- HTML clickables (lowercase strings to click on) -->\n    <!-- <localization string-id='permalink'>permalink</localization> -->\n    <localization string-id='incontext'>Contexte</localization>\n    <!-- <localization string-id='standalone'>Standalone</localization> -->\n    <!-- <localization string-id='embed'>Embed</localization> -->\n    <!-- <localization string-id='embed-this-page'>Embed this page</localization> -->\n    <!-- <localization string-id='copy'>Copy</localization> -->\n    <!-- <localization string-id='profile'>Profile</localization> -->\n    <!-- Following is in ENGLISH and should be translated.  Due to its -->\n    <!-- ubiquitous nature we have not left it undefined.  See the -->\n    <!-- \"en-US\" file for a more complete explanation of its use. -->\n    <!-- Please remove this entire comment when translated.  Thanks. -->\n    <localization string-id='permalink-tooltip'>Copy heading and permalink for</localization>\n    <!-- <localization string-id='calculator'>Calculator</localization> -->\n    <!-- This needs to be defined to *something* (English) -->\n    <!-- Translate at first opportunity, please -->\n    <localization string-id='evaluate'>Évaluer</localization>\n    <!-- <localization string-id='code'>Code</localization> -->\n    <localization string-id='instructions'>Instructions</localization>\n    <localization string-id='correct'>Correct</localization>\n    <localization string-id='incorrect'>Incorrect</localization>\n    <localization string-id='blank'>Vide</localization>\n    <localization string-id='submit'>Soumettre</localization>\n    <localization string-id='check-responses'>Vérifier les réponses</localization>\n    <localization string-id='reveal'>Dévoiler</localization>\n    <localization string-id='randomize'>Générer une nouvelle version aléatoire</localization>\n    <localization string-id='activate'>Activer</localization>\n    <localization string-id='reset'>Réinitialiser</localization>\n    <!-- <localization string-id='array'>array</localization> -->\n    <!-- <localization string-id=\"papersize\">Paper size</localization> -->\n    <!-- <localization string-id=\"printing-options\">Additional printing options</localization> -->\n    <!-- <localization string-id=\"hide-hints\">Hide hints</localization> -->\n    <!-- <localization string-id=\"hide-answers\">Hide answers</localization> -->\n    <!-- <localization string-id=\"hide-solutions\">Hide solutions</localization> -->\n    <!-- <localization string-id=\"print-header\">Print headers</localization> -->\n    <!-- <localization string-id=\"print-footer\">Print footers</localization> -->\n    <!-- <localization string-id=\"first-page\">First page</localization> -->\n    <!-- <localization string-id=\"running\">Running</localization> -->\n    <!-- <localization string-id=\"highlight-workspace\">Highlight workspace</localization> -->\n    <localization string-id='print'>Imprimer</localization>\n    <!-- <localization string-id='print-preview'>Print preview</localization> -->\n    <localization string-id='close'>Fermer</localization>\n    <localization string-id='open-new-tab'>Ouvrir dans un nouvel onglet</localization>\n    <!-- Readability menu items, HTML only, utilized by Javascript -->\n    <localization string-id='readability-settings'>Paramètres de lecture</localization>\n    <localization string-id='readability-line-height'>Interligne</localization>\n    <localization string-id='readability-content-font-size'>Taille de police</localization>\n    <localization string-id='readability-theme'>Thème</localization>\n    <localization string-id='readability-theme-system'>Système</localization>\n    <localization string-id='readability-theme-light'>Clair</localization>\n    <localization string-id='readability-theme-dark'>Sombre</localization>\n    <localization string-id='readability-assistive-technologies'>Technologies d'assistance</localization>\n    <localization string-id='readability-expose-permalinks'>Exposer les permaliens</localization>\n    <localization string-id='reset-all'>Options par défaut</localization>\n</locale>\n","localizations/hu-HU.xml":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n<!--********************************************************************\nCopyright (C) 2014-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- See  xsl/localizations/README.md  for an explanation of this file -->\n\n<!-- hu-HU, Hungarian (Hungary) -->\n<!-- Sándor Czirbusz, czirbusz@gmail.com, 2017-04-09 -->\n\n<locale language=\"hu-HU\" direction=\"ltr\"\n        quote-primary=\"english-double\" quote-secondary=\"english-single\">\n    <!-- THEOREM-LIKE blocks -->\n    <!-- The english quotation style above is just a default, it needs adjustment -->\n    <localization string-id='theorem'>Tétel</localization>\n    <localization string-id='corollary'>Következmény</localization>\n    <localization string-id='lemma'>Lemma</localization>\n    <localization string-id='algorithm'>Algoritmus</localization>\n    <localization string-id='proposition'>Állítás</localization>\n    <localization string-id='claim'>Állítás</localization>\n    <localization string-id='fact'>Tény</localization>\n    <localization string-id='identity'>Azonosság</localization>\n    <!-- PROOF-LIKE -->\n    <localization string-id='proof'>Bizonyítás</localization>\n    <!-- <localization string-id='argument'>Argument</localization> -->\n    <!-- <localization string-id='justification'>Justification</localization> -->\n    <!-- <localization string-id='reasoning'>Reasoning</localization> -->\n    <!-- <localization string-id='explanation'>Explanation</localization> -->\n    <localization string-id='case'>Eset</localization>\n    <!-- Components of the narrative -->\n    <!-- Mathematical statements without proofs -->\n    <!-- AXIOM-LIKE blocks -->\n    <localization string-id='axiom'>Axióma</localization>\n    <localization string-id='conjecture'>Sejtés</localization>\n    <localization string-id='principle'>Elv</localization>\n    <localization string-id='heuristic'>Heurisztikus</localization>\n    <localization string-id='hypothesis'>Hipotézis</localization>\n    <localization string-id='assumption'>Feltevés</localization>\n    <!-- Definitions -->\n    <localization string-id='definition'>Definíció</localization>\n    <!-- Mathematics -->\n    <localization string-id='equation'>Egyenlet</localization>\n    <localization string-id='displaymath'>Matematikai megjelenítés</localization>\n    <!-- Types of documents, mostly for informational messages -->\n    <localization string-id='volume'>Kötet</localization>\n    <localization string-id='book'>Könyv</localization>\n    <localization string-id='article'>Cikk</localization>\n    <localization string-id='letter'>Letter</localization>\n    <!-- <localization string-id='slideshow'>Slideshow</localization> -->\n    <localization string-id='memo'>Emlékeztető</localization>\n    <localization string-id='presentation'>Prezentáció</localization>\n    <!-- Parts of a document -->\n    <localization string-id='frontmatter'>Bevezető rész</localization>\n    <localization string-id='part'>Rész</localization>\n    <localization string-id='chapter'>Fejezet</localization>\n    <localization string-id='appendix'>Függelék</localization>\n    <!-- <localization string-id='appendices'>Appendices</localization> -->\n    <localization string-id='section'>Pont</localization>\n    <localization string-id='subsection'>Alpont</localization>\n    <localization string-id='subsubsection'>alpont</localization>\n    <!-- <localization string-id='slide'>Slide</localization> -->\n    <localization string-id='introduction'>Bevezetés</localization>\n    <localization string-id='conclusion'>Következtetés</localization>\n    <localization string-id='exercises'>Feladatok</localization>\n    <!-- <localization string-id='worksheet'>Worksheet</localization> -->\n    <!-- <localization string-id='handout'>Handout</localization> -->\n    <!-- <localization string-id='reading-questions'>Reading Questions</localization> -->\n    <!-- <localization string-id='solutions'>Solutions</localization> -->\n    <!-- <localization string-id='glossary'>Glossary</localization> -->\n    <localization string-id='references'>Hivatkozások</localization>\n    <localization string-id='backmatter'>Záró rész</localization>\n    <localization string-id='paragraphs'>Paragrafusok</localization>\n    <localization string-id='subparagraph'>Al-paragrafus</localization>\n    <!-- Adjustments to titles of divisions -->\n    <!-- <localization string-id='group'>Group</localization> -->\n    <!-- Components of the narrative -->\n    <!-- REMARK-LIKE blocks -->\n    <localization string-id='remark'>Megjegyzés</localization>\n    <localization string-id='convention'>Konvenció</localization>\n    <localization string-id='note'>Megjegyzés</localization>\n    <localization string-id='observation'>Megfigyelés</localization>\n    <localization string-id='warning'>Figyelmeztetés</localization>\n    <localization string-id='insight'>Bepillantás</localization>\n    <!-- COMPUTATION-LIKE blocks -->\n    <localization string-id='computation'>Számítás</localization>\n    <localization string-id='technology'>Technológia</localization>\n    <!-- <localization string-id='data'>Data</localization> -->\n    <!-- ASIDE-LIKE blocks -->\n    <localization string-id='aside'>Kiegészítés</localization>\n    <localization string-id='biographical'>Életrajzi kiegészítés</localization>\n    <localization string-id='historical'>Történeti kiegészítés</localization>\n    <!-- EXAMPLE-LIKE blocks -->\n    <localization string-id='example'>Példa</localization>\n    <localization string-id='question'>Kérdéa</localization>\n    <localization string-id='problem'>Probléma</localization>\n    <!-- PROJECT-LIKE blocks -->\n    <localization string-id='project'>Projekt</localization>\n    <localization string-id='activity'>Aktivitás</localization>\n    <localization string-id='exploration'>Kutatás</localization>\n    <localization string-id='task'>Feladat</localization>\n    <localization string-id='investigation'>Vizsgálat</localization>\n    <localization string-id='assemblage'>Összeállítás</localization>\n    <localization string-id='poem'>Vers</localization>\n    <localization string-id='objectives'>Célkitűzések</localization>\n    <localization string-id='objective'>Célkitűzés</localization>\n    <!-- <localization string-id='outcomes'>Outcomes</localization> -->\n    <!-- <localization string-id='outcome'>Outcome</localization> -->\n    <!-- <localization string-id='openquestion'>Open Question</localization> -->\n    <!-- <localization string-id='openproblem'>Open Problem</localization> -->\n    <!-- <localization string-id='openconjecture'>Open Conjecture</localization> -->\n    <!-- <localization string-id='context'>Context</localization> -->\n    <!-- <localization string-id='discussion'>Discussion</localization> -->\n    <!-- <localization string-id='opinion'>Opinion</localization> -->\n    <!-- <localization string-id='status'>Status</localization> -->\n    <!-- <localization string-id='suggestion'>Suggestion</localization> -->\n    <localization string-id='figure'>Ábra</localization>\n    <localization string-id='table'>Táblázat</localization>\n    <localization string-id='listing'>Felsorolás</localization>\n    <localization string-id='fn'>Lábjegyzet</localization>\n    <localization string-id='contributor'>Résztvevő</localization>\n    <!-- Lists and their items -->\n    <localization string-id='list'>Lista</localization>\n    <localization string-id='li'>Tétel</localization>\n    <!-- <localization string-id='gi'>Term</localization> -->\n    <localization string-id='p'>Paragrafus</localization>\n    <localization string-id='blockquote'>Idézet</localization>\n    <!-- <localization string-id='pre'>Code Block</localization> -->\n    <!-- <localization string-id='fragment'>Fragment</localization> -->\n    <!-- Parts of an exercise and its solution -->\n    <!-- See the en-US file for a detailed explanation of the words for exercises -->\n    <localization string-id='divisionalexercise'>Feladat</localization>\n    <!-- Translation needed for Hungary Hungarian -->\n    <!-- See en-US file for distinctions here, do not repeat previous translation -->\n    <!-- <localization string-id='inlineexercise'>Checkpoint</localization> -->\n    <!-- <localization string-id='worksheetexercise'>Worksheet Exercise</localization> -->\n    <!-- <localization string-id='readingquestion'>Reading Question</localization> -->\n    <localization string-id='webwork'>WeBWorK</localization>\n    <localization string-id='hint'>Tipp</localization>\n    <localization string-id='answer'>Vélasz</localization>\n    <localization string-id='solution'>Megoldás</localization>\n    <!-- <localization string-id='subexercises'>Subexercises</localization> -->\n    <localization string-id='exercisegroup'>Feladatcsoport</localization>\n    <localization string-id='biblio'>Életrajzi bejegyzés</localization>\n    <!-- Front matter components -->\n    <localization string-id='toc'>Tartalom</localization>\n    <localization string-id='abstract'>Absztrakt</localization>\n    <localization string-id='preface'>Előszó</localization>\n    <localization string-id='acknowledgement'>Köszönetnyilvánítás</localization>\n    <localization string-id='biography'>Szerzői életrajz</localization>\n    <localization string-id='about-author'>A szerzőről</localization>\n    <localization string-id='about-authors'>A szerzőkről</localization>\n    <localization string-id='foreword'>Előszó</localization>\n    <localization string-id='dedication'>Ajánlás</localization>\n    <localization string-id='colophon'>Záradék</localization>\n    <!-- Runestone Activities -->\n    <!-- <localization string-id='video'>Video</localization> -->\n    <!-- <localization string-id='program'>Program</localization> -->\n    <!-- Runestone Exercises -->\n    <!-- <localization string-id='true'>True</localization> -->\n    <!-- <localization string-id='false'>False</localization> -->\n    <!-- <localization string-id='or'>Or</localization> -->\n    <!-- <localization string-id='either'>Either</localization> -->\n    <!-- <localization string-id='uncategorized'>Uncategorized</localization> -->\n    <!-- <localization string-id='query'>Query</localization> -->\n    <localization string-id='program-activecode'>ActiveCode</localization>\n    <!-- <localization string-id='scratch-activecode'>Scratch ActiveCode</localization> -->\n    <localization string-id='program-codelens'>CodeLens</localization>\n    <!-- Back matter components -->\n    <localization string-id='index'>Index</localization>\n    <localization string-id='jump-to'>Ugrás ide:</localization>\n    <!-- Parts of the Index -->\n    <localization string-id='see'>Lásd</localization>\n    <localization string-id='also'>Lásd még</localization>\n    <!-- Notation List headings/foot -->\n    <localization string-id='symbol'>szimbólum</localization>\n    <localization string-id='description'>Leírás</localization>\n    <localization string-id='location'>Hely</localization>\n    <localization string-id='page'>Lap</localization>\n    <localization string-id='continued'>Folytatás a következő lapon</localization>\n    <!-- Navigation Interface elements -->\n    <localization string-id='skip-to-content'>Ugrás a fő tartalomjegyzékre</localization>\n    <localization string-id='previous'>Előző</localization>\n    <localization string-id='up'>Fel</localization>\n    <localization string-id='next'>Következő</localization>\n    <localization string-id='previous-short'>El.</localization>\n    <localization string-id='up-short'>Fel</localization>\n    <localization string-id='next-short'>Köv.</localization>\n    <!-- <localization string-id='top'>Top</localization> -->\n    <localization string-id='annotations'>Magyarázatok</localization>\n    <localization string-id='feedback'>Visszacsatolás</localization>\n    <localization string-id='authored'>Authored in</localization>\n    <!-- Search Results display/dialog -->\n    <!-- <localization string-id='search-book'>Search Book</localization> -->\n    <!-- <localization string-id='search-results-heading'>Search Results</localization> -->\n    <!-- <localization string-id='no-search-results'>No results</localization> -->\n    <!-- Parts of memos and letters -->\n    <localization string-id='to'>Kinek:</localization>\n    <localization string-id='from'>Kitől:</localization>\n    <localization string-id='subject'>Tárgy</localization>\n    <localization string-id='date'>Dátum</localization>\n    <localization string-id='cc'>cc</localization>\n    <localization string-id='enclosure'>beleértve</localization>\n    <!-- Various -->\n    <localization string-id='todo'>Tennivaló</localization>\n    <localization string-id='editor'>Szerkesztő</localization>\n    <localization string-id='edition'>Kiadás</localization>\n    <localization string-id='website'>Weboldal</localization>\n    <localization string-id='copyright'>Szerzői jog</localization>\n    <!-- <localization string-id='keywords'>Keywords</localization> -->\n    <!-- HTML clickables (lowercase strings to click on) -->\n    <localization string-id='permalink'>permalink</localization>\n    <localization string-id='incontext'>Szövegkörnyezet</localization>\n    <!-- <localization string-id='standalone'>Standalone</localization> -->\n    <!-- <localization string-id='embed'>Embed</localization> -->\n    <!-- <localization string-id='embed-this-page'>Embed this page</localization> -->\n    <!-- <localization string-id='copy'>Copy</localization> -->\n    <!-- <localization string-id='profile'>Profile</localization> -->\n    <!-- Following is in ENGLISH and should be translated.  Due to its -->\n    <!-- ubiquitous nature we have not left it undefined.  See the -->\n    <!-- \"en-US\" file for a more complete explanation of its use. -->\n    <!-- Please remove this entire comment when translated.  Thanks. -->\n    <localization string-id='permalink-tooltip'>Copy heading and permalink for</localization>\n    <!-- <localization string-id='calculator'>Calculator</localization> -->\n    <!-- This needs to be defined to *something* (English) -->\n    <!-- Translate at first opportunity, please -->\n    <localization string-id='evaluate'>Evaluate</localization>\n    <!-- <localization string-id='code'>Code</localization> -->\n    <!-- <localization string-id='instructions'>Instructions</localization> -->\n    <!-- <localization string-id='correct'>Correct</localization> -->\n    <!-- <localization string-id='incorrect'>Incorrect</localization> -->\n    <!-- <localization string-id='blank'>Blank</localization> -->\n    <!-- <localization string-id='submit'>Submit</localization> -->\n    <!-- <localization string-id='check-responses'>Check Responses</localization> -->\n    <!-- <localization string-id='reveal'>Reveal</localization> -->\n    <!-- <localization string-id='randomize'>Randomize</localization> -->\n    <!-- <localization string-id='activate'>Activate</localization> -->\n    <!-- <localization string-id='reset'>Reset</localization> -->\n    <!-- <localization string-id='array'>array</localization> -->\n    <!-- <localization string-id=\"papersize\">Paper size</localization> -->\n    <!-- <localization string-id=\"printing-options\">Additional printing options</localization> -->\n    <!-- <localization string-id=\"hide-hints\">Hide hints</localization> -->\n    <!-- <localization string-id=\"hide-answers\">Hide answers</localization> -->\n    <!-- <localization string-id=\"hide-solutions\">Hide solutions</localization> -->\n    <!-- <localization string-id=\"print-header\">Print headers</localization> -->\n    <!-- <localization string-id=\"print-footer\">Print footers</localization> -->\n    <!-- <localization string-id=\"first-page\">First page</localization> -->\n    <!-- <localization string-id=\"running\">Running</localization> -->\n    <!-- <localization string-id=\"highlight-workspace\">Highlight workspace</localization> -->\n    <!-- <localization string-id='print'>Print</localization> -->\n    <!-- <localization string-id='print-preview'>Print preview</localization> -->\n    <!-- <localization string-id='close'>Close</localization> -->\n    <!-- <localization string-id='open-new-tab'>Open in new tab</localization> -->\n    <!-- Readability menu items, HTML only, utilized by Javascript -->\n    <!-- <localization string-id='readability-settings'>Readability settings</localization> -->\n    <!-- <localization string-id='readability-line-height'>Line height</localization> -->\n    <!-- <localization string-id='readability-content-font-size'>Content font size</localization> -->\n    <!-- <localization string-id='readability-theme'>Theme</localization> -->\n    <!-- <localization string-id='readability-theme-system'>System</localization> -->\n    <!-- <localization string-id='readability-theme-light'>Light</localization> -->\n    <!-- <localization string-id='readability-theme-dark'>Dark</localization> -->\n    <!-- <localization string-id='readability-assistive-technologies'>Assistive technologies</localization> -->\n    <!-- <localization string-id='readability-expose-permalinks'>Expose permalinks</localization> -->\n    <!-- <localization string-id='reset-all'>Reset All</localization> -->\n</locale>\n","localizations/it-IT.xml":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n<!--********************************************************************\nCopyright (C) 2014-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- See  xsl/localizations/README.md  for an explanation of this file -->\n\n<!-- it-IT, Italian (Italy) -->\n<!-- Valerio Monti, gedeonedepaperoni@gmail.com, 2020-07-27   -->\n\n<locale language=\"it-IT\" direction=\"ltr\"\n        quote-primary=\"english-double\" quote-secondary=\"english-single\">\n    <!-- THEOREM-LIKE blocks -->\n    <!-- The english quotation style above is just a default, it needs adjustment -->\n    <localization string-id='theorem'>Teorema</localization>\n    <localization string-id='corollary'>Corollario</localization>\n    <localization string-id='lemma'>Lemma</localization>\n    <localization string-id='algorithm'>Algoritmo</localization>\n    <localization string-id='proposition'>Proposizione</localization>\n    <localization string-id='claim'>Affermazione</localization>\n    <localization string-id='fact'>Fatto</localization>\n    <localization string-id='identity'>Identità</localization>\n    <!-- PROOF-LIKE -->\n    <localization string-id='proof'>Dimostrazione</localization>\n    <localization string-id='argument'>Argomento</localization>\n    <localization string-id='justification'>Giustificazione</localization>\n    <localization string-id='reasoning'>Ragionamento</localization>\n    <localization string-id='explanation'>Spiegazione</localization>\n    <localization string-id='case'>Caso</localization>\n    <!-- Components of the narrative -->\n    <!-- Mathematical statements without proofs -->\n    <!-- AXIOM-LIKE blocks -->\n    <localization string-id='axiom'>Assioma</localization>\n    <localization string-id='conjecture'>Congettura</localization>\n    <localization string-id='principle'>Principio</localization>\n    <localization string-id='heuristic'>Processo euristico</localization>\n    <localization string-id='hypothesis'>Ipotesi</localization>\n    <localization string-id='assumption'>Assunzione</localization>\n    <!-- Definitions -->\n    <localization string-id='definition'>Definizione</localization>\n    <!-- Mathematics -->\n    <localization string-id='equation'>Equazione</localization>\n    <localization string-id='displaymath'>Matematica in display</localization>\n    <!-- Types of documents, mostly for informational messages -->\n    <localization string-id='volume'>Volume</localization>\n    <localization string-id='book'>Libro</localization>\n    <localization string-id='article'>Articolo</localization>\n    <localization string-id='letter'>Lettera</localization>\n    <localization string-id='slideshow'>Sequenza di diapositive</localization>\n    <localization string-id='memo'>Memo</localization>\n    <localization string-id='presentation'>Presentazione</localization>\n    <!-- Parts of a document -->\n    <localization string-id='frontmatter'>Materiale iniziale</localization>\n    <localization string-id='part'>Parte</localization>\n    <localization string-id='chapter'>Capitolo</localization>\n    <localization string-id='appendix'>Appendice</localization>\n    <localization string-id='appendices'>Appendici</localization>\n    <localization string-id='section'>Paragrafo</localization>\n    <localization string-id='subsection'>Sottoparagrafo</localization>\n    <localization string-id='subsubsection'>Sotto-sottoparagrafo</localization>\n    <localization string-id='slide'>Diapositiva</localization>\n    <localization string-id='introduction'>Introduzione</localization>\n    <localization string-id='conclusion'>Conclusione</localization>\n    <localization string-id='exercises'>Esercizi</localization>\n    <localization string-id='worksheet'>Scheda didattica</localization>\n    <localization string-id='handout'>Dispensa</localization>\n    <localization string-id='reading-questions'>Domande di comprensione del testo</localization>\n    <localization string-id='solutions'>Soluzioni</localization>\n    <localization string-id='glossary'>Glossario</localization>\n    <localization string-id='references'>Bibliografia</localization>\n    <localization string-id='backmatter'>Materiale finale</localization>\n    <localization string-id='paragraphs'>Capoversi</localization>\n    <localization string-id='subparagraph'>Sottocapoverso</localization>\n    <!-- Adjustments to titles of divisions -->\n    <localization string-id='group'>Gruppo</localization>\n    <!-- Components of the narrative -->\n    <!-- REMARK-LIKE blocks -->\n    <localization string-id='remark'>Osservazione</localization>\n    <localization string-id='convention'>Convenzione</localization>\n    <localization string-id='note'>Nota</localization>\n    <!-- <localization string-id='observation'>Observation</localization> -->\n    <localization string-id='warning'>Avviso</localization>\n    <localization string-id='insight'>Intuizione</localization>\n    <!-- COMPUTATION-LIKE blocks -->\n    <localization string-id='computation'>Computazione</localization>\n    <localization string-id='technology'>Tecnologia</localization>\n    <localization string-id='data'>Dati</localization>\n    <!-- ASIDE-LIKE blocks -->\n    <localization string-id='aside'>Inciso</localization>\n    <localization string-id='biographical'>Inciso biografico</localization>\n    <localization string-id='historical'>Inciso storico</localization>\n    <!-- EXAMPLE-LIKE blocks -->\n    <localization string-id='example'>Esempio</localization>\n    <localization string-id='question'>Domanda</localization>\n    <localization string-id='problem'>Problema</localization>\n    <!-- PROJECT-LIKE blocks -->\n    <localization string-id='project'>Progetto</localization>\n    <localization string-id='activity'>Attività</localization>\n    <localization string-id='exploration'>Esplorazione</localization>\n    <localization string-id='task'>Compito</localization>\n    <localization string-id='investigation'>Investigazione</localization>\n    <localization string-id='assemblage'>Raccolta</localization>\n    <localization string-id='poem'>Poema</localization>\n    <localization string-id='objectives'>Obiettivi</localization>\n    <localization string-id='objective'>Obiettivo</localization>\n    <localization string-id='outcomes'>Risultati</localization>\n    <localization string-id='outcome'>Risultato</localization>\n    <localization string-id='openquestion'>Domanda aperta</localization>\n    <localization string-id='openproblem'>Problema aperto</localization>\n    <localization string-id='openconjecture'>Congettura aperta</localization>\n    <localization string-id='context'>Contesto</localization>\n    <localization string-id='discussion'>Discussione</localization>\n    <localization string-id='opinion'>Opinione</localization>\n    <localization string-id='status'>Stato</localization>\n    <localization string-id='suggestion'>Idea</localization>\n    <localization string-id='figure'>Figura</localization>\n    <localization string-id='table'>Tabella</localization>\n    <localization string-id='listing'>Listato</localization>\n    <localization string-id='fn'>Nota a piè di pagina</localization>\n    <localization string-id='contributor'>Contributore</localization>\n    <!-- Lists and their items -->\n    <localization string-id='list'>Elenco</localization>\n    <localization string-id='li'>Punto</localization>\n    <localization string-id='gi'>Termine</localization>\n    <localization string-id='p'>Capoverso</localization>\n    <localization string-id='blockquote'>Citazione</localization>\n    <localization string-id='pre'>Blocco di codice</localization>\n    <localization string-id='fragment'>Porzione</localization>\n    <!-- Parts of an exercise and its solution -->\n    <!-- See the en-US file for a detailed explanation of the words for exercises -->\n    <localization string-id='divisionalexercise'>Esercizio</localization>\n    <localization string-id='inlineexercise'>Punto di controllo</localization>\n    <localization string-id='worksheetexercise'>Esercizio in scheda didattica</localization>\n    <localization string-id='readingquestion'>Domanda di comprensione del testo</localization>\n    <localization string-id='webwork'>WeBWorK</localization>\n    <localization string-id='hint'>Suggerimento</localization>\n    <localization string-id='answer'>Risposta</localization>\n    <localization string-id='solution'>Soluzione</localization>\n    <localization string-id='subexercises'>Sottoesercizi</localization>\n    <localization string-id='exercisegroup'>Gruppo di esercizi</localization>\n    <localization string-id='biblio'>Riferimento bibliografico</localization>\n    <!-- Front matter components -->\n    <localization string-id='toc'>Indice</localization>\n    <localization string-id='abstract'>Sommario</localization>\n    <localization string-id='preface'>Prefazione</localization>\n    <localization string-id='acknowledgement'>Ringraziamenti</localization>\n    <localization string-id='biography'>Biografia dell'autore</localization>\n    <localization string-id='about-author'>Sull'autore</localization>\n    <localization string-id='about-authors'>Sugli autori</localization>\n    <localization string-id='foreword'>Presentazione</localization>\n    <localization string-id='dedication'>Dedica</localization>\n    <localization string-id='colophon'>Colophon</localization>\n    <!-- Runestone Activities -->\n    <localization string-id='video'>Video</localization>\n    <localization string-id='program'>Programma</localization>\n    <!-- Runestone Exercises -->\n    <localization string-id='true'>Vero</localization>\n    <localization string-id='false'>Falso</localization>\n    <localization string-id='or'>O</localization>\n    <localization string-id='either'>O</localization>\n    <localization string-id='uncategorized'>Senza categoria</localization>\n    <!-- <localization string-id='query'>Query</localization> -->\n    <localization string-id='program-activecode'>ActiveCode</localization>\n    <!-- <localization string-id='scratch-activecode'>Scratch ActiveCode</localization> -->\n    <localization string-id='program-codelens'>CodeLens</localization>\n    <!-- Back matter components -->\n    <localization string-id='index'>Indice analitico</localization>\n    <localization string-id='jump-to'>Vai a:</localization>\n    <!-- Parts of the Index -->\n    <localization string-id='see'>Vedi</localization>\n    <localization string-id='also'>Vedi anche</localization>\n    <!-- Notation List headings/foot -->\n    <localization string-id='symbol'>Simbolo</localization>\n    <localization string-id='description'>Descrizione</localization>\n    <localization string-id='location'>Posizione</localization>\n    <localization string-id='page'>Pag.</localization>\n    <localization string-id='continued'>Continua alla pagina successiva</localization>\n    <!-- Navigation Interface elements -->\n    <localization string-id='skip-to-content'>Vai all'indice generale</localization>\n    <localization string-id='previous'>Precedente</localization>\n    <localization string-id='up'>Su</localization>\n    <localization string-id='next'>Successivo</localization>\n    <localization string-id='previous-short'>Prec</localization>\n    <localization string-id='up-short'>Su</localization>\n    <localization string-id='next-short'>Succ</localization>\n    <localization string-id='top'>Inizio</localization>\n    <localization string-id='annotations'>Annotazioni</localization>\n    <localization string-id='feedback'>Feedback</localization>\n    <localization string-id='authored'>Redatto in PreTeXt</localization>\n    <!-- Search Results display/dialog -->\n    <localization string-id='search-book'>Cerca nel libro</localization>\n    <localization string-id='search-results-heading'>Risultati</localization>\n    <localization string-id='no-search-results'>Nessun risultato</localization>\n    <!-- Parts of memos and letters -->\n    <localization string-id='to'>Per</localization>\n    <localization string-id='from'>Da</localization>\n    <localization string-id='subject'>Oggetto</localization>\n    <localization string-id='date'>Data</localization>\n    <localization string-id='cc'>e p.c.</localization>\n    <localization string-id='enclosure'>allegati</localization>\n    <!-- Various -->\n    <localization string-id='todo'>Da fare</localization>\n    <localization string-id='editor'>Curatore</localization>\n    <localization string-id='edition'>Edizione</localization>\n    <localization string-id='website'>Sito web</localization>\n    <localization string-id='copyright'>Copyright</localization>\n    <localization string-id='keywords'>Parole chiave</localization>\n    <!-- HTML clickables (lowercase strings to click on) -->\n    <localization string-id='permalink'>permalink</localization>\n    <localization string-id='incontext'>Nel Contesto</localization>\n    <!-- <localization string-id='standalone'>Standalone</localization> -->\n    <localization string-id='embed'>Incorpora</localization>\n    <localization string-id='embed-this-page'>Incorpora questa pagina</localization>\n    <localization string-id='copy'>Copia</localization>\n    <localization string-id='profile'>Profilo</localization>\n    <localization string-id='permalink-tooltip'>Copia titolo e permalink per</localization>\n    <localization string-id='calculator'>Calcolatrice</localization>\n    <localization string-id='evaluate'>Calcola</localization>\n    <localization string-id='code'>Codice</localization>\n    <localization string-id='instructions'>Istruzioni</localization>\n    <localization string-id='correct'>Giusto</localization>\n    <localization string-id='incorrect'>Sbagliato</localization>\n    <localization string-id='blank'>Spazio vuoto</localization>\n    <localization string-id='submit'>Invia</localization>\n    <localization string-id='check-responses'>Controlla le risposte</localization>\n    <localization string-id='reveal'>Mostra</localization>\n    <localization string-id='randomize'>Casuale</localization>\n    <localization string-id='activate'>Attiva</localization>\n    <localization string-id='reset'>Azzera</localization>\n    <localization string-id='array'>tabella</localization>\n    <localization string-id=\"papersize\">Formato carta</localization>\n    <localization string-id=\"printing-options\">Opzioni di stampa addizionali</localization>\n    <localization string-id=\"hide-hints\">Nascondi suggerimenti</localization>\n    <localization string-id=\"hide-answers\">Nascondi risposte</localization>\n    <localization string-id=\"hide-solutions\">Nascondi soluzioni</localization>\n    <localization string-id=\"print-header\">Stampa intestazioni</localization>\n    <localization string-id=\"print-footer\">Stampa piè di pagina</localization>\n    <localization string-id=\"first-page\">Prima pagina</localization>\n    <localization string-id=\"running\">Successive</localization>\n    <localization string-id=\"highlight-workspace\">Evidenzia spazio di lavoro</localization>\n    <localization string-id='print'>Stampa</localization>\n    <localization string-id='print-preview'>Anteprima di stampa</localization>\n    <localization string-id='close'>Chiudi</localization>\n    <localization string-id='open-new-tab'>Apri in nuova scheda</localization>\n    <!-- Readability menu items, HTML only, utilized by Javascript -->\n    <localization string-id='readability-settings'>Impostazioni di leggibilità</localization>\n    <localization string-id='readability-line-height'>Interlinea</localization>\n    <localization string-id='readability-content-font-size'>Dimensione dei caratteri del contenuto</localization>\n    <localization string-id='readability-theme'>Tema</localization>\n    <localization string-id='readability-theme-system'>Sistema</localization>\n    <localization string-id='readability-theme-light'>Chiaro</localization>\n    <localization string-id='readability-theme-dark'>Scuro</localization>\n    <localization string-id='readability-assistive-technologies'>Tecnologie assistive</localization>\n    <localization string-id='readability-expose-permalinks'>Mostra i permalink</localization>\n    <localization string-id='reset-all'>Ripristina tutte</localization>\n</locale>\n","localizations/ku-CKB.xml":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n<!--********************************************************************\nCopyright (C) 2014-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- See  xsl/localizations/README.md  for an explanation of this file -->\n\n<!-- ku-CKB, Kurdish (Cental Kurdish) -->\n<!-- Rebin Muhammad, reben80@gmail.com, 2023-06-24 -->\n\n<locale language=\"ku-CKB\" direction=\"rtl\"\n        quote-primary=\"english-double\" quote-secondary=\"english-single\">\n    <!-- THEOREM-LIKE blocks -->\n    <!-- The english quotation style above is just a default, it needs adjustment -->\n    <localization string-id='theorem'>بیردۆز</localization>\n    <localization string-id='corollary'>ئاکام</localization>\n    <localization string-id='lemma'>لێما</localization>\n    <localization string-id='algorithm'>ئەلگۆریزم</localization>\n    <localization string-id='proposition'>دەستەواژە</localization>\n    <localization string-id='claim'>بانگەشە</localization>\n    <localization string-id='fact'>ڕاستی</localization>\n    <localization string-id='identity'>بێلایەن</localization>\n    <!-- PROOF-LIKE -->\n    <localization string-id='proof'>سەلماندن</localization>\n    <localization string-id='argument'>ئەرگویمينت</localization>\n    <localization string-id='justification'>پاساو</localization>\n    <localization string-id='reasoning'>لێکدانەوە</localization>\n    <localization string-id='explanation'>ڕوونکردنەوە</localization>\n    <localization string-id='case'>‌‌دۆخ</localization>\n    <!-- Components of the narrative -->\n    <!-- Mathematical statements without proofs -->\n    <!-- AXIOM-LIKE blocks -->\n    <localization string-id='axiom'>بەڵگەنەویست</localization>\n    <localization string-id='conjecture'>کۆنجێکچەر</localization>\n    <localization string-id='principle'>پرەنسەپڵ</localization>\n    <localization string-id='heuristic'>ئیرشادی</localization>\n    <localization string-id='hypothesis'>گریمانە</localization>\n    <localization string-id='assumption'>گریمانکردن</localization>\n    <!-- Definitions -->\n    <localization string-id='definition'>پێناسە</localization>\n    <!-- Mathematics -->\n    <localization string-id='equation'>هاوکێشە</localization>\n    <localization string-id='displaymath'>بیرکاری پیشانبدە</localization>\n    <!-- Types of documents, mostly for informational messages -->\n    <localization string-id='volume'>بەرگ</localization>\n    <localization string-id='book'>کتێب</localization>\n    <localization string-id='article'>مەقالە</localization>\n    <localization string-id='letter'>نامە</localization>\n    <localization string-id='slideshow'>سلاید</localization>\n    <localization string-id='memo'>یادنامە</localization>\n    <localization string-id='presentation'>پێشكه‌شكاری</localization>\n    <!-- Parts of a document -->\n    <localization string-id='frontmatter'>بەرگی پشتەوە</localization>\n    <localization string-id='part'>بەش</localization>\n    <localization string-id='chapter'>بەش</localization>\n    <localization string-id='appendix'>پاشکۆ</localization>\n    <localization string-id='appendices'>پاشکۆکان</localization>\n    <localization string-id='section'>بەش</localization>\n    <localization string-id='subsection'>کەرتەبەش</localization>\n    <localization string-id='subsubsection'>کەرتەبەش</localization>\n    <localization string-id='slide'>سلاید</localization>\n    <localization string-id='introduction'>پێشەکی</localization>\n    <localization string-id='conclusion'>دەرئەنجام</localization>\n    <localization string-id='exercises'>مەشق</localization>\n    <localization string-id='worksheet'>پەڕەیکار</localization>\n    <!-- <localization string-id='handout'>Handout</localization> -->\n    <localization string-id='reading-questions'>پرسیاری خوێندنەوە</localization>\n    <localization string-id='solutions'>شیکار</localization>\n    <localization string-id='glossary'>فەرهەنگۆک</localization>\n    <localization string-id='references'>سەرچاوەکان</localization>\n    <localization string-id='backmatter'>بەرگی پشتەوە</localization>\n    <localization string-id='paragraphs'>پەڕەگرافەکان</localization>\n    <localization string-id='subparagraph'>بەشە پەرەگراف</localization>\n    <!-- Adjustments to titles of divisions -->\n    <!-- <localization string-id='group'>Group</localization> -->\n    <!-- Components of the narrative -->\n    <!-- REMARK-LIKE blocks -->\n    <localization string-id='remark'>تێبینی</localization>\n    <localization string-id='convention'>ڕێکەوتن</localization>\n    <localization string-id='note'>تيبینی</localization>\n    <localization string-id='observation'>لێ وردبوونەوە</localization>\n    <localization string-id='warning'>وریاکردنەوە</localization>\n    <localization string-id='insight'>دووربینی</localization>\n    <!-- COMPUTATION-LIKE blocks -->\n    <localization string-id='computation'>کۆمپیوتەیشن</localization>\n    <localization string-id='technology'>تەکنەلۆجی</localization>\n    <localization string-id='data'>بەروار</localization>\n    <!-- ASIDE-LIKE blocks -->\n    <localization string-id='aside'>بەجیا</localization>\n    <localization string-id='biographical'>ژیاننامە بە جیا</localization>\n    <localization string-id='historical'>مێژووی بە جیا</localization>\n    <!-- EXAMPLE-LIKE blocks -->\n    <localization string-id='example'>نموونە</localization>\n    <localization string-id='question'>پرسیار</localization>\n    <localization string-id='problem'>کێشە</localization>\n    <!-- PROJECT-LIKE blocks -->\n    <localization string-id='project'>پڕۆژە</localization>\n    <localization string-id='activity'>چالاکی</localization>\n    <localization string-id='exploration'>کنەکردن</localization>\n    <localization string-id='task'>ئەرک</localization>\n    <localization string-id='investigation'>پشکنین</localization>\n    <localization string-id='assemblage'>پێکەوەنان</localization>\n    <localization string-id='poem'>هۆنراوە</localization>\n    <localization string-id='objectives'>ئامانجەکان</localization>\n    <localization string-id='objective'>ئامانج</localization>\n    <localization string-id='outcomes'>دەرهاویشتەکان</localization>\n    <localization string-id='outcome'>دەرهاویشتە</localization>\n    <localization string-id='openquestion'>پرسیاری کراوە</localization>\n    <localization string-id='openproblem'>کێشەی کراوە</localization>\n    <localization string-id='openconjecture'>کۆنجێکچەری کراوە</localization>\n    <localization string-id='context'>کۆنتێکست</localization>\n    <localization string-id='discussion'>گفتووگۆ</localization>\n    <localization string-id='opinion'>بۆچوون</localization>\n    <localization string-id='status'>‌‌دۆخ</localization>\n    <localization string-id='suggestion'>پێشنیاز</localization>\n    <localization string-id='figure'>وێنە</localization>\n    <localization string-id='table'>خشتە</localization>\n    <localization string-id='listing'>لیستەگرتن</localization>\n    <localization string-id='fn'>پەراوێز</localization>\n    <localization string-id='contributor'>بەژداربوو</localization>\n    <!-- Lists and their items -->\n    <localization string-id='list'>لیست</localization>\n    <localization string-id='li'>بڕگە</localization>\n    <localization string-id='gi'>تێرم</localization>\n    <localization string-id='p'>پەرەگراف</localization>\n    <localization string-id='blockquote'>ووتەی وەرگیراو</localization>\n    <localization string-id='pre'>بلۆکی کۆد</localization>\n    <localization string-id='fragment'>پارچە</localization>\n    <!-- Parts of an exercise and its solution -->\n    <localization string-id='divisionalexercise'>مەشق</localization>\n    <localization string-id='inlineexercise'>خاڵی پشکنین</localization>\n    <localization string-id='worksheetexercise'>پەڕەکاری ڕاهێنانەکان</localization>\n    <localization string-id='readingquestion'>پرسیارەکانی خوێندنەوە</localization>\n    <localization string-id='webwork'>WeBWorK</localization>\n    <localization string-id='hint'>یارمەتی</localization>\n    <localization string-id='answer'>وەڵام</localization>\n    <localization string-id='solution'>شیکار</localization>\n    <localization string-id='subexercises'>بەشە-ڕاهێنانەکان</localization>\n    <localization string-id='exercisegroup'>گروپی ڕاهێنانەکان</localization>\n    <localization string-id='biblio'>پيڕستی بایۆلۆگرافیا</localization>\n    <!-- Front matter components -->\n    <localization string-id='toc'>ناوەڕۆک</localization>\n    <localization string-id='abstract'>پوختە</localization>\n    <localization string-id='preface'>پێشەکی</localization>\n    <localization string-id='acknowledgement'>پێزانین</localization>\n    <localization string-id='biography'>ژیاننامەی نووسەر</localization>\n    <localization string-id='about-author'>دەربارەی نوسەر</localization>\n    <localization string-id='about-authors'>دەربارەی نوسەرەکان</localization>\n    <localization string-id='foreword'>پێشەکی</localization>\n    <localization string-id='dedication'>پێشکەشە </localization>\n    <localization string-id='colophon'>هاوپلان</localization>\n    <!-- Runestone Activities -->\n    <localization string-id='video'>ڤیدیۆ</localization>\n    <localization string-id='program'>پرۆگرام</localization>\n    <!-- Runestone Exercises -->\n    <!-- <localization string-id='true'>True</localization> -->\n    <!-- <localization string-id='false'>False</localization> -->\n    <!-- <localization string-id='or'>Or</localization> -->\n    <!-- <localization string-id='either'>Either</localization> -->\n    <!-- <localization string-id='uncategorized'>Uncategorized</localization> -->\n    <!-- <localization string-id='query'>Query</localization> -->\n    <localization string-id='program-activecode'>کۆد-چالاکردن</localization>\n    <!-- <localization string-id='scratch-activecode'>Scratch ActiveCode</localization> -->\n    <localization string-id='program-codelens'>CodeLens</localization>\n    <!-- Back matter components -->\n    <localization string-id='index'>پێرست</localization>\n    <localization string-id='jump-to'>بچۆرە سەر</localization>\n    <!-- Parts of the Index -->\n    <localization string-id='see'>تەماشا بکە</localization>\n    <localization string-id='also'>تەماشای ئەمەیش بکە</localization>\n    <!-- Notation List headings/foot -->\n    <localization string-id='symbol'>سیمبول</localization>\n    <localization string-id='description'>وەسفکردن</localization>\n    <localization string-id='location'>شوێن</localization>\n    <localization string-id='page'>پەڕە</localization>\n    <localization string-id='continued'>بەردەوەمبە بۆ سەر پەڕەی داهاتوو</localization>\n    <!-- Navigation Interface elements -->\n    <localization string-id='skip-to-content'>بازبدە بۆ سەر بابەتە سەرەکیەکە</localization>\n    <localization string-id='previous'>پێشووتر</localization>\n    <localization string-id='up'>سەرەوە</localization>\n    <localization string-id='next'>داهاتوو</localization>\n    <localization string-id='previous-short'>پێشوو</localization>\n    <localization string-id='up-short'>سەرەوە</localization>\n    <localization string-id='next-short'>داهاتوو</localization>\n    <!-- <localization string-id='top'>Top</localization> -->\n    <localization string-id='annotations'>په‌راوێزنووسینەکان</localization>\n    <localization string-id='feedback'>فیدباک</localization>\n    <localization string-id='authored'>بەرهەمهاتووە PreTeXt لەڕیگای </localization>\n    <!-- Search Results display/dialog -->\n    <!-- <localization string-id='search-book'>Search Book</localization> -->\n    <localization string-id='search-results-heading'>ئەنجامی گەڕان</localization>\n    <localization string-id='no-search-results'>ەنجامی-گەڕانەکان-نیە</localization>\n    <!-- Parts of memos and letters -->\n    <localization string-id='to'>بۆ</localization>\n    <localization string-id='from'>لە</localization>\n    <localization string-id='subject'>بابەت</localization>\n    <localization string-id='date'>بەروار</localization>\n    <localization string-id='cc'>cc</localization>\n    <localization string-id='enclosure'>پیچانەوە</localization>\n    <!-- Various -->\n    <localization string-id='todo'>بۆ کردنی</localization>\n    <localization string-id='editor'>دەستکاریکار</localization>\n    <localization string-id='edition'>چاپ</localization>\n    <localization string-id='website'>وێبسایت</localization>\n    <localization string-id='copyright'>مافی پاراستن</localization>\n    <!-- <localization string-id='keywords'>Keywords</localization> -->\n    <!-- HTML clickables (lowercase strings to click on) -->\n    <localization string-id='permalink'>بەستەری چەسپاو</localization>\n    <localization string-id='incontext'>ناو-کۆنتێکستدا</localization>\n    <!-- <localization string-id='standalone'>Standalone</localization> -->\n    <!-- <localization string-id='embed'>Embed</localization> -->\n    <!-- <localization string-id='embed-this-page'>Embed this page</localization> -->\n    <!-- <localization string-id='copy'>Copy</localization> -->\n    <!-- <localization string-id='profile'>Profile</localization> -->\n    <!-- Following is in ENGLISH and should be translated.  Due to its -->\n    <!-- ubiquitous nature we have not left it undefined.  See the -->\n    <!-- \"en-US\" file for a more complete explanation of its use. -->\n    <!-- Please remove this entire comment when translated.  Thanks. -->\n    <localization string-id='permalink-tooltip'>Copy heading and permalink for</localization>\n    <!-- <localization string-id='calculator'>Calculator</localization> -->\n    <localization string-id='evaluate'>نرخ دۆزینەوە</localization>\n    <!-- <localization string-id='code'>Code</localization> -->\n    <localization string-id='instructions'>ڕێنماییەکان</localization>\n    <localization string-id='correct'>ڕاست</localization>\n    <localization string-id='incorrect'>ناڕاست</localization>\n    <localization string-id='blank'>بەتاڵ</localization>\n    <localization string-id='submit'>پشتڕاستی بکەوە</localization>\n    <localization string-id='check-responses'>وەڵامەکەت ساغبکەرەوە</localization>\n    <localization string-id='reveal'>پیشانی بدە</localization>\n    <localization string-id='randomize'>هەرەمەکیکردن</localization>\n    <localization string-id='activate'>چالاکردن</localization>\n    <localization string-id='reset'>ڕێکخستنەوە</localization>\n    <localization string-id='array'>ڕیزکراو</localization>\n    <!-- <localization string-id=\"papersize\">Paper size</localization> -->\n    <!-- <localization string-id=\"printing-options\">Additional printing options</localization> -->\n    <!-- <localization string-id=\"hide-hints\">Hide hints</localization> -->\n    <!-- <localization string-id=\"hide-answers\">Hide answers</localization> -->\n    <!-- <localization string-id=\"hide-solutions\">Hide solutions</localization> -->\n    <!-- <localization string-id=\"print-header\">Print headers</localization> -->\n    <!-- <localization string-id=\"print-footer\">Print footers</localization> -->\n    <!-- <localization string-id=\"first-page\">First page</localization> -->\n    <!-- <localization string-id=\"running\">Running</localization> -->\n    <!-- <localization string-id=\"highlight-workspace\">Highlight workspace</localization> -->\n    <localization string-id='print'>پرنت</localization>\n    <!-- <localization string-id='print-preview'>Print preview</localization> -->\n    <!-- <localization string-id='close'>Close</localization> -->\n    <!-- <localization string-id='open-new-tab'>Open in new tab</localization> -->\n    <!-- Readability menu items, HTML only, utilized by Javascript -->\n    <!-- <localization string-id='readability-settings'>Readability settings</localization> -->\n    <!-- <localization string-id='readability-line-height'>Line height</localization> -->\n    <!-- <localization string-id='readability-content-font-size'>Content font size</localization> -->\n    <!-- <localization string-id='readability-theme'>Theme</localization> -->\n    <!-- <localization string-id='readability-theme-system'>System</localization> -->\n    <!-- <localization string-id='readability-theme-light'>Light</localization> -->\n    <!-- <localization string-id='readability-theme-dark'>Dark</localization> -->\n    <!-- <localization string-id='readability-assistive-technologies'>Assistive technologies</localization> -->\n    <!-- <localization string-id='readability-expose-permalinks'>Expose permalinks</localization> -->\n    <!-- <localization string-id='reset-all'>Reset All</localization> -->\n</locale>\n","localizations/localizations.xml":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n<!--********************************************************************\nCopyright (C) 2014-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- See  xsl/localizations/README.md  for an explanation of this file -->\n<!-- Please respect alphabetical order here                            -->\n\n<!-- NB: there are two very similar elements for each language since   -->\n<!-- they each get used for slightly different purposes (reading       -->\n<!-- files, verifying support) and need to be converted as node-sets   -->\n<!-- without any intermediate manipulation.                            -->\n\n<localizations xmlns:xi=\"http://www.w3.org/2001/XInclude\">\n    <locale>af-ZA</locale><filename>af-ZA.xml</filename>\n    <locale>bg-BG</locale><filename>bg-BG.xml</filename>\n    <locale>cs-CZ</locale><filename>cs-CZ.xml</filename>\n    <locale>ca-ES</locale><filename>ca-ES.xml</filename>\n    <locale>de-DE</locale><filename>de-DE.xml</filename>\n    <locale>en-US</locale><filename>en-US.xml</filename>\n    <locale>es-ES</locale><filename>es-ES.xml</filename>\n    <locale>fi-FI</locale><filename>fi-FI.xml</filename>\n    <locale>fr-CA</locale><filename>fr-CA.xml</filename>\n    <locale>fr-FR</locale><filename>fr-FR.xml</filename>\n    <locale>hu-HU</locale><filename>hu-HU.xml</filename>\n    <locale>it-IT</locale><filename>it-IT.xml</filename>\n    <locale>ku-CKB</locale><filename>ku-CKB.xml</filename>\n    <locale>nl-NL</locale><filename>nl-NL.xml</filename>\n    <locale>pt-BR</locale><filename>pt-BR.xml</filename>\n    <locale>pt-PT</locale><filename>pt-PT.xml</filename>\n    <locale>zh-HANS</locale><filename>zh-HANS.xml</filename>\n</localizations>\n","localizations/nl-NL.xml":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n<!--********************************************************************\nCopyright (C) 2014-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- See  xsl/localizations/README.md  for an explanation of this file -->\n\n<!-- nl-NL, Dutch (The Netherlands) -->\n<!-- Gosia Wrzesinska, gosia@coderso.com, 2022-12-21   -->\n\n<locale language=\"nl-NL\" direction=\"ltr\"\n        quote-primary=\"english-double\" quote-secondary=\"english-single\">\n    <!-- THEOREM-LIKE blocks -->\n    <!-- The english quotation style above is just a default, it needs adjustment -->\n    <localization string-id='theorem'>Stelling</localization>\n    <localization string-id='corollary'>Gevolg</localization>\n    <localization string-id='lemma'>Lemma</localization>\n    <localization string-id='algorithm'>Algoritme</localization>\n    <localization string-id='proposition'>Propositie</localization>\n    <localization string-id='claim'>Claim</localization>\n    <localization string-id='fact'>Feit</localization>\n    <localization string-id='identity'>Identiteit</localization>\n    <!-- PROOF-LIKE -->\n    <localization string-id='proof'>Bewijs</localization>\n    <localization string-id='argument'>Argument</localization>\n    <localization string-id='justification'>Verantwoording</localization>\n    <localization string-id='reasoning'>Redenering</localization>\n    <localization string-id='explanation'>Uitleg</localization>\n    <localization string-id='case'>Geval</localization>\n    <!-- Components of the narrative -->\n    <!-- Mathematical statements without proofs -->\n    <!-- AXIOM-LIKE blocks -->\n    <localization string-id='axiom'>Axioma</localization>\n    <localization string-id='conjecture'>Vermoeden</localization>\n    <localization string-id='principle'>Principe</localization>\n    <localization string-id='heuristic'>Heuristiek</localization>\n    <localization string-id='hypothesis'>Hypothese</localization>\n    <localization string-id='assumption'>Aanname</localization>\n    <!-- Definitions -->\n    <localization string-id='definition'>Definitie</localization>\n    <!-- Mathematics -->\n    <localization string-id='equation'>Formule</localization>\n    <!-- <localization string-id='displaymath'>Display Mathematics</localization> -->\n    <!-- Types of documents, mostly for informational messages -->\n    <localization string-id='volume'>Boekdeel</localization>\n    <localization string-id='book'>Boek</localization>\n    <localization string-id='article'>Artikel</localization>\n    <localization string-id='letter'>Brief</localization>\n    <localization string-id='slideshow'>Diavoorstelling</localization>\n    <localization string-id='memo'>Notitie</localization>\n    <localization string-id='presentation'>Presentatie</localization>\n    <!-- Parts of a document -->\n    <localization string-id='frontmatter'>Voorpagina</localization>\n    <localization string-id='part'>Deel</localization>\n    <localization string-id='chapter'>Hoofdstuk</localization>\n    <localization string-id='appendix'>Bijlage</localization>\n    <localization string-id='appendices'>Bijlagen</localization>\n    <localization string-id='section'>Sectie</localization>\n    <localization string-id='subsection'>Subsectie</localization>\n    <localization string-id='subsubsection'>Subsubsectie</localization>\n    <localization string-id='slide'>Dia</localization>\n    <localization string-id='introduction'>Inleiding</localization>\n    <localization string-id='conclusion'>Slot</localization>\n    <localization string-id='exercises'>Oefeningen</localization>\n    <localization string-id='worksheet'>Werkblad</localization>\n    <!-- <localization string-id='handout'>Handout</localization> -->\n    <!-- <localization string-id='reading-questions'>Reading Questions</localization> -->\n    <localization string-id='solutions'>Oplossingen</localization>\n    <localization string-id='glossary'>Begrippenlijst</localization>\n    <localization string-id='references'>Verwijzingen</localization>\n    <localization string-id='backmatter'>Achterpagina</localization>\n    <localization string-id='paragraphs'>Alinea's</localization>\n    <localization string-id='subparagraph'>Subalinea</localization>\n    <!-- Adjustments to titles of divisions -->\n    <!-- <localization string-id='group'>Group</localization> -->\n    <!-- Components of the narrative -->\n    <!-- REMARK-LIKE blocks -->\n    <localization string-id='remark'>Opmerking</localization>\n    <localization string-id='convention'>Conventie</localization>\n    <localization string-id='note'>Notitie</localization>\n    <localization string-id='observation'>Observatie</localization>\n    <localization string-id='warning'>Waarschuwing</localization>\n    <localization string-id='insight'>Inzicht</localization>\n    <!-- COMPUTATION-LIKE blocks -->\n    <localization string-id='computation'>Berekening</localization>\n    <localization string-id='technology'>Technologie</localization>\n    <!-- <localization string-id='data'>Data</localization> -->\n    <!-- ASIDE-LIKE blocks -->\n    <localization string-id='aside'>Aside</localization>\n    <localization string-id='biographical'>Biographical Aside</localization>\n    <localization string-id='historical'>Historical Aside</localization>\n    <!-- EXAMPLE-LIKE blocks -->\n    <localization string-id='example'>Voorbeeld</localization>\n    <localization string-id='question'>Vraag</localization>\n    <localization string-id='problem'>Probleem</localization>\n    <!-- PROJECT-LIKE blocks -->\n    <localization string-id='project'>Project</localization>\n    <localization string-id='activity'>Activiteit</localization>\n    <localization string-id='exploration'>Verkenning</localization>\n    <localization string-id='task'>Taak</localization>\n    <localization string-id='investigation'>Onderzoek</localization>\n    <localization string-id='assemblage'>Verzameling</localization>\n    <localization string-id='poem'>Gedicht</localization>\n    <localization string-id='objectives'>Doelstellingen</localization>\n    <localization string-id='objective'>Doelstelling</localization>\n    <localization string-id='outcomes'>Uitkomsten</localization>\n    <localization string-id='outcome'>Uitkomst</localization>\n    <!-- <localization string-id='openquestion'>Open Question</localization> -->\n    <!-- <localization string-id='openproblem'>Open Problem</localization> -->\n    <!-- <localization string-id='openconjecture'>Open Conjecture</localization> -->\n    <!-- <localization string-id='context'>Context</localization> -->\n    <!-- <localization string-id='discussion'>Discussion</localization> -->\n    <!-- <localization string-id='opinion'>Opinion</localization> -->\n    <!-- <localization string-id='status'>Status</localization> -->\n    <!-- <localization string-id='suggestion'>Suggestion</localization> -->\n    <localization string-id='figure'>Afbeelding</localization>\n    <localization string-id='table'>Tabel</localization>\n    <!-- <localization string-id='listing'>Listing</localization> -->\n    <localization string-id='fn'>Voetnoot</localization>\n    <!-- <localization string-id='contributor'>Contributor</localization> -->\n    <!-- Lists and their items -->\n    <localization string-id='list'>Lijst</localization>\n    <localization string-id='li'>Lijstelement</localization>\n    <localization string-id='gi'>Begrip</localization>\n    <localization string-id='p'>Alinea</localization>\n    <localization string-id='blockquote'>Citaat</localization>\n    <localization string-id='pre'>Codeblok</localization>\n    <localization string-id='fragment'>Fragment</localization>\n    <!-- Parts of an exercise and its solution -->\n    <localization string-id='divisionalexercise'>Oefening</localization>\n    <localization string-id='inlineexercise'>Controlepunt</localization>\n    <localization string-id='worksheetexercise'>Werkblad-oefening</localization>\n    <localization string-id='readingquestion'>Leesvraag</localization>\n    <localization string-id='webwork'>WeBWorK</localization>\n    <localization string-id='hint'>Tip</localization>\n    <localization string-id='answer'>Antwoord</localization>\n    <localization string-id='solution'>Oplossing</localization>\n    <!-- <localization string-id='subexercises'>Subexercises</localization> -->\n    <!-- <localization string-id='exercisegroup'>Exercise Group</localization> -->\n    <!-- <localization string-id='biblio'>Bibliographic Entry</localization> -->\n    <!-- Front matter components -->\n    <localization string-id='toc'>Inhoudsopgave</localization>\n    <localization string-id='abstract'>Samenvatting</localization>\n    <localization string-id='preface'>Voorwoord</localization>\n    <localization string-id='acknowledgement'>Dankbetuigingen</localization>\n    <localization string-id='biography'>Schrijversbiografie</localization>\n    <localization string-id='about-author'>Over de schrijver</localization>\n    <localization string-id='about-authors'>Over de schrijvers</localization>\n    <localization string-id='foreword'>Voorwoord</localization>\n    <!-- <localization string-id='dedication'>Dedication</localization> -->\n    <localization string-id='colophon'>Colofon</localization>\n    <!-- Runestone Activities -->\n    <localization string-id='video'>Video</localization>\n    <localization string-id='program'>Program</localization>\n    <!-- Runestone Exercises -->\n    <!-- <localization string-id='true'>True</localization> -->\n    <!-- <localization string-id='false'>False</localization> -->\n    <!-- <localization string-id='or'>Or</localization> -->\n    <!-- <localization string-id='either'>Either</localization> -->\n    <!-- <localization string-id='uncategorized'>Uncategorized</localization> -->\n    <!-- <localization string-id='query'>Query</localization> -->\n    <localization string-id='program-activecode'>ActiveCode</localization>\n    <localization string-id='scratch-activecode'>Scratch ActiveCode</localization>\n    <localization string-id='program-codelens'>CodeLens</localization>\n    <!-- Back matter components -->\n    <localization string-id='index'>Index</localization>\n    <localization string-id='jump-to'>Jump to:</localization>\n    <!-- Parts of the Index -->\n    <localization string-id='see'>Zie</localization>\n    <localization string-id='also'>Zie ook</localization>\n    <!-- Notation List headings/foot -->\n    <localization string-id='symbol'>Symbool</localization>\n    <localization string-id='description'>Omschrijving</localization>\n    <localization string-id='location'>Locatie</localization>\n    <localization string-id='page'>Pagina</localization>\n    <localization string-id='continued'>Vervolg op de volgende pagina</localization>\n    <!-- Navigation Interface elements -->\n    <localization string-id='skip-to-content'>Naar de hoofdinhoud</localization>\n    <localization string-id='previous'>Vorig</localization>\n    <localization string-id='up'>Omhoog</localization>\n    <localization string-id='next'>Volgend</localization>\n    <localization string-id='previous-short'>Vorig</localization>\n    <localization string-id='up-short'>Omhoog</localization>\n    <localization string-id='next-short'>Volgend</localization>\n    <!-- <localization string-id='top'>Top</localization> -->\n    <localization string-id='annotations'>Annotations</localization>\n    <localization string-id='feedback'>Feedback</localization>\n    <localization string-id='authored'>Opgesteld met PreTeXt</localization>\n    <!-- Search Results display/dialog -->\n    <!-- <localization string-id='search-book'>Search Book</localization> -->\n    <localization string-id='search-results-heading'>Zoekresultaten</localization>\n    <localization string-id='no-search-results'>Geen resultaten</localization>\n    <!-- Parts of memos and letters -->\n    <localization string-id='to'>Aan</localization>\n    <localization string-id='from'>Van</localization>\n    <localization string-id='subject'>Onderwerp</localization>\n    <localization string-id='date'>Datum</localization>\n    <localization string-id='cc'>kopie</localization>\n    <localization string-id='enclosure'>bijgevoegd</localization>\n    <!-- Various -->\n    <localization string-id='todo'>Takenlijst</localization>\n    <localization string-id='editor'>Redacteur</localization> <!-- As in: person who edits -->\n    <localization string-id='edition'>Uitgaven</localization>\n    <localization string-id='website'>Website</localization>\n    <localization string-id='copyright'>Copyright</localization>\n    <!-- <localization string-id='keywords'>Keywords</localization> -->\n    <!-- HTML clickables (lowercase strings to click on) -->\n    <!-- <localization string-id='permalink'>permalink</localization> -->\n    <localization string-id='incontext'>In Context</localization>\n    <!-- <localization string-id='standalone'>Standalone</localization> -->\n    <!-- <localization string-id='embed'>Embed</localization> -->\n    <!-- <localization string-id='embed-this-page'>Embed this page</localization> -->\n    <!-- <localization string-id='copy'>Copy</localization> -->\n    <!-- <localization string-id='profile'>Profile</localization> -->\n    <!-- Following is in ENGLISH and should be translated.  Due to its -->\n    <!-- ubiquitous nature we have not left it undefined.  See the -->\n    <!-- \"en-US\" file for a more complete explanation of its use. -->\n    <!-- Please remove this entire comment when translated.  Thanks. -->\n    <localization string-id='permalink-tooltip'>Copy heading and permalink for</localization>\n    <!-- <localization string-id='calculator'>Calculator</localization> -->\n    <localization string-id='evaluate'>Evalueer</localization>\n    <!-- <localization string-id='code'>Code</localization> -->\n    <!-- <localization string-id='instructions'>Instructions</localization> -->\n    <localization string-id='correct'>Correct</localization>\n    <localization string-id='incorrect'>Niet correct</localization>\n    <localization string-id='blank'>Blanco</localization>\n    <localization string-id='submit'>Indienen</localization>\n    <localization string-id='check-responses'>Controleren</localization>\n    <localization string-id='reveal'>Onthullen</localization>\n    <localization string-id='randomize'>Randomiseren</localization>\n    <localization string-id='activate'>Activeren</localization>\n    <localization string-id='reset'>Resetten</localization>\n    <!-- <localization string-id='array'>array</localization> -->\n    <!-- <localization string-id=\"papersize\">Paper size</localization> -->\n    <!-- <localization string-id=\"printing-options\">Additional printing options</localization> -->\n    <!-- <localization string-id=\"hide-hints\">Hide hints</localization> -->\n    <!-- <localization string-id=\"hide-answers\">Hide answers</localization> -->\n    <!-- <localization string-id=\"hide-solutions\">Hide solutions</localization> -->\n    <!-- <localization string-id=\"print-header\">Print headers</localization> -->\n    <!-- <localization string-id=\"print-footer\">Print footers</localization> -->\n    <!-- <localization string-id=\"first-page\">First page</localization> -->\n    <!-- <localization string-id=\"running\">Running</localization> -->\n    <!-- <localization string-id=\"highlight-workspace\">Highlight workspace</localization> -->\n    <!-- <localization string-id='print'>Print</localization> -->\n    <!-- <localization string-id='print-preview'>Print preview</localization> -->\n    <!-- <localization string-id='close'>Close</localization> -->\n    <!-- <localization string-id='open-new-tab'>Open in new tab</localization> -->\n    <!-- Readability menu items, HTML only, utilized by Javascript -->\n    <!-- <localization string-id='readability-settings'>Readability settings</localization> -->\n    <!-- <localization string-id='readability-line-height'>Line height</localization> -->\n    <!-- <localization string-id='readability-content-font-size'>Content font size</localization> -->\n    <!-- <localization string-id='readability-theme'>Theme</localization> -->\n    <!-- <localization string-id='readability-theme-system'>System</localization> -->\n    <!-- <localization string-id='readability-theme-light'>Light</localization> -->\n    <!-- <localization string-id='readability-theme-dark'>Dark</localization> -->\n    <!-- <localization string-id='readability-assistive-technologies'>Assistive technologies</localization> -->\n    <!-- <localization string-id='readability-expose-permalinks'>Expose permalinks</localization> -->\n    <!-- <localization string-id='reset-all'>Reset All</localization> -->\n</locale>\n","localizations/pt-BR.xml":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n<!--********************************************************************\nCopyright (C) 2014-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- See  xsl/localizations/README.md  for an explanation of this file -->\n\n<!-- pt-BR, Portugese (Brazil)-->\n<!-- Igor Morgado, morgado.igor@gmail.com, 2014-08-11, 2014-08-14 -->\n<!-- Vinicius Monego, monego@posteo.net, 2020-11-07 -->\n<!-- Leon Silva, leon.silva@ufrpe.br, 2022-03-30 -->\n\n<locale language=\"pt-BR\" direction=\"ltr\"\n        quote-primary=\"english-double\" quote-secondary=\"english-single\">\n    <!-- THEOREM-LIKE blocks -->\n    <!-- The english quotation style above is just a default, it needs adjustment -->\n    <localization string-id='theorem'>Teorema</localization>\n    <localization string-id='corollary'>Corolário</localization>\n    <localization string-id='lemma'>Lema</localization>\n    <localization string-id='algorithm'>Algoritmo</localization>\n    <localization string-id='proposition'>Proposição</localization>\n    <localization string-id='claim'>Afirmação</localization>\n    <localization string-id='fact'>Fato</localization>\n    <localization string-id='identity'>Identidade</localization>\n    <!-- PROOF-LIKE -->\n    <localization string-id='proof'>Demonstração</localization>\n    <localization string-id='argument'>Argumento</localization>\n    <localization string-id='justification'>Justificativa</localization>\n    <localization string-id='reasoning'>Raciocínio</localization>\n    <localization string-id='explanation'>Explicação</localization>\n    <localization string-id='case'>Caso</localization>\n    <!-- Components of the narrative -->\n    <!-- Mathematical statements without proofs -->\n    <!-- AXIOM-LIKE blocks -->\n    <localization string-id='axiom'>Axioma</localization>\n    <localization string-id='conjecture'>Conjectura</localization>\n    <localization string-id='principle'>Princípio</localization>\n    <localization string-id='heuristic'>Heurística</localization>\n    <localization string-id='hypothesis'>Hipótese</localization>\n    <localization string-id='assumption'>Suposição</localization>\n    <!-- Definitions -->\n    <localization string-id='definition'>Definição</localization>\n    <!-- Mathematics -->\n    <localization string-id='equation'>Equação</localization>\n    <localization string-id='displaymath'>Matemática em Destaque</localization>\n    <!-- Types of documents, mostly for informational messages -->\n    <localization string-id='volume'>Volume</localization>\n    <localization string-id='book'>Livro</localization>\n    <localization string-id='article'>Artigo</localization>\n    <localization string-id='letter'>Carta</localization>\n    <!-- Translation needed for Brazilian Portugese -->\n    <localization string-id='slideshow'>Apresentação de Slides</localization>\n    <localization string-id='memo'>Memorando</localization>\n    <localization string-id='presentation'>Apresentação</localization>\n    <!-- Parts of a document -->\n    <localization string-id='frontmatter'>Pré-textual</localization>\n    <localization string-id='part'>Parte</localization>\n    <localization string-id='chapter'>Capítulo</localization>\n    <localization string-id='appendix'>Apêndice</localization>\n    <localization string-id='appendices'>Apêndices</localization>\n    <localization string-id='section'>Seção</localization>\n    <localization string-id='subsection'>Subseção</localization>\n    <localization string-id='subsubsection'>Subsubseção</localization>\n    <localization string-id='slide'>Transparência</localization>\n    <localization string-id='introduction'>Introdução</localization>\n    <localization string-id='conclusion'>Conclusão</localization>\n    <localization string-id='exercises'>Exercícios</localization>\n    <!-- Translation needed for Brazilian Portugese -->\n    <localization string-id='worksheet'>Lista de Exercícios</localization>\n    <!-- <localization string-id='handout'>Handout</localization> -->\n    <localization string-id='reading-questions'>Exercícios de Interpretação</localization>\n    <localization string-id='solutions'>Soluções</localization>\n    <localization string-id='glossary'>Glossário</localization>\n    <localization string-id='references'>Referêcias</localization>\n    <!-- Translation needed for Brazilian Portugese -->\n    <localization string-id='backmatter'>Pós-textual</localization>\n    <localization string-id='paragraphs'>Parágrafos</localization>\n    <localization string-id='subparagraph'>Subparágrafo</localization>\n    <!-- Adjustments to titles of divisions -->\n    <!-- <localization string-id='group'>Group</localization> -->\n    <!-- Components of the narrative -->\n    <!-- REMARK-LIKE blocks -->\n    <localization string-id='remark'>Nota</localization>\n    <localization string-id='convention'>Convenção</localization>\n    <localization string-id='note'>Nota</localization>\n    <localization string-id='observation'>Observação</localization>\n    <localization string-id='warning'>Atenção</localization>\n    <!-- Translation needed for Brazilian Portugese -->\n    <localization string-id='insight'>Ideia</localization>\n    <!-- COMPUTATION-LIKE blocks -->\n    <localization string-id='computation'>Cálculo</localization>\n    <localization string-id='technology'>Tecnologia</localization>\n    <localization string-id='data'>Dados</localization>\n    <!-- ASIDE-LIKE blocks -->\n    <localization string-id='aside'>Nota</localization>\n    <localization string-id='biographical'>Nota Biográfica Aside</localization>\n    <localization string-id='historical'>Nota Histórica</localization>\n    <!-- EXAMPLE-LIKE blocks -->\n    <localization string-id='example'>Exemplo</localization>\n    <localization string-id='question'>Questão</localization>\n    <localization string-id='problem'>Problema</localization>\n    <!-- PROJECT-LIKE blocks -->\n    <localization string-id='project'>Projeto</localization>\n    <localization string-id='activity'>Atividade</localization>\n    <localization string-id='exploration'>Exploração</localization>\n    <localization string-id='task'>Tarefa</localization>\n    <localization string-id='investigation'>Investigação</localization>\n    <!-- Translation needed for Brazilian Portugese -->\n    <localization string-id='assemblage'>Coleção</localization>\n    <localization string-id='poem'>Poema</localization>\n    <localization string-id='objectives'>Objetivos</localization>\n    <localization string-id='objective'>Objetivo</localization>\n    <localization string-id='outcomes'>Resultados</localization>\n    <localization string-id='outcome'>Resultado</localization>\n    <!-- <localization string-id='openquestion'>Open Question</localization> -->\n    <!-- <localization string-id='openproblem'>Open Problem</localization> -->\n    <!-- <localization string-id='openconjecture'>Open Conjecture</localization> -->\n    <!-- <localization string-id='context'>Context</localization> -->\n    <!-- <localization string-id='discussion'>Discussion</localization> -->\n    <!-- <localization string-id='opinion'>Opinion</localization> -->\n    <!-- <localization string-id='status'>Status</localization> -->\n    <!-- <localization string-id='suggestion'>Suggestion</localization> -->\n    <localization string-id='figure'>Figura</localization>\n    <localization string-id='table'>Tabela</localization>\n    <localization string-id='listing'>Listagem</localization>\n    <localization string-id='fn'>Nota de rodapé</localization>\n    <localization string-id='contributor'>Contribuidor</localization>\n    <!-- Lists and their items -->\n    <localization string-id='list'>Lista</localization>\n    <localization string-id='li'>Item</localization>\n    <localization string-id='gi'>Termo</localization>\n    <localization string-id='p'>Parágrafo</localization>\n    <localization string-id='blockquote'>Citação</localization>\n    <localization string-id='pre'>Bloco de Código</localization>\n    <localization string-id='fragment'>Fragmento</localization>\n    <!-- Parts of an exercise and its solution -->\n    <!-- See the en-US file for a detailed explanation of the words for exercises -->\n    <localization string-id='divisionalexercise'>Exercício</localization>\n    <!-- Translation needed for Brazilian Portugese -->\n    <!-- See en-US file for distinctions here, do not repeat previous translation -->\n    <localization string-id='inlineexercise'>Exercício de Verificação</localization>\n    <localization string-id='worksheetexercise'>Exercício da Lista</localization>\n    <localization string-id='readingquestion'>Exercício de Interpretação</localization>\n    <localization string-id='webwork'>WeBWorK</localization>\n    <localization string-id='hint'>Dica</localization>\n    <localization string-id='answer'>Resposta</localization>\n    <localization string-id='solution'>Solução</localization>\n    <!-- <localization string-id='subexercises'>Subexercises</localization> -->\n    <localization string-id='exercisegroup'>Grupo de exercícios</localization>\n    <localization string-id='biblio'>Referência bibliográfica</localization>\n    <!-- Front matter components -->\n    <localization string-id='toc'>Sumário</localization>\n    <localization string-id='abstract'>Resumo</localization>\n    <localization string-id='preface'>Prefácio</localization>\n    <localization string-id='acknowledgement'>Agradecimentos</localization>\n    <localization string-id='biography'>Biografia do autor</localization>\n    <localization string-id='about-author'>Sobre o autor</localization>\n    <localization string-id='about-authors'>Sobre os autores</localization>\n    <localization string-id='foreword'>Preâmbulo</localization>\n    <localization string-id='dedication'>Dedicatória</localization>\n    <localization string-id='colophon'>Ficha técnica</localization>\n    <!-- Runestone Activities -->\n    <localization string-id='video'>Vídeo</localization>\n    <localization string-id='program'>Programa</localization>\n    <!-- Runestone Exercises -->\n    <!-- <localization string-id='true'>True</localization> -->\n    <!-- <localization string-id='false'>False</localization> -->\n    <!-- <localization string-id='or'>Or</localization> -->\n    <!-- <localization string-id='either'>Either</localization> -->\n    <!-- <localization string-id='uncategorized'>Uncategorized</localization> -->\n    <!-- <localization string-id='query'>Query</localization> -->\n    <localization string-id='program-activecode'>ActiveCode</localization>\n    <!-- <localization string-id='scratch-activecode'>Scratch ActiveCode</localization> -->\n    <localization string-id='program-codelens'>CodeLens</localization>\n    <!-- Back matter components -->\n    <localization string-id='index'>Índice</localization>\n    <localization string-id='jump-to'>Ir para:</localization>\n    <!-- Parts of the Index -->\n    <localization string-id='see'>Veja</localization>\n    <localization string-id='also'>Veja também</localization>\n    <!-- Notation List headings/foot -->\n    <localization string-id='symbol'>Símbolo</localization>\n    <localization string-id='description'>Descrição</localization>\n    <localization string-id='location'>Posição</localization>\n    <localization string-id='page'>Página</localization>\n    <localization string-id='continued'>Continua na próxima página</localization>\n    <!-- Navigation Interface elements -->\n    <localization string-id='skip-to-content'>Ir ao conteúdo principal</localization>\n    <localization string-id='previous'>Anterior</localization>\n    <localization string-id='up'>Acima</localization>\n    <localization string-id='next'>Próximo</localization>\n    <!-- TODO: SHORTEN THESE -->\n    <localization string-id='previous-short'>Anterior</localization>\n    <localization string-id='up-short'>Acima</localization>\n    <localization string-id='next-short'>Próximo</localization>\n    <!-- <localization string-id='top'>Top</localization> -->\n    <localization string-id='annotations'>Anotações</localization>\n    <localization string-id='feedback'>Comentários</localization>\n    <localization string-id='authored'>Feito com PreTeXt</localization>\n    <!-- Search Results display/dialog -->\n    <!-- <localization string-id='search-book'>Search Book</localization> -->\n    <localization string-id='search-results-heading'>Buscando por</localization>\n    <localization string-id='no-search-results'>Não encontrado</localization>\n    <!-- Parts of memos and letters -->\n    <localization string-id='to'>Para</localization>\n    <localization string-id='from'>De</localization>\n    <localization string-id='subject'>Assunto</localization>\n    <localization string-id='date'>Data</localization>\n    <localization string-id='cc'>Cópia</localization>\n    <localization string-id='enclosure'>Anexo</localization>\n    <!-- Various -->\n    <localization string-id='todo'>Para fazer</localization>\n    <localization string-id='editor'>Editor</localization>\n    <localization string-id='edition'>Edição</localization>\n    <localization string-id='website'>Endereço eletrônico</localization>\n    <localization string-id='copyright'>XXXCopyright</localization>\n    <!-- <localization string-id='keywords'>Keywords</localization> -->\n    <!-- HTML clickables (lowercase strings to click on) -->\n    <localization string-id='permalink'>link permanente</localization>\n    <localization string-id='incontext'>Em Contexto</localization>\n    <!-- <localization string-id='standalone'>Standalone</localization> -->\n    <!-- <localization string-id='embed'>Embed</localization> -->\n    <!-- <localization string-id='embed-this-page'>Embed this page</localization> -->\n    <!-- <localization string-id='copy'>Copy</localization> -->\n    <!-- <localization string-id='profile'>Profile</localization> -->\n    <!-- Following is in ENGLISH and should be translated.  Due to its -->\n    <!-- ubiquitous nature we have not left it undefined.  See the -->\n    <!-- \"en-US\" file for a more complete explanation of its use. -->\n    <!-- Please remove this entire comment when translated.  Thanks. -->\n    <localization string-id='permalink-tooltip'>Copy heading and permalink for</localization>\n    <!-- <localization string-id='calculator'>Calculator</localization> -->\n    <!-- This needs to be defined to *something* (English) -->\n    <!-- Translate at first opportunity, please -->\n    <localization string-id='evaluate'>Executar</localization>\n    <!-- <localization string-id='code'>Code</localization> -->\n    <localization string-id='instructions'>Instruções</localization>\n    <localization string-id='correct'>Correto</localization>\n    <localization string-id='incorrect'>Incorreto</localization>\n    <localization string-id='blank'>Em brancoBlank</localization>\n    <localization string-id='submit'>Enviar</localization>\n    <localization string-id='check-responses'>Conferir Respostas</localization>\n    <localization string-id='reveal'>Revelar</localization>\n    <localization string-id='randomize'>Aleatoriza</localization>\n    <localization string-id='activate'>Ativar</localization>\n    <localization string-id='reset'>Redefinir</localization>\n    <localization string-id='array'>lista</localization>\n    <localization string-id=\"papersize\">Formato do papel</localization>\n    <localization string-id=\"printing-options\">Opções de impressão</localization>\n    <localization string-id=\"hide-hints\">Esconder dicas</localization>\n    <localization string-id=\"hide-answers\">Esconder respostas</localization>\n    <localization string-id=\"hide-solutions\">Esconder soluções</localization>\n    <localization string-id=\"print-header\">Imprimir cabeçalho</localization>\n    <localization string-id=\"print-footer\">Imprimir rodapé</localization>\n    <localization string-id=\"first-page\">Primeira página</localization>\n    <localization string-id=\"running\">Página atual</localization>\n    <localization string-id=\"highlight-workspace\">Destacar área para solução</localization>\n    <localization string-id='print'>Imprimir</localization>\n    <localization string-id='print-preview'>Pré-visualização da impressão</localization>\n    <localization string-id='close'>Fechar</localization>\n    <localization string-id='open-new-tab'>Abrir em nova aba</localization>\n    <!-- Readability menu items, HTML only, utilized by Javascript -->\n    <!-- <localization string-id='readability-settings'>Readability settings</localization> -->\n    <!-- <localization string-id='readability-line-height'>Line height</localization> -->\n    <!-- <localization string-id='readability-content-font-size'>Content font size</localization> -->\n    <!-- <localization string-id='readability-theme'>Theme</localization> -->\n    <!-- <localization string-id='readability-theme-system'>System</localization> -->\n    <!-- <localization string-id='readability-theme-light'>Light</localization> -->\n    <!-- <localization string-id='readability-theme-dark'>Dark</localization> -->\n    <!-- <localization string-id='readability-assistive-technologies'>Assistive technologies</localization> -->\n    <!-- <localization string-id='readability-expose-permalinks'>Expose permalinks</localization> -->\n    <!-- <localization string-id='reset-all'>Reset All</localization> -->\n</locale>\n","localizations/pt-PT.xml":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n<!--********************************************************************\nCopyright (C) 2015-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- See  xsl/localizations/README.md  for an explanation of this file -->\n\n<!-- pt-PT, Portugese (Portugal) -->\n<!-- António Pereira, apereiraua@gmail.com, 2015-07-26 -->\n\n<locale language=\"pt-PT\" direction=\"ltr\"\n        quote-primary=\"english-double\" quote-secondary=\"english-single\">\n    <!-- THEOREM-LIKE blocks -->\n    <!-- The english quotation style above is just a default, it needs adjustment -->\n    <localization string-id='theorem'>Teorema</localization>\n    <localization string-id='corollary'>Corolário</localization>\n    <localization string-id='lemma'>Lema</localization>\n    <localization string-id='algorithm'>Algoritmo</localization>\n    <localization string-id='proposition'>Proposição</localization>\n    <localization string-id='claim'>Afirmação</localization>\n    <localization string-id='fact'>Facto</localization>\n    <!-- <localization string-id='identity'>Identity</localization> -->\n    <!-- PROOF-LIKE -->\n    <localization string-id='proof'>Demonstração</localization>\n    <!-- <localization string-id='argument'>Argument</localization> -->\n    <!-- <localization string-id='justification'>Justification</localization> -->\n    <!-- <localization string-id='reasoning'>Reasoning</localization> -->\n    <!-- <localization string-id='explanation'>Explanation</localization> -->\n    <!-- <localization string-id='case'>Case</localization> -->\n    <!-- Components of the narrative -->\n    <!-- Mathematical statements without proofs -->\n    <!-- AXIOM-LIKE blocks -->\n    <localization string-id='axiom'>Axioma</localization>\n    <localization string-id='conjecture'>Conjectura</localization>\n    <localization string-id='principle'>Princípio</localization>\n    <!-- <localization string-id='heuristic'>Heuristic</localization> -->\n    <!-- <localization string-id='hypothesis'>Hypothesis</localization> -->\n    <!-- <localization string-id='assumption'>Assumption</localization> -->\n    <!-- Definitions -->\n    <localization string-id='definition'>Definição</localization>\n    <!-- Mathematics -->\n    <localization string-id='equation'>Equação</localization>\n    <!-- the translations for 'display mathematics' need revision! -->\n    <localization string-id='displaymath'>Equação</localization>\n    <!-- Types of documents, mostly for informational messages -->\n    <localization string-id='volume'>Volume</localization>\n    <localization string-id='book'>Livro</localization>\n    <localization string-id='article'>Artigo</localization>\n    <localization string-id='letter'>Carta</localization>\n    <!-- <localization string-id='slideshow'>Slideshow</localization> -->\n    <localization string-id='memo'>Memorando</localization>\n    <localization string-id='presentation'>Apresentação</localization>\n    <!-- Parts of a document -->\n    <!-- 'Front Matter' and 'Back matter' translations need more thinking... -->\n    <localization string-id='frontmatter'>Pré Texto</localization>\n    <localization string-id='part'>Parte</localization>\n    <localization string-id='chapter'>Capítulo</localization>\n    <localization string-id='appendix'>Apêndice</localization>\n    <!-- <localization string-id='appendices'>Appendices</localization> -->\n    <localization string-id='section'>Secção</localization>\n    <localization string-id='subsection'>Subsecção</localization>\n    <localization string-id='subsubsection'>Subsubsecção</localization>\n    <!-- <localization string-id='slide'>Slide</localization> -->\n    <localization string-id='introduction'>Introdução</localization>\n    <localization string-id='conclusion'>Conclusão</localization>\n    <localization string-id='exercises'>Exercícios</localization>\n    <!-- <localization string-id='worksheet'>Worksheet</localization> -->\n    <!-- <localization string-id='handout'>Handout</localization> -->\n    <!-- <localization string-id='reading-questions'>Reading Questions</localization> -->\n    <!-- <localization string-id='solutions'>Solutions</localization> -->\n    <!-- <localization string-id='glossary'>Glossary</localization> -->\n    <localization string-id='references'>Referências</localization>\n    <localization string-id='backmatter'>Pós Texto</localization>\n    <localization string-id='paragraphs'>Parágrafos</localization>\n    <localization string-id='subparagraph'>Subparágrafo</localization>\n    <!-- Adjustments to titles of divisions -->\n    <!-- <localization string-id='group'>Group</localization> -->\n    <!-- Components of the narrative -->\n    <!-- REMARK-LIKE blocks -->\n    <localization string-id='remark'>Observação</localization>\n    <!-- <localization string-id='convention'>Convention</localization> -->\n    <localization string-id='note'>Nota</localization>\n    <!-- <localization string-id='observation'>Observation</localization> -->\n    <!-- <localization string-id='warning'>Warning</localization> -->\n    <!-- <localization string-id='insight'>Insight</localization> -->\n    <!-- COMPUTATION-LIKE blocks -->\n    <!-- <localization string-id='computation'>Computation</localization> -->\n    <!-- <localization string-id='technology'>Technology</localization> -->\n    <!-- <localization string-id='data'>Data</localization> -->\n    <!-- ASIDE-LIKE blocks -->\n    <!-- <localization string-id='aside'>Aside</localization> -->\n    <!-- <localization string-id='biographical'>Biographical Aside</localization> -->\n    <!-- <localization string-id='historical'>Historical Aside</localization> -->\n    <!-- EXAMPLE-LIKE blocks -->\n    <localization string-id='example'>Exemplo</localization>\n    <!-- <localization string-id='question'>Question</localization> -->\n    <!-- <localization string-id='problem'>Problem</localization> -->\n    <!-- PROJECT-LIKE blocks -->\n    <!-- <localization string-id='project'>Project</localization> -->\n    <!-- <localization string-id='activity'>Activity</localization> -->\n    <!-- <localization string-id='exploration'>Exploration</localization> -->\n    <!-- <localization string-id='task'>Task</localization> -->\n    <!-- <localization string-id='investigation'>Investigation</localization> -->\n    <!-- <localization string-id='assemblage'>Assemblage</localization> -->\n    <!-- <localization string-id='poem'>Poem</localization> -->\n    <!-- <localization string-id='objectives'>Objectives</localization> -->\n    <!-- <localization string-id='objective'>Objective</localization> -->\n    <!-- <localization string-id='outcomes'>Outcomes</localization> -->\n    <!-- <localization string-id='outcome'>Outcome</localization> -->\n    <!-- <localization string-id='openquestion'>Open Question</localization> -->\n    <!-- <localization string-id='openproblem'>Open Problem</localization> -->\n    <!-- <localization string-id='openconjecture'>Open Conjecture</localization> -->\n    <!-- <localization string-id='context'>Context</localization> -->\n    <!-- <localization string-id='discussion'>Discussion</localization> -->\n    <!-- <localization string-id='opinion'>Opinion</localization> -->\n    <!-- <localization string-id='status'>Status</localization> -->\n    <!-- <localization string-id='suggestion'>Suggestion</localization> -->\n    <localization string-id='figure'>Figura</localization>\n    <localization string-id='table'>Tabela</localization>\n    <!-- Translation needed for Portugal Portugese -->\n    <!-- <localization string-id='listing'>Listing</localization> -->\n    <localization string-id='fn'>Nota de rodapé</localization>\n    <!-- Translation needed for Portugal Portugese -->\n    <!-- <localization string-id='contributor'>Contributor</localization> -->\n    <!-- Lists and their items -->\n    <!-- Translations needed for Portugal Portugese -->\n    <!-- <localization string-id='list'>List</localization> -->\n    <!-- <localization string-id='li'>Item</localization> -->\n    <!-- <localization string-id='gi'>Term</localization> -->\n    <localization string-id='p'>Parágrafo</localization>\n    <!-- <localization string-id='blockquote'>Quotation</localization> -->\n    <!-- <localization string-id='pre'>Code Block</localization> -->\n    <!-- <localization string-id='fragment'>Fragment</localization> -->\n    <!-- Parts of an exercise and its solution -->\n    <!-- See the en-US file for a detailed explanation of the words for exercises -->\n    <localization string-id='divisionalexercise'>Exercício</localization>\n    <!-- Translation needed for Portugal Portugese -->\n    <!-- See en-US file for distinctions here, do not repeat previous translation -->\n    <!-- <localization string-id='inlineexercise'>Checkpoint</localization> -->\n    <!-- <localization string-id='worksheetexercise'>Worksheet Exercise</localization> -->\n    <!-- <localization string-id='readingquestion'>Reading Question</localization> -->\n    <localization string-id='webwork'>WeBWorK</localization>\n    <localization string-id='hint'>Dica</localization>\n    <localization string-id='answer'>Resposta</localization>\n    <localization string-id='solution'>Solução</localization>\n    <!-- Translation needed for Portugal Portugese -->\n    <!-- <localization string-id='subexercises'>Subexercises</localization> -->\n    <!-- <localization string-id='exercisegroup'>Exercise Group</localization> -->\n    <!-- the term 'Bibliographic Item' could be just 'Referência'... -->\n    <localization string-id='biblio'>Referência Bibliográfica</localization>\n    <!-- Front matter components -->\n    <!-- Other possible names for 'toc' are: Conteúdo, Sumário, Índice -->\n    <localization string-id='toc'>Sumário</localization>\n    <localization string-id='abstract'>Resumo</localization>\n    <localization string-id='preface'>Prefácio</localization>\n    <localization string-id='acknowledgement'>Agradecimentos</localization>\n    <localization string-id='biography'>Biografia do Autor</localization>\n    <!-- <localization string-id='about-author'>About the Author</localization> -->\n    <!-- <localization string-id='about-authors'>About the Authors</localization> -->\n    <!-- Other possible names for 'foreword': Prefácio -->\n    <localization string-id='foreword'>Prefácio</localization>\n    <localization string-id='dedication'>Dedicatória</localization>\n    <localization string-id='colophon'>Ficha técnica</localization>\n    <!-- Runestone Activities -->\n    <!-- <localization string-id='video'>Video</localization> -->\n    <!-- <localization string-id='program'>Program</localization> -->\n    <!-- Runestone Exercises -->\n    <!-- <localization string-id='true'>True</localization> -->\n    <!-- <localization string-id='false'>False</localization> -->\n    <!-- <localization string-id='or'>Or</localization> -->\n    <!-- <localization string-id='either'>Either</localization> -->\n    <!-- <localization string-id='uncategorized'>Uncategorized</localization> -->\n    <!-- <localization string-id='query'>Query</localization> -->\n    <localization string-id='program-activecode'>ActiveCode</localization>\n    <!-- <localization string-id='scratch-activecode'>Scratch ActiveCode</localization> -->\n    <localization string-id='program-codelens'>CodeLens</localization>\n    <!-- Back matter components -->\n    <localization string-id='index'>Índice Remissivo</localization>\n    <!-- <localization string-id='jump-to'>Jump to:</localization> -->\n    <!-- Parts of the Index -->\n    <localization string-id='see'>Veja</localization>\n    <localization string-id='also'>Veja também</localization>\n    <!-- Notation List headings/foot -->\n    <localization string-id='symbol'>Símbolo</localization>\n    <localization string-id='description'>Descrição</localization>\n    <!-- Translation needed for Portugal Portugese -->\n    <!-- <localization string-id='location'>Location</localization> -->\n    <localization string-id='page'>Página</localization>\n    <localization string-id='continued'>Continua na página seguinte</localization>\n    <!-- Navigation Interface elements -->\n    <!-- <localization string-id='skip-to-content'>Skip to main content</localization> -->\n    <localization string-id='previous'>Anterior</localization>\n    <localization string-id='up'>Acima</localization>\n    <localization string-id='next'>Seguinte</localization>\n    <!-- TODO: SHORTEN THESE -->\n    <localization string-id='previous-short'>Anterior</localization>\n    <localization string-id='up-short'>Acima</localization>\n    <localization string-id='next-short'>Seguinte</localization>\n    <!-- <localization string-id='top'>Top</localization> -->\n    <localization string-id='annotations'>Anotações</localization>\n    <localization string-id='feedback'>Comentário</localization>\n    <localization string-id='authored'>Produzido com PreTeXt</localization>\n    <!-- Search Results display/dialog -->\n    <!-- <localization string-id='search-book'>Search Book</localization> -->\n    <!-- <localization string-id='search-results-heading'>Search Results</localization> -->\n    <!-- <localization string-id='no-search-results'>No results</localization> -->\n    <!-- Parts of memos and letters -->\n    <localization string-id='to'>Para</localization>\n    <localization string-id='from'>De</localization>\n    <localization string-id='subject'>Assunto</localization>\n    <localization string-id='date'>Data</localization>\n    <localization string-id='cc'>Cópia</localization>\n    <localization string-id='enclosure'>Anexo</localization>\n    <!-- Various -->\n    <localization string-id='todo'>Para fazer</localization>\n    <localization string-id='editor'>Editor</localization>\n    <!-- <localization string-id='edition'>Edition</localization> -->\n    <!-- <localization string-id='website'>Website</localization> -->\n    <localization string-id='copyright'>Copyright</localization>\n    <!-- <localization string-id='keywords'>Keywords</localization> -->\n    <!-- HTML clickables (lowercase strings to click on) -->\n    <!-- Translation needed for Portugal Portugese -->\n    <!-- <localization string-id='permalink'>permalink</localization> -->\n    <!-- <localization string-id='incontext'>In Context</localization> -->\n    <!-- <localization string-id='standalone'>Standalone</localization> -->\n    <!-- <localization string-id='embed'>Embed</localization> -->\n    <!-- <localization string-id='embed-this-page'>Embed this page</localization> -->\n    <!-- <localization string-id='copy'>Copy</localization> -->\n    <!-- <localization string-id='profile'>Profile</localization> -->\n    <!-- Following is in ENGLISH and should be translated.  Due to its -->\n    <!-- ubiquitous nature we have not left it undefined.  See the -->\n    <!-- \"en-US\" file for a more complete explanation of its use. -->\n    <!-- Please remove this entire comment when translated.  Thanks. -->\n    <localization string-id='permalink-tooltip'>Copy heading and permalink for</localization>\n    <!-- <localization string-id='calculator'>Calculator</localization> -->\n    <!-- This needs to be defined to *something* (English) -->\n    <!-- Translate at first opportunity, please -->\n    <localization string-id='evaluate'>Evaluate</localization>\n    <!-- <localization string-id='code'>Code</localization> -->\n    <!-- <localization string-id='instructions'>Instructions</localization> -->\n    <!-- <localization string-id='correct'>Correct</localization> -->\n    <!-- <localization string-id='incorrect'>Incorrect</localization> -->\n    <!-- <localization string-id='blank'>Blank</localization> -->\n    <!-- <localization string-id='submit'>Submit</localization> -->\n    <!-- <localization string-id='check-responses'>Check Responses</localization> -->\n    <!-- <localization string-id='reveal'>Reveal</localization> -->\n    <!-- <localization string-id='randomize'>Randomize</localization> -->\n    <!-- <localization string-id='activate'>Activate</localization> -->\n    <!-- <localization string-id='reset'>Reset</localization> -->\n    <!-- <localization string-id='array'>array</localization> -->\n    <localization string-id=\"papersize\">Formato do papel</localization>\n    <localization string-id=\"printing-options\">Opções de impressão</localization>\n    <localization string-id=\"hide-hints\">Esconder dicas</localization>\n    <localization string-id=\"hide-answers\">Esconder respostas</localization>\n    <localization string-id=\"hide-solutions\">Esconder soluções</localization>\n    <localization string-id=\"print-header\">Imprimir cabeçalho</localization>\n    <localization string-id=\"print-footer\">Imprimir rodapé</localization>\n    <localization string-id=\"first-page\">Primeira página</localization>\n    <localization string-id=\"running\">Página atual</localization>\n    <localization string-id=\"highlight-workspace\">Destacar área para solução</localization>\n    <localization string-id='print'>Imprimir</localization>\n    <localization string-id='print-preview'>Pré-visualização da impressão</localization>\n    <localization string-id='close'>Fechar</localization>\n    <localization string-id='open-new-tab'>Abrir em nova aba</localization>\n    <!-- Readability menu items, HTML only, utilized by Javascript -->\n    <!-- <localization string-id='readability-settings'>Readability settings</localization> -->\n    <!-- <localization string-id='readability-line-height'>Line height</localization> -->\n    <!-- <localization string-id='readability-content-font-size'>Content font size</localization> -->\n    <!-- <localization string-id='readability-theme'>Theme</localization> -->\n    <!-- <localization string-id='readability-theme-system'>System</localization> -->\n    <!-- <localization string-id='readability-theme-light'>Light</localization> -->\n    <!-- <localization string-id='readability-theme-dark'>Dark</localization> -->\n    <!-- <localization string-id='readability-assistive-technologies'>Assistive technologies</localization> -->\n    <!-- <localization string-id='readability-expose-permalinks'>Expose permalinks</localization> -->\n    <!-- <localization string-id='reset-all'>Reset All</localization> -->\n</locale>\n","localizations/zh-HANS.xml":"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n<!--********************************************************************\nCopyright (C) 2014-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- See  xsl/localizations/README.md  for an explanation of this file -->\n\n<!-- zh-HANS, Chinese Simplified (China) -->\n<!-- Hongqi Wang, whq_nuaa@qq.com, 2024-01-03   -->\n\n<locale language=\"zh-HANS\" direction=\"ltr\">\n    <!-- THEOREM-LIKE blocks -->\n    <localization string-id='theorem'>定理</localization>\n    <localization string-id='corollary'>推论</localization>\n    <localization string-id='lemma'>引理</localization>\n    <localization string-id='algorithm'>算法</localization>\n    <localization string-id='proposition'>命题</localization>\n    <localization string-id='claim'>断言</localization>\n    <localization string-id='fact'>事实</localization>\n    <localization string-id='identity'>恒等</localization>\n    <!-- PROOF-LIKE -->\n    <localization string-id='proof'>证明</localization>\n    <localization string-id='argument'>论证</localization>\n    <localization string-id='justification'>论证</localization>\n    <localization string-id='reasoning'>推理</localization>\n    <localization string-id='explanation'>解释</localization>\n    <localization string-id='case'>情形</localization>\n    <!-- Components of the narrative -->\n    <!-- Mathematical statements without proofs -->\n    <!-- AXIOM-LIKE blocks -->\n    <localization string-id='axiom'>公理</localization>\n    <localization string-id='conjecture'>猜想</localization>\n    <localization string-id='principle'>原理</localization>\n    <localization string-id='heuristic'>启发</localization>\n    <localization string-id='hypothesis'>假设</localization>\n    <localization string-id='assumption'>假设</localization>\n    <!-- Definitions -->\n    <localization string-id='definition'>定义</localization>\n    <!-- Mathematics -->\n    <!-- <localization string-id='equation'>Equation</localization> -->\n    <!-- <localization string-id='displaymath'>Display Mathematics</localization> -->\n    <!-- Types of documents, mostly for informational messages -->\n    <localization string-id='volume'>卷册</localization>\n    <localization string-id='book'>书籍</localization>\n    <localization string-id='article'>论文</localization>\n    <localization string-id='letter'>书札</localization>\n    <localization string-id='slideshow'>幻灯片</localization>\n    <localization string-id='memo'>备忘录</localization>\n    <localization string-id='presentation'>演示文稿</localization>\n    <!-- Parts of a document -->\n    <localization string-id='frontmatter'>前置页</localization>\n    <localization string-id='part'>部分</localization>\n    <localization string-id='chapter'>章</localization>\n    <localization string-id='appendix'>附录</localization>\n    <localization string-id='appendices'>附录</localization>\n    <localization string-id='section'>节</localization>\n    <localization string-id='subsection'>子节</localization>\n    <localization string-id='subsubsection'>子子节</localization>\n    <localization string-id='slide'>幻灯片</localization>\n    <localization string-id='introduction'>绪言</localization>\n    <localization string-id='conclusion'>结论</localization>\n    <localization string-id='exercises'>练习</localization>\n    <localization string-id='worksheet'>工作单</localization>\n    <!-- <localization string-id='handout'>Handout</localization> -->\n    <localization string-id='reading-questions'>问题</localization>\n    <localization string-id='solutions'>解答</localization>\n    <localization string-id='glossary'>术语</localization>\n    <localization string-id='references'>参考文献</localization>\n    <localization string-id='backmatter'>后置页</localization>\n    <localization string-id='paragraphs'>段落</localization>\n    <localization string-id='subparagraph'>子段落</localization>\n    <!-- Adjustments to titles of divisions -->\n    <!-- <localization string-id='group'>Group</localization> -->\n    <!-- Components of the narrative -->\n    <!-- REMARK-LIKE blocks -->\n    <localization string-id='remark'>备注</localization>\n    <localization string-id='convention'>约定</localization>\n    <localization string-id='note'>备注</localization>\n    <localization string-id='observation'>观察</localization>\n    <localization string-id='warning'>警告</localization>\n    <localization string-id='insight'>洞察</localization>\n    <!-- COMPUTATION-LIKE blocks -->\n    <localization string-id='computation'>计算</localization>\n    <localization string-id='technology'>技术</localization>\n    <localization string-id='data'>数据</localization>\n    <!-- ASIDE-LIKE blocks -->\n    <localization string-id='aside'>旁注</localization>\n    <localization string-id='biographical'>传记旁注</localization>\n    <localization string-id='historical'>历史旁注</localization>\n    <!-- EXAMPLE-LIKE blocks -->\n    <localization string-id='example'>例</localization>\n    <localization string-id='question'>问题</localization>\n    <localization string-id='problem'>问题</localization>\n    <!-- PROJECT-LIKE blocks -->\n    <localization string-id='project'>工程</localization>\n    <localization string-id='activity'>活动</localization>\n    <localization string-id='exploration'>探究</localization>\n    <localization string-id='task'>任务</localization>\n    <localization string-id='investigation'>调查</localization>\n    <localization string-id='assemblage'>集</localization>\n    <localization string-id='poem'>诗</localization>\n    <localization string-id='objectives'>目标清单</localization>\n    <localization string-id='objective'>目标</localization>\n    <localization string-id='outcomes'>成果清单</localization>\n    <localization string-id='outcome'>成果</localization>\n    <localization string-id='openquestion'>开放问题</localization>\n    <localization string-id='openproblem'>开放问题</localization>\n    <localization string-id='openconjecture'>开放猜想</localization>\n    <localization string-id='context'>上下文</localization>\n    <localization string-id='discussion'>讨论</localization>\n    <localization string-id='opinion'>见解</localization>\n    <localization string-id='status'>状态</localization>\n    <localization string-id='suggestion'>建议</localization>\n    <localization string-id='figure'>图</localization>\n    <localization string-id='table'>表</localization>\n    <localization string-id='listing'>清单</localization>\n    <localization string-id='fn'>脚注</localization>\n    <localization string-id='contributor'>贡献者</localization>\n    <!-- Lists and their items -->\n    <localization string-id='list'>列表</localization>\n    <localization string-id='li'>项</localization>\n    <localization string-id='gi'>术语</localization>\n    <localization string-id='p'>段落</localization>\n    <localization string-id='blockquote'>引用</localization>\n    <localization string-id='pre'>代码块</localization>\n    <localization string-id='fragment'>代码片段</localization>\n    <!-- Parts of an exercise and its solution -->\n    <localization string-id='divisionalexercise'>练习</localization>\n    <localization string-id='inlineexercise'>检查点</localization>\n    <localization string-id='worksheetexercise'>工作单练习</localization>\n    <localization string-id='readingquestion'>问题</localization>\n    <localization string-id='webwork'>WeBWorK</localization>\n    <localization string-id='hint'>提示</localization>\n    <localization string-id='answer'>答案</localization>\n    <localization string-id='solution'>解答</localization>\n    <localization string-id='subexercises'>子练习</localization>\n    <localization string-id='exercisegroup'>练习组</localization>\n    <localization string-id='biblio'>书目项</localization>\n    <!-- Front matter components -->\n    <localization string-id='toc'>目录</localization>\n    <localization string-id='abstract'>摘要</localization>\n    <localization string-id='preface'>前言</localization>\n    <localization string-id='acknowledgement'>致谢</localization>\n    <localization string-id='biography'>作者简介</localization>\n    <localization string-id='about-author'>关于作者</localization>\n    <localization string-id='about-authors'>关于作者</localization>\n    <localization string-id='foreword'>前言</localization>\n    <localization string-id='dedication'>致谢</localization>\n    <localization string-id='colophon'>版权</localization>\n    <!-- Runestone Activities -->\n    <localization string-id='video'>Video</localization>\n    <localization string-id='program'>Program</localization>\n    <!-- Runestone Exercises -->\n    <!-- <localization string-id='true'>True</localization> -->\n    <!-- <localization string-id='false'>False</localization> -->\n    <!-- <localization string-id='or'>Or</localization> -->\n    <!-- <localization string-id='either'>Either</localization> -->\n    <!-- <localization string-id='uncategorized'>Uncategorized</localization> -->\n    <!-- <localization string-id='query'>Query</localization> -->\n    <localization string-id='program-activecode'>ActiveCode</localization>\n    <!-- <localization string-id='scratch-activecode'>Scratch ActiveCode</localization> -->\n    <localization string-id='program-codelens'>CodeLens</localization>\n    <!-- Back matter components -->\n    <localization string-id='index'>索引</localization>\n    <localization string-id='jump-to'>跳转:</localization>\n    <!-- Parts of the Index -->\n    <localization string-id='see'>见</localization>\n    <localization string-id='also'>另见</localization>\n    <!-- Notation List headings/foot -->\n    <localization string-id='symbol'>符号</localization>\n    <localization string-id='description'>描述</localization>\n    <localization string-id='location'>位置</localization>\n    <localization string-id='page'>页</localization>\n    <localization string-id='continued'>续</localization>\n    <!-- Navigation Interface elements -->\n    <localization string-id='skip-to-content'>主要内容</localization>\n    <localization string-id='previous'>向前</localization>\n    <localization string-id='up'>向上</localization>\n    <localization string-id='next'>向后</localization>\n    <localization string-id='previous-short'>向前</localization>\n    <localization string-id='up-short'>向上</localization>\n    <localization string-id='next-short'>向后</localization>\n    <!-- <localization string-id='top'>Top</localization> -->\n    <localization string-id='annotations'>注释</localization>\n    <localization string-id='feedback'>反馈</localization>\n    <localization string-id='authored'>PreTeXt写就</localization>\n    <!-- Search Results display/dialog -->\n    <!-- <localization string-id='search-book'>Search Book</localization> -->\n    <localization string-id='search-results-heading'>搜索结果</localization>\n    <localization string-id='no-search-results'>没有结果</localization>\n    <!-- Parts of memos and letters -->\n    <localization string-id='to'>致</localization>\n    <localization string-id='from'>来自</localization>\n    <localization string-id='subject'>主题</localization>\n    <localization string-id='date'>日期</localization>\n    <localization string-id='cc'>抄送</localization>\n    <localization string-id='enclosure'>附件</localization>\n    <!-- Various -->\n    <localization string-id='todo'>待办</localization>\n    <localization string-id='editor'>编辑器</localization>\n    <localization string-id='edition'>版本</localization>\n    <localization string-id='website'>网站</localization>\n    <localization string-id='copyright'>版权</localization>\n    <!-- <localization string-id='keywords'>Keywords</localization> -->\n    <!-- HTML clickables (lowercase strings to click on) -->\n    <localization string-id='permalink'>永久链接</localization>\n    <localization string-id='incontext'>文中</localization>\n    <!-- <localization string-id='standalone'>Standalone</localization> -->\n    <!-- <localization string-id='embed'>Embed</localization> -->\n    <!-- <localization string-id='embed-this-page'>Embed this page</localization> -->\n    <!-- <localization string-id='copy'>Copy</localization> -->\n    <!-- <localization string-id='profile'>Profile</localization> -->\n    <!-- <localization string-id='permalink-tooltip'>Copy heading and permalink for</localization> -->\n    <!-- <localization string-id='calculator'>Calculator</localization> -->\n    <localization string-id='evaluate'>求解</localization>\n    <!-- <localization string-id='code'>Code</localization> -->\n    <localization string-id='instructions'>说明</localization>\n    <localization string-id='correct'>正确</localization>\n    <localization string-id='incorrect'>错误</localization>\n    <localization string-id='blank'>空白</localization>\n    <localization string-id='submit'>提交</localization>\n    <localization string-id='check-responses'>校验</localization>\n    <localization string-id='reveal'>显示</localization>\n    <localization string-id='randomize'>随机</localization>\n    <localization string-id='activate'>激活</localization>\n    <localization string-id='reset'>重置</localization>\n    <localization string-id='array'>数组</localization>\n    <!-- <localization string-id=\"papersize\">Paper size</localization> -->\n    <!-- <localization string-id=\"printing-options\">Additional printing options</localization> -->\n    <!-- <localization string-id=\"hide-hints\">Hide hints</localization> -->\n    <!-- <localization string-id=\"hide-answers\">Hide answers</localization> -->\n    <!-- <localization string-id=\"hide-solutions\">Hide solutions</localization> -->\n    <!-- <localization string-id=\"print-header\">Print headers</localization> -->\n    <!-- <localization string-id=\"print-footer\">Print footers</localization> -->\n    <!-- <localization string-id=\"first-page\">First page</localization> -->\n    <!-- <localization string-id=\"running\">Running</localization> -->\n    <!-- <localization string-id=\"highlight-workspace\">Highlight workspace</localization> -->\n    <localization string-id='print'>打印</localization>\n    <!-- <localization string-id='print-preview'>Print preview</localization> -->\n    <!-- <localization string-id='close'>Close</localization> -->\n    <!-- <localization string-id='open-new-tab'>Open in new tab</localization> -->\n    <!-- Readability menu items, HTML only, utilized by Javascript -->\n    <!-- <localization string-id='readability-settings'>Readability settings</localization> -->\n    <!-- <localization string-id='readability-line-height'>Line height</localization> -->\n    <!-- <localization string-id='readability-content-font-size'>Content font size</localization> -->\n    <!-- <localization string-id='readability-theme'>Theme</localization> -->\n    <!-- <localization string-id='readability-theme-system'>System</localization> -->\n    <!-- <localization string-id='readability-theme-light'>Light</localization> -->\n    <!-- <localization string-id='readability-theme-dark'>Dark</localization> -->\n    <!-- <localization string-id='readability-assistive-technologies'>Assistive technologies</localization> -->\n    <!-- <localization string-id='readability-expose-permalinks'>Expose permalinks</localization> -->\n    <!-- <localization string-id='reset-all'>Reset All</localization> -->\n</locale>\n","pretext-assembly.xsl":"<?xml version='1.0'?>\n\n<!--********************************************************************\nCopyright (C) 2020-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!DOCTYPE xsl:stylesheet [\n    <!ENTITY % entities SYSTEM \"entities.ent\">\n    %entities;\n]>\n\n<xsl:stylesheet\n    xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\"\n    xmlns:xml=\"http://www.w3.org/XML/1998/namespace\"\n    xmlns:xhtml=\"http://www.w3.org/1999/xhtml\"\n    xmlns:pi=\"http://pretextbook.org/2020/pretext/internal\"\n    xmlns:pf=\"https://prefigure.org\"\n    xmlns:exsl=\"http://exslt.org/common\"\n    xmlns:date=\"http://exslt.org/dates-and-times\"\n    xmlns:str=\"http://exslt.org/strings\"\n    extension-element-prefixes=\"exsl date str\"\n    exclude-result-prefixes=\"pi\"\n>\n\n<!-- This is the once-mythical pre-processor, though we prefer     -->\n<!-- to describe it as the \"assembly\" of \"enhanced\" source.  By    -->\n<!-- \"assembly\" we mean pre-processing of source, by \"assembling\"  -->\n<!-- various pieces of material or content, authored or computed,  -->\n<!-- into an enhanced source tree. This template operates by       -->\n<!-- successive passes through the entire source tree making       -->\n<!-- adjustments into a new \"enhanced\" or modified source tree     -->\n<!-- with each pass.                                               -->\n<!--                                                               -->\n<!-- * $original will point to source file/tree/XML at the overall -->\n<!--   \"pretext\" element.                                          -->\n<!-- * The \"version\" templates are applied to decide if certain    -->\n<!--   elements are excluded from the source tree.  This creates   -->\n<!--   the new $version source tree by *removing* source.  It also -->\n<!--   resolves \"custom\" elements.  If these two features have     -->\n<!--   been used properly by an author, then the result should be  -->\n<!--   valid PreTeXt (when perhaps the authored source was not).   -->\n<!-- * The modal \"assembly\" templates are applied to the source    -->\n<!--   root element, creating a new version of the source, which   -->\n<!--   has been \"enhanced\".  This pass assembles computed          -->\n<!--   content (most visibly the bibliography), creating the       -->\n<!--   $assembly source tree by *adding* new source elements.      -->\n<!-- * The \"repair\" templates will automatically repair deprecated -->\n<!--   constructions so that actual conversions can remove         -->\n<!--   orphaned code.  Despite the name, we also implement         -->\n<!--   conveniences that are universal across all conversions, so  -->\n<!--   that conversions can assume a more canonical version of the -->\n<!--   source, or remove the need for additional templates to      -->\n<!--   realize certain constructions.  This creates the            -->\n<!--   $repair source tree by *changing* source.                   -->\n<!-- * $root will point to the root of the final enhanced          -->\n<!--   source file/tree/XML.                                       -->\n<!-- * Derived variables, $docinfo and $document-root, will        -->\n<!--   be created here for use in subsequent stylesheets.          -->\n<!--                                                               -->\n<!-- Notes:                                                        -->\n<!--                                                               -->\n<!-- 1.  $original is needed for context switches back into the    -->\n<!--     original authored source, such as for determining the     -->\n<!--     location of the source in the file system.                -->\n<!-- 2.  Any coordination of automatically assigned identifiers    -->\n<!--     requires identical source, so even a simple extraction    -->\n<!--     stylesheet might require preparing identical source       -->\n<!--     via this method.                                          -->\n<!-- 3.  Overrides, customization of the assembly will typically   -->\n<!--     happen here, but can be converter-specific in some ways.  -->\n<!--                                                               -->\n<!-- The \"publisher-variables.xsl\" and \"pretext-assembly.xsl\"      -->\n<!-- stylesheets are symbiotic, and should be imported             -->\n<!-- simultaneously.  Assembly will change the source in various   -->\n<!-- ways, while some defaults for publisher variables will depend -->\n<!-- on source.  The default variables should depend on gross      -->\n<!-- structure and adjustments should be to smaller portions of    -->\n<!-- the source, but we don't take any chances.  So, note in       -->\n<!-- \"assembly\" that an intermediate tree is defined as a          -->\n<!-- variable, which is then used in defining some variables,      -->\n<!-- based on assembled source.  Conversely, certain variables,    -->\n<!-- such as locations of customizations or private solutions,     -->\n<!-- are needed early in assembly, while other variables, such     -->\n<!-- as options for numbering, are needed for later enhancements   -->\n<!-- to the source.  If new code results in undefined, or          -->\n<!-- recursively defined, variables, this discussion may be        -->\n<!-- relevant.  (This is repeated verbatim in the other            -->\n<!-- stylesheet).                                                  -->\n<!--  -->\n<!-- Note too, that we want this stylesheet to be independent, and -->\n<!-- that can be tested with the  pretext-enhanced-source.xsl      -->\n<!-- stylesheet.  There is one danger: any (modal) template        -->\n<!-- applied here, needs to be defined here.  \"Normal\" conversions -->\n<!-- will import things like \"pretext-common.xsl\" and templates    -->\n<!-- defined there will be available.  But when not defined here,  -->\n<!-- the default is to just apply default templates to the         -->\n<!-- content, which may generally just produce a lot of text.      -->\n<!-- Which is no good, say as an attribute value.                  -->\n\n<!-- This stylesheet runs as a chain of full-tree passes.  Each      -->\n<!-- pass is a modal traversal that copies the previous tree and     -->\n<!-- alters only the elements it cares about, yielding a new         -->\n<!-- tree.  The new tree is built as a result tree fragment and      -->\n<!-- immediately turned into a real node-set with                    -->\n<!-- exsl:node-set(), so the next pass can walk it.  The chain is    -->\n<!-- wired in \"The Assembly Pipeline\" section as a sequence of       -->\n<!-- variables ($version, $assembly, ...); that sequence, not the    -->\n<!-- order of templates in this file, is the authoritative pass      -->\n<!-- order.                                                          -->\n<!--                                                                 -->\n<!-- Most passes are the identity for almost every node.  The        -->\n<!-- low-priority identity templates that make each pass a           -->\n<!-- faithful copy by default are collected in \"Source Assembly      -->\n<!-- Infrastructure\"; the section for a pass then overrides them     -->\n<!-- (one section per pass, below, in execution order) for just      -->\n<!-- the handful of elements that pass transforms.                   -->\n<!--                                                                 -->\n<!-- The passes, in the order they run (the identifier in            -->\n<!-- parentheses is the node-set each one produces):                 -->\n<!--                                                                 -->\n<!--    1. private-solutions   ($private-solutions)                  -->\n<!--         Splice in an external file of instructor solutions.     -->\n<!--         Identity, and skipped, when no such file is named.      -->\n<!--    2. version             ($version)                            -->\n<!--         Resolve \"version\" and \"custom\" elements, *removing*     -->\n<!--         excluded content.  Result should be valid PreTeXt.      -->\n<!--    3. id-attribute        ($original-labeled)  @pi:original-id  -->\n<!--         First of three identification stamps (see below).       -->\n<!--    4. assembly            ($assembly)                           -->\n<!--         *Add* computed content: the assembled bibliography,     -->\n<!--         copied WeBWorK problems, matching/card-sort pieces.     -->\n<!--    5. exercise            ($exercise)                           -->\n<!--         Tag each exercise with its kind (inline, divisional,    -->\n<!--         worksheet, ...) for later decisions.                    -->\n<!--    6. id-attribute        ($assembly-label)    @pi:assembly-id  -->\n<!--         Second stamp: the early id passes coordinate on.        -->\n<!--    7. dynamic-substitution ($dynamic)                           -->\n<!--         Splice computed answers into fill-in-the-blank and      -->\n<!--         kindred dynamic exercises.  Skipped when none exist.    -->\n<!--    8. representations     ($representations)                    -->\n<!--         Render interactive exercises as static or dynamic       -->\n<!--         equivalents, per $exercise-style.                       -->\n<!--    9. repair              ($repair)                             -->\n<!--         *Change* source: fix deprecated constructions and       -->\n<!--         apply conveniences, for a canonical tree.               -->\n<!--   10. enrichment          ($enrichment)                         -->\n<!--         *Add* generated material, e.g. a GeoGebra preview       -->\n<!--         or visual text for a bare url.                          -->\n<!--   11. labels              ($labels)                             -->\n<!--         Promote an authored @xml:id to @label and record        -->\n<!--         localization support.  See \"Labels\".                    -->\n<!--   12. id-attribute        ($identification)    @pi:unique-id    -->\n<!--         Third stamp: the final id conversions consume.          -->\n<!--   13. augment             ($augment)                            -->\n<!--         Annotate divisions with @pi:level (and ordered lists    -->\n<!--         with @pi:ordered-list-level), as numbering needs.       -->\n<!--   14. serial-stamp        ($serial-stamp)                       -->\n<!--         Stamp @pi:serial on every numbered item.  See           -->\n<!--         \"Numbering\".                                            -->\n<!--                                                                 -->\n<!-- After the chain, $root, $docinfo, $document-root and            -->\n<!-- $bibinfo are derived from the final tree for the conversion     -->\n<!-- stylesheets that import this one.                               -->\n<!--                                                                 -->\n<!-- Three identifiers, one mechanism.  The id-attribute pass        -->\n<!-- runs three times (passes 3, 6, 12), each stamping one           -->\n<!-- attribute by a deterministic depth-first walk: @pi:original-id  -->\n<!-- (authored structure), @pi:assembly-id (early, so passes can     -->\n<!-- coordinate before filenames exist) and @pi:unique-id (the final -->\n<!-- identifier).  The three agree element-for-element only          -->\n<!-- because no intervening pass reorders siblings; that             -->\n<!-- invariant is stated in full at \"Structural Contract for         -->\n<!-- Identification Passes\" and checked, when assembly.debug is      -->\n<!-- set, by the id-coherence-check.                                 -->\n<!--                                                                 -->\n<!-- Two-pass extraction and substitution.  A few constructs         -->\n<!-- (fill-in-the-blank answers, WeBWorK, MOM, ...) need an          -->\n<!-- external round trip: this stylesheet first emits a tree that    -->\n<!-- drives the trip, then on a later run reads the results back.    -->\n<!-- The $b-extracting-* switches that select that mode are          -->\n<!-- described at \"Controlling Two-Pass Extraction and               -->\n<!-- Substitution\".                                                  -->\n\n<!-- Isolate conversion of Runestone/interactive to PreTeXt/static -->\n<xsl:import href=\"./pretext-runestone-static.xsl\"/>\n\n<!-- We explicitly do not import \"pretext-common.xsl\" as we want    -->\n<!-- this important pre-processing stylesheet to have no hidden     -->\n<!-- dependencies.  In almost every rational use, the \"-common\"     -->\n<!-- stylesheet is imported by a conversion, so it is easy to       -->\n<!-- miss these dependencies.  An example in 2022-06 was the use    -->\n<!-- of the \"unique-id\" template to coordinate construction and     -->\n<!-- insertion of WeBWorK problems with an intervening trip to a    -->\n<!-- WW server.  The \"pretext-enhanced-source.xsl\" stylesheet is    -->\n<!-- one place where \"-common\" does not creep in.  Use of a modal   -->\n<!-- template here, with a definition in -common, will do a         -->\n<!-- massive \"value-of\" when not defined for the \"-enhanced-source\" -->\n<!-- stylesheet, which might be detectable (in strange ways).       -->\n\n<!-- The \"representations\" pass is used to make derived versions of      -->\n<!-- authored exercises which can be rendered dynamically.  For example, -->\n<!-- a multiple choice question.  These representations can be \"static\"  -->\n<!-- and so meant for use in PDF or braille output, or \"dynamic\", which  -->\n<!-- means anyplace Javascript (or similar) is available.  Right now     -->\n<!-- that is just HTML (and not output built on HTML, such as EPUB).     -->\n<!--                                                                     -->\n<!-- Notes:                                                              -->\n<!--   * We default here to \"static\".  HTML production will override     -->\n<!--     to \"dynamic\" and then any importing stylesheet will need to     -->\n<!--     override back to \"static\".                                      -->\n<!--   * 'pg-problems' are WeBWorK problems for an archive               -->\n<!--   * If testing, the pretext-enhanced-source.xsl  stylesheet will    -->\n<!--     need a stringparam override to view and test dynamic versions.  -->\n<xsl:variable name=\"exercise-style\" select=\"'static'\"/>\n\n<!-- Short-Circuit -->\n<!-- Sometimes we only want to stop at an intermediate tree.  For example, -->\n<!-- we may convert only to a \"version\" (valid PreTeXt) via resolution of  -->\n<!-- version support and customizations, or stop at the tree that has      -->\n<!-- @pi:assembly-id attributes but has not yet loaded exercise components.-->\n<!-- We control this with internal variables, not documented as author or  -->\n<!-- publisher features.  When we stop this early, \"exercise-style\" is     -->\n<!-- irrelevant.                                                           -->\n\n<!-- default is empty, so we can detect non-use -->\n<xsl:param name=\"assembly.version-only\" select=\"''\"/>\n<xsl:param name=\"assembly.assembly-id-only\" select=\"''\"/>\n\n<!-- Set to 'yes' to enable diagnostic checks, such as         -->\n<!-- verifying coherence of @pi:assembly-id and @pi:unique-id. -->\n<!-- Not documented as an author or publisher feature.         -->\n<xsl:param name=\"assembly.debug\" select=\"''\"/>\n<xsl:variable name=\"b-assembly-debug\" select=\"$assembly.debug = 'yes'\"/>\n\n<!-- Set to 'yes' to convert the @xml:base attributes stamped by the -->\n<!-- xinclude mechanism into @pi:source-uri attributes, so that a    -->\n<!-- diagnostic (validation, say) can name the file where a problem  -->\n<!-- lies.  Not documented as an author or publisher feature.        -->\n<xsl:param name=\"assembly.file-attribution\" select=\"''\"/>\n<xsl:variable name=\"b-file-attribution\" select=\"$assembly.file-attribution = 'yes'\"/>\n\n<!-- convert to a boolean, with error-checking -->\n<xsl:variable name=\"version-only\">\n    <xsl:choose>\n        <xsl:when test=\"$assembly.version-only = ''\">\n            <xsl:text>no</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$assembly.version-only = 'yes'\">\n            <xsl:text>yes</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$assembly.version-only = 'no'\">\n            <xsl:text>no</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message>PTX:BUG:  the internal parameter  assembly.version-only  received an unrecognized value of \"<xsl:value-of select=\"$assembly.version-only\"/>\" (possible values are \"yes\" and \"no\")</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n<xsl:variable name=\"b-version-only\" select=\"$version-only = 'yes'\"/>\n\n<!-- convert to a boolean, with error-checking -->\n<xsl:variable name=\"assembly-id-only\">\n    <xsl:choose>\n        <xsl:when test=\"$assembly.assembly-id-only = ''\">\n            <xsl:text>no</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$assembly.assembly-id-only = 'yes'\">\n            <xsl:text>yes</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$assembly.assembly-id-only = 'no'\">\n            <xsl:text>no</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message>PTX:BUG:  the internal parameter  assembly.assembly-id-only  received an unrecognized value of \"<xsl:value-of select=\"$assembly.assembly-id-only\"/>\" (possible values are \"yes\" and \"no\")</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n<xsl:variable name=\"b-assembly-id-only\" select=\"$assembly-id-only = 'yes'\"/>\n\n<!-- ################################################ -->\n<!-- Controlling Two-Pass Extraction and Substitution -->\n<!-- ################################################ -->\n\n<!-- Some objects are authored in their native source languages,     -->\n<!-- and after one application of this stylesheet, can be extracted, -->\n<!-- \"compiled\", and then automatically incorporated into output     -->\n<!-- formats.  An example is a \"latex-image\", which is extracted,    -->\n<!-- and compiled by LaTeX into an image, which can then simply be   -->\n<!-- pointed to reliably by the mechanisms of the various output     -->\n<!-- formats.  In other words, the result of this \"compilation\"      -->\n<!-- stands on its own, and is not brought back into the source.     -->\n<!--                                                                 -->\n<!-- Other objects are extracted, then processed (sent to a server   -->\n<!-- typically), and a \"static\" PreTeXt version, in valid PreTeXt    -->\n<!-- syntax, is returned and captured in files by the Python         -->\n<!-- extraction step.  Then in a general application of this         -->\n<!-- stylesheet to produce static output formats, those files are    -->\n<!-- read and the static versions are substituted into the eventual  -->\n<!-- source, for processing by stylesheets producing less-capable    -->\n<!-- output (less-capable than HTML).                                -->\n<!--                                                                 -->\n<!-- Such objects are:                                               -->\n<!--                                                                 -->\n<!--   WeBWorK (WW/PG), MyOpenMath (MOM), STACK,                     -->\n<!--   Dynamic Fill-in-the-Blank (FITB), bibliography                -->\n<!--   entries, and QR codes                                         -->\n<!--                                                                 -->\n<!-- But there is a \"chicken-and-egg condition\" if two such objects  -->\n<!-- are present in a fresh, un-processed, source document.  The     -->\n<!-- extraction of the first object will also try to \"sub in\" the    -->\n<!-- static versions of the second object from its                   -->\n<!-- extracted/generated files, which do not yet exist.  So we note  -->\n<!-- which extraction is happening *by a variable that is            -->\n<!-- over-ridden by the particular extraction stylesheet* and we     -->\n<!-- use this information to avoid the substitution.  We assume this -->\n<!-- does not disturb the identifiers in use to coordinate the       -->\n<!-- extraction and substitution.                                    -->\n<!--                                                                 -->\n<!-- At most, one of the following is true, and only if running      -->\n<!-- an extraction stylesheet.  In general use (producing useful     -->\n<!-- final output formats), they are all false.  The \"extraction\"    -->\n<!-- stylesheets for each type of object, will override exactly one  -->\n<!-- variable by setting it to \"true()\"                              -->\n<xsl:variable name=\"b-extracting-pg\"   select=\"false()\"/>\n<xsl:variable name=\"b-extracting-mom\"  select=\"false()\"/>\n<xsl:variable name=\"b-extracting-fitb\" select=\"false()\"/>\n<xsl:variable name=\"b-extracting-biblio\" select=\"false()\"/>\n<xsl:variable name=\"b-extracting-stack\" select=\"false()\"/>\n<xsl:variable name=\"b-extracting-qrcode\" select=\"false()\"/>\n\n<xsl:variable name=\"b-extracting\" select=\"$b-extracting-pg or $b-extracting-mom or $b-extracting-fitb or $b-extracting-biblio or $b-extracting-stack or $b-extracting-qrcode\"/>\n\n<!-- ############################## -->\n<!-- Source Assembly Infrastructure -->\n<!-- ############################## -->\n\n<!-- When building duplicates, we have occasion                     -->\n<!-- to inspect the original in various places                      -->\n<!-- We do not know if we have \"fixed\" the                          -->\n<!-- deprecated overall element, so need to                         -->\n<!-- try both.  For example, this variable is                       -->\n<!-- employed by the warnings and deprecation                       -->\n<!-- messages that result from analyzing an                         -->\n<!-- author's source, since we may \"repair\"                         -->\n<!-- some of them later, so we have to catch                        -->\n<!-- them early.                                                    -->\n<!-- The author's source, as parsed.  Kept for duties genuinely     -->\n<!-- about the source document: resolving relative filenames via    -->\n<!-- the second argument of the document() function, and            -->\n<!-- warnings/views that inspect exactly what the author wrote      -->\n<!-- (\"generic-warnings\", view-source).  Checks and lookups against -->\n<!-- the document's *content* belong on the assembled tree, $root,  -->\n<!-- where private solutions are merged and versions are resolved.  -->\n<xsl:variable name=\"original\" select=\"/mathbook|/pretext\"/>\n\n<!-- These modal templates duplicate the source exactly for each -->\n<!-- pass: elements, attributes, text, whitespace, comments,     -->\n<!-- everything. Various other templates will override these     -->\n<!-- templates to create a new enhanced source tree.             -->\n\n<xsl:template match=\"node()|@*\" mode=\"private-solutions\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"private-solutions\"/>\n    </xsl:copy>\n</xsl:template>\n\n<xsl:template match=\"node()|@*\" mode=\"version\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"version\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- Later, this template only *adds* an attribute to an element -->\n<!-- it is copying over to the result tree.  Here we copy text   -->\n<!-- nodes and the other attributes and the parameters are not   -->\n<!-- needed.  This is a general-purpose template, see comments   -->\n<!-- at further definition for elements.                         -->\n<xsl:template match=\"node()|@*\" mode=\"id-attribute\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"id-attribute\"/>\n    </xsl:copy>\n</xsl:template>\n\n<xsl:template match=\"node()|@*\" mode=\"assembly\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"assembly\"/>\n    </xsl:copy>\n</xsl:template>\n\n<xsl:template match=\"node()|@*\" mode=\"exercise\">\n    <xsl:param name=\"division\" select=\"''\"/>\n\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"exercise\">\n            <xsl:with-param name=\"division\" select=\"$division\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<xsl:template match=\"node()|@*\" mode=\"dynamic-substitution\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"dynamic-substitution\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- The highest format version of the substitutions file this stylesheet  -->\n<!-- knows how to read.  Version 1 is the form in which an \"eval-subst\"    -->\n<!-- carries \"latex\" and \"plain\" children.  Files written before that      -->\n<!-- distinction existed carry no @version and hold text directly; they    -->\n<!-- are read as version 0 by the fallback in \"dynamic-representation\".    -->\n<xsl:variable name=\"dynamic-substitutions-format\" select=\"1\"/>\n\n<!-- The root of this pass, which runs once, and so is where a check on    -->\n<!-- the substitutions file as a whole belongs rather than at each of the  -->\n<!-- individual lookups.  Without this the file would be read by a         -->\n<!-- stylesheet older than the script that wrote it, and the mismatch      -->\n<!-- would surface as substitutions quietly coming out wrong instead of    -->\n<!-- as a statement of what is actually the matter.                        -->\n<xsl:template match=\"/\" mode=\"dynamic-substitution\">\n    <xsl:if test=\"($exercise-style = 'static') and not($b-extracting) and not($dynamic-substitutions-file = '')\">\n        <xsl:variable name=\"recorded\" select=\"document($dynamic-substitutions-file,$original)/*/@version\"/>\n        <!-- A missing @version is an older file, and is silent: the        -->\n        <!-- representation template already falls back for those.  Only a  -->\n        <!-- version from the future is worth saying anything about.        -->\n        <xsl:if test=\"$recorded &gt; $dynamic-substitutions-format\">\n            <xsl:message>\n                <xsl:text>PTX:WARNING: the dynamic substitutions file records format version </xsl:text>\n                <xsl:value-of select=\"$recorded\"/>\n                <xsl:text>,&#xa;</xsl:text>\n                <xsl:text>but this version of PreTeXt reads version </xsl:text>\n                <xsl:value-of select=\"$dynamic-substitutions-format\"/>\n                <xsl:text> at the newest.  The file was written by a&#xa;</xsl:text>\n                <xsl:text>newer PreTeXt, and dynamic exercises may come out wrong.  Either update&#xa;</xsl:text>\n                <xsl:text>PreTeXt, or delete the file and let this version generate it again.</xsl:text>\n            </xsl:message>\n        </xsl:if>\n    </xsl:if>\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"dynamic-substitution\"/>\n    </xsl:copy>\n</xsl:template>\n\n<xsl:template match=\"node()|@*\" mode=\"representations\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"representations\"/>\n    </xsl:copy>\n</xsl:template>\n\n<xsl:template match=\"node()|@*\" mode=\"repair\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"repair\"/>\n    </xsl:copy>\n</xsl:template>\n\n<xsl:template match=\"node()|@*\" mode=\"enrichment\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"enrichment\"/>\n    </xsl:copy>\n</xsl:template>\n\n<xsl:template match=\"node()|@*\" mode=\"labels\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"labels\"/>\n    </xsl:copy>\n</xsl:template>\n\n<xsl:template match=\"node()|@*\" mode=\"augment\">\n    <xsl:param name=\"parent-struct\" select=\"''\"/>\n    <xsl:param name=\"level\" select=\"0\"/>\n\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"augment\">\n            <xsl:with-param name=\"parent-struct\" select=\"$parent-struct\"/>\n            <xsl:with-param name=\"level\" select=\"$level\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<!-- Catch-all identity: thread the inherited node-sets through. -->\n<xsl:template match=\"node()|@*\" mode=\"serial-stamp\">\n    <!-- no defaults: every caller passes the scopes explicitly -->\n    <xsl:param name=\"eq-nodes\"/>\n    <xsl:param name=\"fn-nodes\"/>\n    <xsl:param name=\"blocks-nodes\"/>\n    <xsl:param name=\"figure-nodes\"/>\n    <xsl:param name=\"project-nodes\"/>\n    <xsl:param name=\"exercise-nodes\"/>\n    <xsl:param name=\"openproblem-nodes\"/>\n    <xsl:copy>\n        <xsl:apply-templates select=\"@*|node()\" mode=\"serial-stamp\">\n            <xsl:with-param name=\"eq-nodes\" select=\"$eq-nodes\"/>\n            <xsl:with-param name=\"fn-nodes\" select=\"$fn-nodes\"/>\n            <xsl:with-param name=\"blocks-nodes\" select=\"$blocks-nodes\"/>\n            <xsl:with-param name=\"figure-nodes\" select=\"$figure-nodes\"/>\n            <xsl:with-param name=\"project-nodes\" select=\"$project-nodes\"/>\n            <xsl:with-param name=\"exercise-nodes\" select=\"$exercise-nodes\"/>\n            <xsl:with-param name=\"openproblem-nodes\" select=\"$openproblem-nodes\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<!-- ##################### -->\n<!-- The Assembly Pipeline -->\n<!-- ##################### -->\n\n<!-- These templates initiate and create several iterations of -->\n<!-- the source tree via modal templates.  Think of each as a  -->\n<!-- \"pass\" through the source. Generally this constructs the  -->\n<!-- new tree as a (text) result tree fragment and then we     -->\n<!-- convert it into real XML nodes. These \"real\" trees have a -->\n<!-- root element, as a result of the node-set() manufacture.  -->\n\n<!-- The per-pass overview at the top of this file names what      -->\n<!-- each variable below contributes; this sequence of             -->\n<!-- variables is the authoritative pass order.                    -->\n\n<!-- Grab private solutions first.  The \"exercise\" (and more) -->\n<!-- that they belong to might be part of a version (have a   -->\n<!-- @component attribute) and we don't want to miss that.    -->\n<!-- It can happen next.                                      -->\n<!-- Without a file of private solutions this pass is the identity, -->\n<!-- so we do not build (or hold) a copy of the entire source: the   -->\n<!-- result tree fragment stays empty, and the filtered union below  -->\n<!-- hands the authored source itself to the next pass.              -->\n<xsl:variable name=\"private-solutions-rtf\">\n    <xsl:if test=\"$b-private-solutions\">\n        <xsl:apply-templates select=\"/\" mode=\"private-solutions\"/>\n    </xsl:if>\n</xsl:variable>\n<xsl:variable name=\"private-solutions\" select=\"exsl:node-set($private-solutions-rtf)[$b-private-solutions] | (/)[not($b-private-solutions)]\"/>\n\n<xsl:variable name=\"version-rtf\">\n    <xsl:apply-templates select=\"$private-solutions\" mode=\"version\"/>\n</xsl:variable>\n<xsl:variable name=\"version\" select=\"exsl:node-set($version-rtf)\"/>\n\n<!-- The \"version\" tree should be valid PreTeXt.  Furthermore, there  -->\n<!-- should not be anymore modifications in subsequent passes which   -->\n<!-- change the gross structure of a document (i.e. nature of the     -->\n<!-- divisions).  The determination of various publisher variables,   -->\n<!-- mostly relative to numbering depth, have default values that     -->\n<!-- depend on the structure.  So aspects of this tree are consulted  -->\n<!-- frequently in  publisher-variables.xsl.  This includes           -->\n<!-- $html-chunk-level which inspects top-level division structure    -->\n<!-- (book/part, article/section) to set chunking defaults.           -->\n<!-- Also, note that this tree is useful for certain tasks, like      -->\n<!-- validation, or reporting values of publisher variables, without  -->\n<!-- regard to the subsequent passes.                                 -->\n<!-- The version tree is the earliest assembly product a publisher   -->\n<!-- variable may consult (structure can differ by version).  The    -->\n<!-- passes up to, and including, \"version\" must never consult a     -->\n<!-- variable defined from this tree — that is a circular reference, -->\n<!-- detected only at runtime.  The \"crossing point\" facts in        -->\n<!-- publisher-variables.xsl enumerate the consumers.                -->\n<xsl:variable name=\"version-root\" select=\"$version/pretext\"/>\n<xsl:variable name=\"version-docinfo\" select=\"$version-root/docinfo\"/>\n<xsl:variable name=\"version-document-root\" select=\"$version-root/*[not(self::docinfo)]\"/>\n\n<!-- This pass adds 100% internal identification for elements before   -->\n<!-- anything has been added or subtracted. The tree it builds is used -->\n<!-- for constructing \"View Source\" knowls in HTML output as a form of -->\n<!-- always-accurate documentation.  And this is its only purpose.     -->\n<!-- N.B.: see the $original-labeled tree used in the HTML conversion, -->\n<!-- optionally, under the sway of a string parameter.  This is in the -->\n<!-- (imported) pretext-view-source.xsl stylesheet.                    -->\n<!-- Hack: to short-circuit this stylesheet, in the case of desiring   -->\n<!-- the \"version\" tree *only*, we create an empty RTF.  This becomes  -->\n<!-- a (essentially) empty node-set.  The empty node-set is the input  -->\n<!-- the next pass, which will create an empty RTF, which will create  -->\n<!-- an empty node-set.  Rinse.  Repeat.  Even though all these        -->\n<!-- passes/variables are created, this is about a 17x speed-up.       -->\n<!-- A review suggests there is no fixed overhead in any of these      -->\n<!-- subsequent passes.                                                -->\n<xsl:variable name=\"original-labeled-rtf\">\n    <!-- written as a \"choose\" for clarity -->\n    <xsl:choose>\n        <!-- short-circuit to stop after \"version\" -->\n        <xsl:when test=\"$b-version-only\"/>\n        <!-- build on \"version\" to add original id's -->\n        <xsl:otherwise>\n            <!-- Duplicate identifiers are an authoring error, so the checks -->\n            <!-- run on the version tree: private solutions are merged by    -->\n            <!-- now (authored content in companion files), while version    -->\n            <!-- resolution has already discarded the deliberate duplicates  -->\n            <!-- that multi-version source may carry.  Later phases          -->\n            <!-- manufacture copies of authored content (e.g. static         -->\n            <!-- representations of interactive exercises), and those must   -->\n            <!-- not be blamed on the author.                                -->\n            <xsl:call-template name=\"duplication-check-xmlid\">\n                <xsl:with-param name=\"nodes\" select=\"$version//*[@xml:id]\"/>\n                <xsl:with-param name=\"purpose\" select=\"'authored'\"/>\n            </xsl:call-template>\n            <xsl:call-template name=\"duplication-check-label\">\n                <xsl:with-param name=\"nodes\" select=\"$version//*[@label]\"/>\n                <xsl:with-param name=\"purpose\" select=\"'authored'\"/>\n            </xsl:call-template>\n            <!-- checks are done, now add the \"original-id\" identification -->\n            <xsl:apply-templates select=\"$version\" mode=\"id-attribute\">\n                <!-- $parent-id defaults to 'root' in template -->\n                <xsl:with-param name=\"attr-name\" select=\"'original-id'\"/>\n            </xsl:apply-templates>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n<xsl:variable name=\"original-labeled\" select=\"exsl:node-set($original-labeled-rtf)\"/>\n\n<xsl:variable name=\"assembly-rtf\">\n    <xsl:apply-templates select=\"$original-labeled\" mode=\"assembly\"/>\n</xsl:variable>\n<xsl:variable name=\"assembly\" select=\"exsl:node-set($assembly-rtf)\"/>\n\n<!-- Exercises are \"tagged\" as to their nature (division, inline, -->\n<!-- worksheet, reading, project-like) and interactive exercises  -->\n<!-- get more precise categorization.  The latter is used to      -->\n<!-- determine if Runestone Services are loaded.                  -->\n\n<xsl:variable name=\"exercise-rtf\">\n    <!-- initialize with default, 'inline' -->\n    <xsl:apply-templates select=\"$assembly\" mode=\"exercise\">\n        <xsl:with-param name=\"division\" select=\"'inline'\"/>\n    </xsl:apply-templates>\n</xsl:variable>\n<xsl:variable name=\"exercise\" select=\"exsl:node-set($exercise-rtf)\"/>\n\n<xsl:variable name=\"assembly-label-rtf\">\n    <xsl:apply-templates select=\"$exercise\" mode=\"id-attribute\">\n        <!-- $parent-id defaults to 'root' in template -->\n        <xsl:with-param name=\"attr-name\" select=\"'assembly-id'\"/>\n    </xsl:apply-templates>\n</xsl:variable>\n<xsl:variable name=\"assembly-label\" select=\"exsl:node-set($assembly-label-rtf)\"/>\n\n<!-- Make static substitutions for dynamic exercises.  This runs AFTER      -->\n<!-- the @pi:assembly-id stamp because the substitution round trip keys on  -->\n<!-- @pi:assembly-id: extract-dynamic.xsl writes it as the exercise_id, and -->\n<!-- the lookup below reads it.  @pi:assembly-id is the early identifier    -->\n<!-- both ends can compute consistently (the authored @label would only     -->\n<!-- match for labeled exercises, missing unlabeled ones and tasks).        -->\n<!-- The pass only acts on the elements enumerated in this presence         -->\n<!-- test (see the \"dynamic-substitution\" templates); without any of        -->\n<!-- them it is the identity, so we skip the full-tree copy.  NB: a         -->\n<!-- new template in the mode must be reflected in this test.               -->\n<xsl:variable name=\"b-has-dynamic-markup\" select=\"boolean($assembly-label//setup | $assembly-label//numcmp | $assembly-label//strcmp | $assembly-label//jscmp | $assembly-label//mathcmp | $assembly-label//logic | $assembly-label//fillin[@ansobj] | $assembly-label//eval[@obj])\"/>\n<!-- \"assembly-id-only\" emits $assembly-label, so every pass below is   -->\n<!-- discarded in that mode.  $post-label is empty then, and each later -->\n<!-- pass takes its input from $post-label, so each one copies nothing  -->\n<!-- and opens no file.  The test is written once, here, instead of     -->\n<!-- being repeated in every pass: libxslt computes a global variable   -->\n<!-- even when nothing uses the result, so a pass is not skipped just   -->\n<!-- by leaving its variable unread.                                    -->\n<xsl:variable name=\"post-label\" select=\"$assembly-label[not($b-assembly-id-only)]\"/>\n<xsl:variable name=\"dynamic-rtf\">\n    <xsl:if test=\"$b-has-dynamic-markup\">\n        <xsl:apply-templates select=\"$post-label\" mode=\"dynamic-substitution\"/>\n    </xsl:if>\n</xsl:variable>\n<xsl:variable name=\"dynamic\" select=\"exsl:node-set($dynamic-rtf)[$b-has-dynamic-markup] | $post-label[not($b-has-dynamic-markup)]\"/>\n\n<xsl:variable name=\"representations-rtf\">\n    <xsl:apply-templates select=\"$dynamic\" mode=\"representations\"/>\n</xsl:variable>\n<xsl:variable name=\"representations\" select=\"exsl:node-set($representations-rtf)\"/>\n\n<!-- Dependency: \"repair\" will fix some exercise representations, -->\n<!-- especially coming from an \"old\" WeBWorK server, so the       -->\n<!-- \"repair\" pass must come after the \"representations\" pass.    -->\n<xsl:variable name=\"repair-rtf\">\n    <xsl:apply-templates select=\"$representations\" mode=\"repair\"/>\n</xsl:variable>\n<xsl:variable name=\"repair\" select=\"exsl:node-set($repair-rtf)\"/>\n\n<!-- \"enrichment\" will *add* to the source automatically,  -->\n<!-- such as footnotes with URLs that might not be visible -->\n<!-- in static formats.                                    -->\n<xsl:variable name=\"enrichment-rtf\">\n    <xsl:apply-templates select=\"$repair\" mode=\"enrichment\"/>\n</xsl:variable>\n<xsl:variable name=\"enrichment\" select=\"exsl:node-set($enrichment-rtf)\"/>\n\n<!-- 2024-02-08: the construction of @label from @xml:id was split  -->\n<!-- out of the \"identification\" pass, so is located here.  Perhaps -->\n<!-- it can/should move earlier, maybe not.                         -->\n<xsl:variable name=\"labels-rtf\">\n    <xsl:apply-templates select=\"$enrichment\" mode=\"labels\"/>\n</xsl:variable>\n<xsl:variable name=\"labels\" select=\"exsl:node-set($labels-rtf)\"/>\n\n<xsl:variable name=\"identification-rtf\">\n    <xsl:apply-templates select=\"$labels\" mode=\"id-attribute\">\n        <!-- $parent-id defaults to 'root' in template -->\n        <xsl:with-param name=\"attr-name\" select=\"'unique-id'\"/>\n    </xsl:apply-templates>\n</xsl:variable>\n<xsl:variable name=\"identification\" select=\"exsl:node-set($identification-rtf)\"/>\n\n<xsl:variable name=\"augment-rtf\">\n    <xsl:apply-templates select=\"$identification\" mode=\"id-coherence-check\"/>\n    <xsl:apply-templates select=\"$identification\" mode=\"augment\"/>\n</xsl:variable>\n<xsl:variable name=\"augment\" select=\"exsl:node-set($augment-rtf)\"/>\n\n<xsl:variable name=\"serial-stamp-rtf\">\n    <!-- begin the pass with no counting scope yet -->\n    <xsl:apply-templates select=\"$augment\" mode=\"serial-stamp\">\n        <xsl:with-param name=\"eq-nodes\" select=\"/..\"/>\n        <xsl:with-param name=\"fn-nodes\" select=\"/..\"/>\n        <xsl:with-param name=\"blocks-nodes\" select=\"/..\"/>\n        <xsl:with-param name=\"figure-nodes\" select=\"/..\"/>\n        <xsl:with-param name=\"project-nodes\" select=\"/..\"/>\n        <xsl:with-param name=\"exercise-nodes\" select=\"/..\"/>\n        <xsl:with-param name=\"openproblem-nodes\" select=\"/..\"/>\n    </xsl:apply-templates>\n</xsl:variable>\n<xsl:variable name=\"serial-stamp\" select=\"exsl:node-set($serial-stamp-rtf)\"/>\n\n<!--                        IMPORTANT                           -->\n<!--                                                            -->\n<!-- Definitions that follow may be overridden after additional -->\n<!-- per-conversion passes that takeoff from the final tree,    -->\n<!-- here $augment.                                             -->\n<!--                                                            -->\n<!--    IF $augment CHANGES, SEARCH FOR AFFECTED CONVERSIONS    -->\n<!--                                                            -->\n<!-- 2023-03-20: braille conversion incorporares Nemeth braille -->\n\n<!-- The main \"pretext\" element only has two possible children      -->\n<!-- One is \"docinfo\", the other is \"book\", \"article\", etc.         -->\n<!-- This is of interest by itself, or the root of content searches -->\n<!-- And docinfo is the other child, these help prevent searching   -->\n<!-- the wrong half.                                                -->\n<!-- NB: source repair below converts a /mathbook to a /pretext     -->\n<xsl:variable name=\"root\" select=\"$serial-stamp/pretext\"/>\n<xsl:variable name=\"docinfo\" select=\"$root/docinfo\"/>\n<xsl:variable name=\"document-root\" select=\"$root/*[not(self::docinfo)]\"/>\n<xsl:variable name=\"bibinfo\" select=\"$document-root/frontmatter/bibinfo\"/>\n\n<!-- ################# -->\n<!-- Private Solutions -->\n<!-- ################# -->\n\n<!-- \"solutions\" here refers generically to \"hint\", \"answer\",  -->\n<!-- and \"solution\" elements of an \"exercise\".  An author may  -->\n<!-- wish to provide limited distribution of some solutions to -->\n<!-- exercises, which we deem \"private\" here.  If a            -->\n<!-- \"private-solutions-file\" is provided, it will be mined    -->\n<!-- for these private solutions.                              -->\n\n<!-- Note: there may be (nested) \"pi:privatesolutionsdivision\"  -->\n<!-- elements in this file.  They are largely meaningless, but  -->\n<!-- are necessary if an author wants to modularize their       -->\n<!-- collection across multiple files.  Then each file can be a -->\n<!-- single overall element.  (We expect/require no additional  -->\n<!-- structure in this file.)  The consequence is the \"//\" in   -->\n<!-- each expression below.                                     -->\n<!-- NB: relative to *original* source file/tree                -->\n<xsl:variable name=\"privatesolns\" select=\"document($private-solutions-file, $original)\"/>\n<xsl:variable name=\"n-hint\"     select=\"$privatesolns/pi:privatesolutions//hint\"/>\n<xsl:variable name=\"n-answer\"   select=\"$privatesolns/pi:privatesolutions//answer\"/>\n<xsl:variable name=\"n-solution\" select=\"$privatesolns/pi:privatesolutions//solution\"/>\n\n<!-- Note that when there are any private solutions then we make a copy that     -->\n<!--   - does not preserve interstitial text nodes (whitespace indentation)      -->\n<!--   - preserves things like \"feedback\", \"choices\", but may reorder them       -->\n<!--     to occur before solutions                                               -->\n<!--   - this happens for *every* \"exercise\", even if it does not have           -->\n<!--     private solutions                                                       -->\n<!--                                                                             -->\n<!-- So there could be                                                           -->\n<!--   - more care about placing new \"hint\", \"answer\", \"solution\"                -->\n<!--     in the right order, perhaps by exploding this out into templates        -->\n<!--   - condition on                                                            -->\n<!--     $n-hint[@ref=$the-id]|$n-answer[@ref=$the-id]|$n-solution[@ref=$the-id] -->\n<!--     to only manipulate an exercise that needs it                            -->\n<xsl:template match=\"exercise|task\" mode=\"private-solutions\">\n    <xsl:choose>\n        <!-- $b-private-solutions is a publisher variable determined   -->\n        <!-- by the specification of a file of private solutions there -->\n        <xsl:when test=\"$b-private-solutions\">\n            <xsl:variable name=\"the-id\" select=\"@xml:id\"/>\n            <xsl:copy>\n                <!-- attributes, then all elements that are not solutions                               -->\n                <!--   unstructured exercise:  \"p\" etc, then solutions OK even if schema violation?     -->\n                <!--   structured exercise: copy statement, then interleave solutions                   -->\n                <!--   non-terminal Task: introduction, task, conclusion                                -->\n                <!--   terminal unstructured task: \"p\" etc, then solutions OK even if schema violation? -->\n                <!--   terminal structured task: copy statement, then interleave solutions              -->\n                <!-- TODO: defend against non-terminal task, unstructured cases      -->\n                <!-- (identify proper structure + non-empty union of three additions -->\n                <!-- Fix unstructured cases by inserting \"statement\",                -->\n                <!-- warn about non-terminal task case and drop additions (error)    -->\n                <xsl:apply-templates select=\"*[not(self::hint or self::answer or self::solution)]|@*\" mode=\"private-solutions\"/>\n                <!-- hints, answers, solutions; first regular, second private -->\n                <xsl:apply-templates select=\"hint\" mode=\"private-solutions\"/>\n                <xsl:apply-templates select=\"$n-hint[@ref=$the-id]\" mode=\"private-solutions\"/>\n                <xsl:apply-templates select=\"answer\" mode=\"private-solutions\"/>\n                <xsl:apply-templates select=\"$n-answer[@ref=$the-id]\" mode=\"private-solutions\"/>\n                <xsl:apply-templates select=\"solution\" mode=\"private-solutions\"/>\n                <xsl:apply-templates select=\"$n-solution[@ref=$the-id]\" mode=\"private-solutions\"/>\n            </xsl:copy>\n        </xsl:when>\n        <!-- otherwise, just a straight xerox -->\n        <xsl:otherwise>\n            <xsl:copy>\n                <xsl:apply-templates select=\"node()|@*\" mode=\"private-solutions\"/>\n            </xsl:copy>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- ######## -->\n<!-- Versions -->\n<!-- ######## -->\n\n<!-- The version feature (@component markings) allows for   -->\n<!-- invalid PreTeXt source.  For example, an author might  -->\n<!-- have two different \"docinfo\" elements for some reason. -->\n<!-- So we allow a sort of pre-PreTeXt, which does not      -->\n<!-- satisfy the schema.  Support for the \"custom\" element  -->\n<!-- is similar in spirit.  So very early on, we unravel    -->\n<!-- (resolve) these features, and if used properly the     -->\n<!-- result will be valid PreTeXt, according to the schema. -->\n\n<!-- Only elements \"marked\" with @component need to be      -->\n<!-- examined, the catch-all xerox template above suffices. -->\n<xsl:template match=\"*[@component]\" mode=\"version\">\n    <!-- prepare for test below -->\n    <xsl:variable name=\"single-component-fenced\" select=\"concat('|', normalize-space(@component), '|')\"/>\n    <xsl:choose>\n        <!-- version scheme not elected, so use element no matter what -->\n        <!-- note that @include=\"\" yields \"||\" in test here            -->\n        <xsl:when test=\"$components-fenced = ''\">\n            <xsl:copy>\n                <xsl:apply-templates select=\"node()|@*\" mode=\"version\"/>\n            </xsl:copy>\n        </xsl:when>\n        <!-- version scheme elected, element participating, so use element -->\n        <!-- if it is a component in publisher's selection of components   -->\n        <xsl:when test=\"contains($components-fenced, $single-component-fenced)\">\n            <xsl:copy>\n                <xsl:apply-templates select=\"node()|@*\" mode=\"version\"/>\n            </xsl:copy>\n        </xsl:when>\n        <!-- version scheme elected, element participating, but its component -->\n        <!-- has not been selected in publisher file, so it gets dropped here -->\n        <xsl:otherwise/>\n    </xsl:choose>\n</xsl:template>\n\n<!-- We use various ad-hoc, non-author elements in lots of places.     -->\n<!-- Best to prefix them all with a namespace and keep them separate   -->\n<!-- from author-land.  Thus, the \"pretext internal\" namespace with    -->\n<!-- prefix/alias \"pi\". But we don't want authors to use some of       -->\n<!-- these elements, like the presentational \"pi:bold\"!                -->\n<!--                                                                   -->\n<!-- So we kill these elements (and attributes) early.  So this is     -->\n<!-- really unrelated to versions, but tere should be little danger in -->\n<!-- doing in here and now.  The \"private-solutions\" pass is a place   -->\n<!-- where files use this prefix, so maybe best not to do it there.    -->\n\n<xsl:template match=\"pi:*\" mode=\"version\"/>\n<xsl:template match=\"@pi:*\" mode=\"version\"/>\n\n<!-- Exception: when file attribution has been requested (below), a -->\n<!-- @pi:source-uri stamped on the source (by the pretext/pretext   -->\n<!-- script's include mechanism, say) rides through the version     -->\n<!-- pass, so a diagnostic can name the file where a problem lies.  -->\n<xsl:template match=\"@pi:source-uri\" mode=\"version\">\n    <xsl:if test=\"$b-file-attribution\">\n        <xsl:copy/>\n    </xsl:if>\n</xsl:template>\n\n<!-- The xinclude mechanism stamps an @xml:base attribute onto the  -->\n<!-- root element of every included file.  We drop it during the    -->\n<!-- version pass, so the assembled source carries none, and the    -->\n<!-- schema need not permit it.  But when file attribution has been -->\n<!-- requested (validation, say, so a problem can be located in the -->\n<!-- file where it lies) we mint a @pi:source-uri instead,          -->\n<!-- consistent with the other \"pi:\" provenance attributes.         -->\n<xsl:template match=\"@xml:base\" mode=\"version\">\n    <xsl:if test=\"$b-file-attribution\">\n        <xsl:attribute name=\"pi:source-uri\">\n            <xsl:value-of select=\".\"/>\n        </xsl:attribute>\n    </xsl:if>\n</xsl:template>\n\n<!-- The \"custom\" element, with a @name in an auxiliary file,     -->\n<!-- and a @ref in a source file, allows for custom substitutions -->\n\n<!-- If the publisher variable  $customizations-file  is bad, -->\n<!-- then  document()  will raise an error.  The empty string -->\n<!-- (default) will not raise an error, so if not specified,  -->\n<!-- no problem.  But an empty string, and an attempted       -->\n<!-- access in the template *will* raise the error below.     -->\n<xsl:variable name=\"customizations\" select=\"document($customizations-file, $original)\"/>\n\n<!-- Set the key, nodes to be located are named -->\n<!-- \"custom\" within the file just accessed     -->\n<!-- For each one, @name is the search term     -->\n<!-- that will locate it: the key, the index    -->\n<xsl:key name=\"name-key\" match=\"custom\" use=\"@name\"/>\n\n<xsl:template match=\"custom[@ref]\" mode=\"version\">\n    <!-- We need to get the @ref attribute now, due to a context shift -->\n    <!-- And the \"custom\" context also, for use in a location report   -->\n    <xsl:variable name=\"the-ref\" select=\"string(@ref)\"/>\n    <xsl:variable name=\"the-custom\" select=\".\"/>\n    <!-- Now the context shift to query the customizations -->\n    <xsl:for-each select=\"$customizations\">\n        <xsl:variable name=\"the-lookup\" select=\"key('name-key', $the-ref)\"/>\n        <!-- This is an AWOL node, not empty content (which is allowed) -->\n        <xsl:if test=\"not($the-lookup)\">\n            <xsl:text>[MISSING CUSTOM CONTENT HERE]</xsl:text>\n            <xsl:message>PTX:ERROR:     lookup for a \"custom\" element with @name set to \"<xsl:value-of select=\"$the-ref\"/>\" has failed, while consulting the customization file \"<xsl:value-of select=\"$customizations-file\"/>\".  Output will contain \"[MISSING CUSTOM CONTENT HERE]\" instead</xsl:message>\n            <xsl:apply-templates select=\"$the-custom\" mode=\"location-report\"/>\n        </xsl:if>\n        <!-- Copying the contents of \"custom\" via the \"version\" templates  -->\n        <!-- will keep the \"pi\" namespace from appearing in places, as it  -->\n        <!-- will with an \"xsl:copy-of\" on the same node set.  But it      -->\n        <!-- allows nested \"custom\" elements.                              -->\n        <!--                                                               -->\n        <!-- Do we want authors to potentially create cyclic references?   -->\n        <!-- A simple 2-cycle test failed quickly and obviously, so it     -->\n        <!-- will be caught quite easily, it seems.                        -->\n        <xsl:apply-templates select=\"$the-lookup/node()\" mode=\"version\"/>\n    </xsl:for-each>\n</xsl:template>\n\n<!-- ############## -->\n<!-- Identification -->\n<!-- ############## -->\n\n<!-- This section is the id-attribute pass.  One mechanism (the    -->\n<!-- \"id-attribute\" templates below) is applied three times by     -->\n<!-- the chain (passes 3, 6 and 12), stamping @pi:original-id,     -->\n<!-- @pi:assembly-id and @pi:unique-id in turn.  The \"labels\" pass -->\n<!-- runs between the second and third of these (see \"Labels\"),    -->\n<!-- and the @label values it creates are what the @pi:unique-id   -->\n<!-- stamp reads here.  The contract that follows is what lets     -->\n<!-- the three stampings agree element-for-element.                -->\n\n<!-- ################################################### -->\n<!-- Structural Contract for Identification Passes       -->\n<!-- ################################################### -->\n\n<!-- The \"id-attribute\" template (mode=\"id-attribute\")       -->\n<!-- produces identification strings by a depth-first        -->\n<!-- traversal, encoding each element's position among its   -->\n<!-- siblings.  An element's ID depends only on its          -->\n<!-- ancestors and their sibling positions, so the template  -->\n<!-- is fast, unique, and local.                             -->\n<!--                                                         -->\n<!-- This template is applied three times, producing three   -->\n<!-- attributes on every element:                            -->\n<!--                                                         -->\n<!--   @pi:original-id                                       -->\n<!--       after \"version\", before any additions             -->\n<!--   @pi:assembly-id                                       -->\n<!--       after \"exercise\", before \"representations\"        -->\n<!--   @pi:unique-id                                         -->\n<!--       after \"labels\", the final structural form         -->\n<!--                                                         -->\n<!-- The architecture relies on one critical invariant:      -->\n<!--                                                         -->\n<!--   BETWEEN ANY TWO ID-STAMPING PASSES, NO INTERVENING    -->\n<!--   PASS MAY CHANGE THE NUMBER OR ORDER OF SIBLING        -->\n<!--   ELEMENTS AT ANY LEVEL OF THE TREE, EXCEPT WITHIN A    -->\n<!--   SUBTREE THAT IS BEING WHOLLY REPLACED (SAME PARENT,   -->\n<!--   SAME SIBLING POSITION).                               -->\n<!--                                                         -->\n<!-- This invariant holds because:                           -->\n<!--                                                         -->\n<!--   (a) Replacements (e.g. an interactive replaced by a   -->\n<!--       static sidebyside) occupy the same sibling        -->\n<!--       position as the original element.                 -->\n<!--                                                         -->\n<!--   (b) Replacements are never nested: a replaced         -->\n<!--       subtree does not itself contain another element   -->\n<!--       that will be replaced at a different sibling      -->\n<!--       position.                                         -->\n<!--                                                         -->\n<!--   (c) Each ID-stamping pass is placed at a moment when  -->\n<!--       the tree is structurally quiet - no pending       -->\n<!--       changes will shift sibling positions before the   -->\n<!--       next one.                                         -->\n<!--                                                         -->\n<!-- Consequence: the id-attribute template produces the     -->\n<!-- same ID for every non-replaced element across passes,   -->\n<!-- and a replaced element's ID (consumed during isolation) -->\n<!-- remains valid through to the substitution phase.        -->\n<!--                                                         -->\n<!-- Any future pass that inserts or removes sibling         -->\n<!-- elements (rather than replacing in-place) MUST be       -->\n<!-- placed so that it does not fall between two ID-stamping -->\n<!-- passes, or else the identification will silently drift. -->\n\n<!-- This general-purpose template constructs unique strings as part   -->\n<!-- of a natural depth-first exploration of the tree.  Strings are    -->\n<!-- reset when provided by authors on elements (ideally via @label).  -->\n<!-- Otherwise the tree structure is reflected by location at each     -->\n<!-- level of the subtree rooted at the last authored string.  A bit   -->\n<!-- unsightly, and only partially effective to unwind numbers back    -->\n<!-- to an element.  But super-fast to construct and reliably unique   -->\n<!-- (though an author could provide two strings that make a conflict, -->\n<!-- we believe).                                                      -->\n<xsl:template match=\"*\" mode=\"id-attribute\">\n    <xsl:param name=\"parent-id\"  select=\"'root'\"/>\n    <xsl:param name=\"attr-name\"  select=\"''\"/>\n\n    <xsl:copy>\n        <!-- duplicate all attributes -->\n        <xsl:apply-templates select=\"@*\" mode=\"id-attribute\"/>\n        <!-- * Strategy is much like @pi:original-id but maybe needs as much care         -->\n        <!-- * Element counts are used to reflect document tree structure                 -->\n        <!-- * Non-numeric separator needed to preserve uniqueness (e.g.1-12 != 11-2).    -->\n        <!-- * Separators are therefore hyphens                                           -->\n        <!-- * Colons as separators would create confusion with namespaces                -->\n        <!-- * Salt added to authored values could decrease risk of collision             -->\n        <xsl:variable name=\"new-id\">\n            <xsl:choose>\n                <!-- A @label might be authored.  Or not authored, and   -->\n                <!-- then an authored @xml:id was promoted into a @label -->\n                <xsl:when test=\"@label\">\n                    <xsl:value-of select=\"@label\"/>\n                </xsl:when>\n                <!-- This mimics the upgrade of an authored xml:id to a label -->\n                <!-- NB: this might not ever happen in some passes, when an   -->\n                <!-- @xml:id value has been upgraded to a @label value in a   -->\n                <!-- prior pass, because if there was an @xml:id, then it     -->\n                <!-- was upgraded to being a @label and if this \"choose\" gets -->\n                <!-- here, then the next test is false.                       -->\n                <xsl:when test=\"@xml:id\">\n                    <xsl:value-of select=\"@xml:id\"/>\n                </xsl:when>\n                <!-- Author has not supplied any sort of identification, no -->\n                <!-- @label and no @xml:id.  So we automatically devise one -->\n                <xsl:otherwise>\n                    <xsl:value-of select=\"$parent-id\"/>\n                    <xsl:text>-</xsl:text>\n                    <!-- Start counting from 1, easier to debug -->\n                    <xsl:number value=\"count(preceding-sibling::*) + 1\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:variable>\n        <xsl:attribute name=\"pi:{$attr-name}\">\n            <xsl:value-of select=\"$new-id\"/>\n        </xsl:attribute>\n        <!-- recurse -->\n        <xsl:apply-templates select=\"node()\" mode=\"id-attribute\">\n            <xsl:with-param name=\"parent-id\" select=\"$new-id\"/>\n            <xsl:with-param name=\"attr-name\" select=\"$attr-name\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<!-- There is no real purpose to put identification onto an     -->\n<!-- (X)HTML element floating around as part of an interactive. -->\n<xsl:template match=\"pf:*|xhtml:*\" mode=\"id-attribute\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"@*|node()\" mode=\"id-attribute\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- Diagnostic: verify @pi:assembly-id equals @pi:unique-id for -->\n<!-- every element that carries both.  A mismatch indicates      -->\n<!-- a structural change between the two ID-stamping passes      -->\n<!-- that violates the identification contract documented        -->\n<!-- near the top of this stylesheet.  Gated by the              -->\n<!-- assembly.debug parameter; does nothing when off.            -->\n\n<xsl:template match=\"node()|@*\" mode=\"id-coherence-check\">\n    <xsl:if test=\"$b-assembly-debug\">\n        <xsl:for-each select=\".//*[@pi:assembly-id and @pi:unique-id and not(@pi:assembly-id = @pi:unique-id)]\">\n            <xsl:message>\n                <xsl:text>PTX:DEBUG:  @pi:assembly-id / @pi:unique-id mismatch on &lt;</xsl:text>\n                <xsl:value-of select=\"local-name()\"/>\n                <xsl:text>&gt;: assembly-id=\"</xsl:text>\n                <xsl:value-of select=\"@pi:assembly-id\"/>\n                <xsl:text>\" unique-id=\"</xsl:text>\n                <xsl:value-of select=\"@pi:unique-id\"/>\n                <xsl:text>\"</xsl:text>\n            </xsl:message>\n        </xsl:for-each>\n    </xsl:if>\n</xsl:template>\n\n<!-- ######################## -->\n<!-- Bibliography Manufacture -->\n<!-- ######################## -->\n\n<!-- Initial experiment, overall \"references\" flagged with -->\n<!-- a @source filename as the place to go get a list of   -->\n<!-- candidate \"biblio\" (in desired order)                 -->\n<!-- NB: this needs a rethink when revisited.  A file of   -->\n<!-- bibliography items can be specified, perhaps in       -->\n<!-- in docinfo (runs with the source?), formed as         -->\n<!-- $biblios in -common, and then mined for matches not   -->\n<!-- explicitly present?                                   -->\n<xsl:template match=\"backmatter/references[@source]\" mode=\"assembly\">\n    <!-- Grab the list.  The filename is relative to the authored -->\n    <!-- document, so the lookup anchors on $original: the context -->\n    <!-- node lives in a constructed tree, which has no base URI   -->\n    <xsl:variable name=\"biblios\" select=\"document(@source, $original)\"/>\n    <!-- Copy the \"references\" element (could be literal, but maybe not in \"text\" output mode) -->\n    <xsl:copy>\n        <!-- @source attribute not needed in enhanced source -->\n        <xsl:apply-templates select=\"@*[not(local-name() = 'source')]\" mode=\"assembly\"/>\n        <!-- likely more elements to duplicate, consult schema -->\n        <xsl:apply-templates select=\"title\" mode=\"assembly\"/>\n        <!-- Look at each \"biblio\" in the external file -->\n        <xsl:for-each select=\"$biblios/pretext-biblios/biblio\">\n            <xsl:variable name=\"the-id\" select=\"@xml:id\"/>\n            <xsl:message>PTX:DEBUG: @xml:id of &lt;biblio&gt; in bibliography file: <xsl:value-of select=\"$the-id\"/></xsl:message>\n            <!-- Building duplicate, so look in this pass's input  -->\n            <!-- tree (the version in play) for an \"xref\" pointing -->\n            <!-- to the current context \"biblio\"                   -->\n            <xsl:if test=\"$original-labeled//xref[@ref = $the-id]\">\n                <xsl:message>PTX:DEBUG:  Located this &lt;biblio&gt; cited in original source</xsl:message>\n                <xsl:apply-templates select=\".\" mode=\"assembly\"/>\n            </xsl:if>\n        </xsl:for-each>\n    </xsl:copy>\n</xsl:template>\n\n<!-- ########################################################## -->\n<!-- ########################################################## -->\n<!-- 2025-08-13: these error checks are not really right.       -->\n<!-- Testing for existence of the file of references seems      -->\n<!-- to be the big problem?  If it does not exist, the          -->\n<!-- processor just fails altogether?  Further, these variables -->\n<!-- might be renamed as positive events, to ease the logic.    -->\n<!-- ########################################################## -->\n<!-- ########################################################## -->\n\n<!-- To use CSL styles, we need to determine if a few things are in place -->\n<!-- (a)  are we even using CSL style files at all                        -->\n<!-- (b)  if we are extracting or not                                     -->\n<!-- (c)  if the desired generated references and citations exist         -->\n<!-- (d)  if the generated file exists, built with the same style file?   -->\n<!-- Without everything in place, we just copy references/\"biblio\".        -->\n<!-- Here comes the gauntlet -->\n\n<!-- $b-using-csl-styles: a consequence of opting in via publisher file         -->\n<!-- $b-extracting-biblio: set here and overridden in the extraction stylesheet -->\n\n<!-- two error conditions -->\n<!-- 2025-08-13: this variable is always false -->\n<xsl:variable name=\"missing-csl-file\">\n    <xsl:choose>\n        <!-- can't be missing if we don't need it, and we   -->\n        <!-- don't induce panic by looking for it, when it  -->\n        <!-- isn't called for, and getting ominous warnings -->\n        <xsl:when test=\"not($b-using-csl-styles)\">\n            <xsl:text>no</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>no</xsl:text>\n            <!-- this is only a test, variable is local and not retained -->\n            <!-- <xsl:variable name=\"the-references\" -->\n                <!-- select=\"document($csl-file, $original)/pi:csl-references\"/> -->\n            <!-- since we build the file, condiition on the size of -->\n            <!-- this node-set:  one (good) or none (bad, missing)  -->\n            <!-- <xsl:choose> -->\n                <!-- file looks good -->\n                <!-- <xsl:when test=\"count($the-references) = 1\"> -->\n                    <!-- <xsl:text>no</xsl:text> -->\n                <!-- </xsl:when> -->\n                <!-- nothing came of document() -->\n                <!-- <xsl:otherwise> -->\n                    <!-- <xsl:text>yes</xsl:text> -->\n                    <!-- and we take the opportunity to say so, just once, and early on -->\n                    <!-- <xsl:message>PTX:ERROR:     your publisher file indicates the use of a Citation Stylesheet Language (CSL) specification for references, but we have not located your file of generated references and citations at \"<xsl:value-of select=\"$csl-file\"/>\".  We will fall back to default processing in order to proceed.</xsl:message> -->\n                <!-- </xsl:otherwise> -->\n            <!-- </xsl:choose> -->\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n<xsl:variable name=\"b-missing-csl-file\" select=\"$missing-csl-file = 'yes'\"/>\n\n<!-- This is the case of having a style file specified in    -->\n<!-- the publisher file AND having a generated file of       -->\n<!-- references and citations AND the two versions of the    -->\n<!-- style file used do not match.  The first two conditions -->\n<!-- should always be consulted.                             -->\n<xsl:variable name=\"style-file-mismatch\">\n    <xsl:choose>\n        <!-- we do not warning at the end of this template, -->\n        <!-- just because the file itself does not exist    -->\n        <xsl:when test=\"not($b-using-csl-styles) or $missing-csl-file\">\n            <xsl:text>no</xsl:text>\n        </xsl:when>\n        <!-- now we are using CSL styles and we do have a file to interrogate -->\n        <xsl:otherwise>\n            <!-- this is only a test, variable is local and not retained -->\n            <xsl:variable name=\"the-references\"\n                select=\"document($csl-file, $original)/pi:csl-references\"/>\n            <!-- attribute in generated file saying which style file was used -->\n            <xsl:variable name=\"csl-style-file-for-generated\">\n                <xsl:value-of select=\"$the-references/@csl-style-file\"/>\n            </xsl:variable>\n            <xsl:choose>\n                <xsl:when test=\"$csl-style-file = $csl-style-file-for-generated\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:text>yes</xsl:text>\n                    <!-- and we take the opportunity to say so, just once, and early on -->\n                    <xsl:message>PTX:WARNING:     your publisher file indicates the use of one Citation Stylesheet Language (CSL) specification for references (\"<xsl:value-of select=\"$csl-style-file\"/>\"), but your file of generated references and citations at \"<xsl:value-of select=\"$csl-file\"/>\" was built using a different CSL style file (\"<xsl:value-of select=\"$csl-style-file-for-generated\"/>\").  We will fall back to default processing in order to proceed.</xsl:message>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n<xsl:variable name=\"b-style-file-mismatch\" select=\"$style-file-mismatch = 'yes'\"/>\n\n<!-- ########################################################## -->\n<!-- ########################################################## -->\n<!-- 2025-08-13: end of incomplete error logic.                 -->\n<!-- ########################################################## -->\n<!-- ########################################################## -->\n\n<xsl:template match=\"backmatter/references[not(@source)]\" mode=\"assembly\">\n    <xsl:choose>\n        <!-- duplicate for biblio extraction process or if using -->\n        <!-- default (simplistic) PreTeXt bibliography support   -->\n        <xsl:when test=\"$b-extracting-biblio or not($b-using-csl-styles)\">\n            <xsl:copy>\n                <xsl:apply-templates select=\"node()|@*\" mode=\"assembly\"/>\n            </xsl:copy>\n        </xsl:when>\n        <!-- not extracting, so doing a conversion, and also     -->\n        <!-- must be using CSL styles, so a collection of        -->\n        <!-- processed references and citations should exist     -->\n        <!-- but maybe not (this \"when\" is separate for clarity) -->\n        <xsl:when test=\"$b-missing-csl-file or $b-style-file-mismatch\">\n            <xsl:copy>\n                <xsl:apply-templates select=\"node()|@*\" mode=\"assembly\"/>\n            </xsl:copy>\n        </xsl:when>\n        <!-- not extracting, using CSL, have a generated file,  -->\n        <!-- matching styles in publihser file and in generated -->\n        <!-- file.  We can just do it.                          -->\n        <xsl:otherwise>\n            <!-- $csl-file is defined in the publisher-variables stylesheet, -->\n            <xsl:variable name=\"the-references\"\n                select=\"document($csl-file, $original)/pi:csl-references\"/>\n            <!-- Now, a \"choose\" within the above \"otherwise\".  If the file -->\n            <!-- is missing or mis-matched, we just duplicate.  Otherwise,  -->\n            <!-- we finally make replacment entries in the \"references\".    -->\n            <xsl:copy>\n                <!-- duplicate attributes on \"references\" -->\n                <xsl:apply-templates select=\"@*\" mode=\"assembly\"/>\n                <!-- duplicate/massage each bibliographic entry   -->\n                <!-- realize as a standard \"raw\" type reference,  -->\n                <!-- though make take this tyepe private some day -->\n                <xsl:for-each select=\"$the-references/pi:csl-biblio\">\n                    <biblio type=\"raw\">\n                        <!-- An @xml:id is likely present, but conceivably -->\n                        <!-- absent if a \"biblio\" is never referenced.     -->\n                        <!-- Preserve it through the process.              -->\n                        <xsl:copy-of select=\"@xml:id\"/>\n                        <!-- preserve numeric identification -->\n                        <xsl:attribute name=\"numeric\">\n                            <xsl:value-of select=\"@numeric\"/>\n                        </xsl:attribute>\n                        <xsl:apply-templates select=\"node()\" mode=\"assembly\"/>\n                    </biblio>\n                </xsl:for-each>\n            </xsl:copy>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"xref\" mode=\"assembly\">\n    <!-- determine if this \"xref\" points to a \"biblio\",  -->\n    <!-- and really just a backmatter/references/biblio, -->\n    <!-- plus using CSL styles for citations             -->\n    <xsl:variable name=\"is-biblio-target\">\n        <xsl:choose>\n            <!-- not doing styles, target is not of interest -->\n            <!-- to us anyway and we want to bail out as     -->\n            <!-- quickly and as easily as possible           -->\n            <xsl:when test=\"not($b-using-csl-styles)\">\n                <xsl:text>no</xsl:text>\n            </xsl:when>\n            <!-- first/last page-range device -->\n            <xsl:when test=\"@first\">\n                <xsl:text>no</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"@provisional\">\n                <xsl:text>no</xsl:text>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:variable name=\"tokenized-refs\" select=\"str:tokenize(@ref, ' ,')\"/>\n                <xsl:variable name=\"first-ref\">\n                    <xsl:value-of select=\"$tokenized-refs[1]\"/>\n                </xsl:variable>\n                <!-- The context \"xref\" sits in this pass's input tree, so -->\n                <!-- id() searches exactly the version in play             -->\n                <xsl:choose>\n                    <xsl:when test=\"id($first-ref)/self::biblio/parent::references/parent::backmatter\">\n                        <xsl:text>yes</xsl:text>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:text>no</xsl:text>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"b-is-biblio-target\" select=\"$is-biblio-target = 'yes'\"/>\n    <!--  -->\n    <xsl:choose>\n        <!-- duplicate for biblio extraction process or if the \"xref\"  -->\n        <!-- is not a candidate for replacement by a CSL citation      -->\n        <!-- Note: not using CSL styles immediately determines that    -->\n        <!-- this \"xrref\" is not a \"biblio target\" and a copy is       -->\n        <!-- made here, immediately as well                            -->\n        <xsl:when test=\"not($b-is-biblio-target) or $b-extracting-biblio\">\n            <xsl:copy>\n                <xsl:apply-templates select=\"node()|@*\" mode=\"assembly\"/>\n            </xsl:copy>\n        </xsl:when>\n        <!-- a candidate for replacement  -->\n        <xsl:otherwise>\n            <xsl:variable name=\"the-xref-id\">\n                <xsl:value-of select=\"@pi:original-id\"/>\n            </xsl:variable>\n            <xsl:variable name=\"matched-citation\" select=\"document('gen/references/csl-bibliography.xml', $original)/pi:csl-references/pi:csl-citation[@xml:id = $the-xref-id]\"/>\n            <xsl:copy-of select=\"$matched-citation\"/>\n            <!-- WARN ON UNMATCHED -->\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- We cosmetically change a \"drag-n-drop\" style matching problem from    -->\n<!-- being signaled by \"matches\" and instead call it a \"cardsort\" problem, -->\n<!-- which is a more accurate description of the interface from Runestoone -->\n<!-- Services.  We can't wait for \"repair\" since we do manipulation of     -->\n<!-- exercises in advance.  Why's that?  So an old WeBWorK server can send -->\n<!-- back old PreTeXt and have it be repaired.  So we do this change in an -->\n<!-- earlier pass.                                                         -->\n<xsl:template match=\"exercise/matches|project/matches|activity/matches|exploration/matches|investigation/matches|task/matches\" mode=\"assembly\">\n    <!-- literal element gets namespace declarations -->\n    <xsl:element name=\"cardsort\">\n        <xsl:apply-templates select=\"node()|@*\" mode=\"assembly\"/>\n    </xsl:element>\n</xsl:template>\n\n<!-- Ordering for static version of a cardsort exercise no longer goes   -->\n<!-- on the \"match\", due to the possibility of multiple \"premise\" inside -->\n<!-- the \"match\".  If the problem is an old-style 1-1 corrspondence, we  -->\n<!-- will move it onto *all* contained \"premise\", which will be fine if  -->\n<!-- there is one or less within the \"match\".  We allow for a recent     -->\n<!-- transition from \"matches\" to \"cardsort\".                            -->\n<xsl:template match=\"matches/match/@order|cardsort/match/@order\" mode=\"assembly\"/>\n\n<xsl:template match=\"matches/match/premise|cardsort/match/premise\" mode=\"assembly\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"@*\" mode=\"assembly\"/>\n        <xsl:if test=\"parent::match/@order\">\n            <xsl:attribute name=\"order\">\n                <xsl:value-of select=\"parent::match/@order\"/>\n            </xsl:attribute>\n        </xsl:if>\n        <xsl:apply-templates select=\"node()\" mode=\"assembly\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- WeBWorK @copy resolution -->\n\n<!-- A \"webwork\" with a @copy attribute is a lightweight reference  -->\n<!-- to another authored \"webwork\".  We resolve the copy here in    -->\n<!-- the assembly pass by pulling the target's content into a new   -->\n<!-- \"webwork\" element.                                             -->\n<xsl:template match=\"webwork[@copy]\" mode=\"assembly\">\n    <!-- Find the target.  Maybe. -->\n    <xsl:variable name=\"target\" select=\"id(@copy)\"/>\n    <!-- Trap potential pitfalls and record part of an error -->\n    <!-- message.  Use a non-empty error message as a signal -->\n    <!-- to bail out gracefully on the copy.                 -->\n    <xsl:variable name=\"error-message-for-copy\">\n        <xsl:choose>\n            <xsl:when test=\"not($target)\">\n                <xsl:text>the @copy attribute points to nothing, check the spelling?</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"not($target/self::webwork)\">\n                <xsl:text>the @copy attribute points to a \"</xsl:text>\n                <xsl:value-of select=\"local-name($target)\"/>\n                <xsl:text>\" element, not another \"webwork\".</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"$target/self::webwork[@source]\">\n                <xsl:text>the @copy attribute points a \"webwork\" with a @source attribute.  (Replace the @copy by the @source?)</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"$target/self::webwork[@copy]\">\n                <xsl:text>the @copy attribute points to \"webwork\" with a @copy attribute. Sorry, we are not that sophisticated.</xsl:text>\n            </xsl:when>\n            <!-- Presumably OK, no error message -->\n            <xsl:otherwise/>\n        </xsl:choose>\n    </xsl:variable>\n\n    <xsl:choose>\n        <!-- no error means to proceed with copy -->\n        <xsl:when test=\"$error-message-for-copy = ''\">\n            <xsl:copy>\n                <xsl:attribute name=\"pi:copied-from\">\n                    <xsl:value-of select=\"@copy\"/>\n                </xsl:attribute>\n                <!-- Duplicate attributes, but remove the @copy attribute -->\n                <!-- used as a signal here.  We don't want to copy this   -->\n                <!-- again after we have been to the WeBWorK server.      -->\n                <xsl:apply-templates select=\"@*[not(local-name(.) = 'copy')]\" mode=\"assembly\"/>\n                <!-- The @seed makes the problem different, and there are also  -->\n                <!-- unique identifiers, so grab any other attributes of the    -->\n                <!-- original, but exclude these while formulating a copy/clone. -->\n                <xsl:apply-templates select=\"$target/@*[(not(local-name(.) = 'id')) and\n                                                        (not(local-name(.) = 'label')) and\n                                                        (not(local-name(.) = 'seed'))]\" mode=\"assembly\"/>\n                <!-- NB: authored WeBWorK content never has @xml:id or @label, -->\n                <!-- so no scrubbing of unique IDs is needed here.             -->\n                <xsl:apply-templates select=\"$target/node()\" mode=\"assembly\"/>\n            </xsl:copy>\n        </xsl:when>\n        <!-- with an error in formulation, drop in something very -->\n        <!-- similar in gross form, and alert at the console      -->\n        <xsl:otherwise>\n            <xsl:copy>\n                <!-- Carry over as much metadata as possible -->\n                <xsl:apply-templates select=\"@*[not(local-name(.) = 'copy')]\" mode=\"assembly\"/>\n                <!-- Now a minimal, but correct PreTeXt, WeBWorK problem into the  -->\n                <!-- extraction machinery, and out into all possible final outputs  -->\n                <statement>\n                    <p>\n                        A WeBWorK problem right here was meant to be a copy of another problem,\n                        but potentially with different randomization, but there was a failure.\n                        The <c>@copy</c> attribute was set to <c><xsl:value-of select=\"@copy\"/></c>.\n                        Please report me, so the publisher can get more details by searching the\n                        runtime output for <q><c>PTX:ERROR</c></q>.\n                    </p>\n                </statement>\n            </xsl:copy>\n            <!-- minimalist report into source, more at console -->\n            <xsl:message>PTX:ERROR:   A WeBWorK problem has a @copy attribute with value \"<xsl:value-of select=\"@copy\"/>\".</xsl:message>\n            <xsl:message>             However, the problem did not render:</xsl:message>\n            <xsl:message><xsl:text>             </xsl:text><xsl:value-of select=\"$error-message-for-copy\"/></xsl:message>\n            <xsl:message>             A placeholder problem will appear in your output instead.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- ######### -->\n<!-- Exercises -->\n<!-- ######### -->\n\n<!-- Exercises, and their kin, are complicated.  They come in five types   -->\n<!-- (inline, divisional, reading, worksheet, project-like) based largely  -->\n<!-- on location.  They can be static, interactive in HTML, interactive    -->\n<!-- on a server.  Interactive versions come in many flavors, such as      -->\n<!-- short answer, multiple choice, true/false, Parson, cardsort, fill-in, -->\n<!-- and so on.  Their solutions (hint, answer, solution) apear, or do not -->\n<!-- appear, where born or in specialized \"solutions\" divisions.  We       -->\n<!-- scribble on each to record as much as we can right now.  It'll be     -->\n<!-- useful below and forever.                                             -->\n\n<!-- Record exercise ancestors/location-->\n<!-- An \"exercise\" can be in one of four places.  We reset the parameter   -->\n<!-- as we pass through.  Default is \"inline\" and we initialize with that  -->\n<!-- value.  These three specialized divisions are always terminal, so we  -->\n<!-- will never find an inline exercise contained within.  We allow        -->\n<!-- publisher customization of exercises based on these locations, *and*  -->\n<!-- for project-like.  These templates are just about divisions.          -->\n\n<xsl:template match=\"reading-questions\" mode=\"exercise\">\n    <xsl:param name=\"division\"/>\n\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"exercise\">\n            <xsl:with-param name=\"division\" select=\"'reading'\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<xsl:template match=\"worksheet\" mode=\"exercise\">\n    <xsl:param name=\"division\"/>\n\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"exercise\">\n            <xsl:with-param name=\"division\" select=\"'worksheet'\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<xsl:template match=\"exercises\" mode=\"exercise\">\n    <xsl:param name=\"division\"/>\n\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"exercise\">\n            <xsl:with-param name=\"division\" select=\"'divisional'\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<!-- Annotate \"exercise\" and PROJECT-LIKE -->\n<!-- Pre-processing here is entirely about supporting interactive       -->\n<!-- exercises powered by Runestone Services.  We allow publisher       -->\n<!-- options to control interactivity of \"short answer\" questions       -->\n<!-- when hosted on a server, so that is why locations are being noted. -->\n<!--   1.  \"exercise-customization\" refers to the situation where       -->\n<!--       certain publication options can vary behavior or visibility  -->\n<!--   2.  \"exercise-interactive\" refers to the type of                 -->\n<!--        interactivity, \"static\" is the default                      -->\n<!--                                                                    -->\n<!-- TODO:                                                              -->\n<!-- 1.  Expand to WW, example-like, and task                           -->\n<!-- 2.  Insert \"statement\" when not authored                           -->\n<!-- 3.  Use locations computed here, remove elsewhere                  -->\n<!-- 4.  Recognize new, modern fill-in problems                         -->\n\n<xsl:template match=\"exercise|&PROJECT-LIKE;|task\" mode=\"exercise\">\n    <xsl:param name=\"division\"/>\n\n    <xsl:copy>\n        <!-- Record one of five categories for customization, which    -->\n        <!-- are not relevant for \"example\" (always inline), or \"task\" -->\n        <!-- (always just a component of something larger).  WeBWorK   -->\n        <!-- problems are interactive or static, inline or not, based  -->\n        <!-- on publisher options.                                     -->\n        <xsl:if test=\"not(self::task)\">\n            <xsl:attribute name=\"pi:exercise-customization\">\n                <xsl:choose>\n                    <xsl:when test=\"&PROJECT-FILTER;\">\n                        <xsl:text>project</xsl:text>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:value-of select=\"$division\"/>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:attribute>\n        </xsl:if>\n        <!-- Determine and record types of interactivity -->\n        <xsl:apply-templates select=\".\" mode=\"exercise-interactive-attribute\"/>\n        <!-- catch remaining attributes -->\n        <xsl:apply-templates select=\"@*\" mode=\"exercise\">\n            <xsl:with-param name=\"division\" select=\"$division\"/>\n        </xsl:apply-templates>\n        <!-- Now the child elements -->\n        <!-- NB: this would be a place to insert a \"statement\" for  -->\n        <!-- \"exercise\", \"example\", \"project\" and \"task\", for which -->\n        <!-- an author has not needed/elected to use one.           -->\n        <xsl:apply-templates select=\"node()\" mode=\"exercise\">\n            <xsl:with-param name=\"division\" select=\"$division\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<!-- These \"interactivity types\" are meant for Runestone-enabled  -->\n<!-- interactive exercises and projects                           -->\n<xsl:template match=\"*\" mode=\"exercise-interactive-attribute\">\n    <xsl:attribute name=\"pi:exercise-interactive\">\n        <xsl:choose>\n            <!-- This is defensive, so statement//var below does not -->\n            <!-- match for WeBWorK.                                  -->\n            <xsl:when test=\"self::task and ancestor::webwork\">\n                <xsl:text>webwork-task</xsl:text>\n            </xsl:when>\n            <!-- WeBWorK exercises always retain \"webwork\" child     -->\n            <!-- through the pipeline.  Substitution from the        -->\n            <!-- representations file happens in the representations -->\n            <!-- pass, after exercise tagging.                       -->\n            <xsl:when test=\"webwork\">\n                <xsl:text>webwork</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"myopenmath\">\n                <xsl:text>myopenmath</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"stack\">\n                <xsl:text>stack</xsl:text>\n            </xsl:when>\n            <!-- @runestone was once used to signify a Runestone exercise given    -->\n            <!-- just by raw HTML.  The  @pi:exercise-interactive  value uses was, -->\n            <!-- appropriately, \"htmlhack\".  We now replace it with an old-time,   -->\n            <!-- static PreTeXt style (dumb) exercise.  Changing the value here    -->\n            <!-- is a quick way to nullify activity in later passes.   See below   -->\n            <!-- where the \"repair\" phase removes the  @runestone  attribute and   -->\n            <!-- creates the (dumb) exercise, in order to understand more fully.   -->\n            <!-- The commit with these changes might also help. (2025-11-04)       -->\n            <xsl:when test=\"@runestone\">\n                <xsl:text>static</xsl:text>\n            </xsl:when>\n            <!-- true/false -->\n            <xsl:when test=\"statement/@correct\">\n                <xsl:text>truefalse</xsl:text>\n            </xsl:when>\n            <!-- multiple choice -->\n            <xsl:when test=\"statement and choices\">\n                <xsl:text>multiplechoice</xsl:text>\n            </xsl:when>\n            <!-- vertical is default/traditional -->\n            <xsl:when test=\"statement and blocks and not(blocks/@layout = 'horizontal')\">\n                <xsl:text>parson</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"statement and blocks and (blocks/@layout = 'horizontal')\">\n                <xsl:text>parson-horizontal</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"statement and cardsort\">\n                <xsl:text>cardsort</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"statement and matching\">\n                <xsl:text>matching</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"statement and areas\">\n                <xsl:text>clickablearea</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"select\">\n                <xsl:text>select</xsl:text>\n            </xsl:when>\n            <!-- noted WeBWorK earlier, so this is Runestone fillin -->\n            <xsl:when test=\"statement//var\">\n                <xsl:text>fillin-basic</xsl:text>\n            </xsl:when>\n            <!-- new dynamic fillin goes here, perhaps:                     -->\n            <!-- statement//fillin[(@*|node()) and not(@characters|@fill)]? -->\n            <xsl:when test=\"statement//fillin and evaluation\">\n                <xsl:text>fillin</xsl:text>\n            </xsl:when>\n            <!-- only interactive programs make sense after a \"statement\" -->\n            <xsl:when test=\"statement and program[(@interactive = 'codelens') or (@interactive = 'activecode')]\">\n                <xsl:text>coding</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"dynamic and static\">\n                <xsl:text>dual</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"statement and response\">\n                <xsl:text>shortanswer</xsl:text>\n            </xsl:when>\n            <!-- That's it, we are out of opportunities to be interactive -->\n\n            <!-- A child that is a task indicates the exercise/project/task -->\n            <!-- that is its parent is simply a container, rather than a    -->\n            <!-- terminal task which would be structured with a \"statement\" -->\n            <!-- in order to be interactive                                 -->\n            <xsl:when test=\"task\">\n                <xsl:text>container</xsl:text>\n            </xsl:when>\n            <!-- Now we have what once would have been called a \"traditional\"     -->\n            <!-- PreTeXt question, which is just \"statement|hint|answer|solution\" -->\n            <!-- Or maybe just a bare statement that is not structured as such    -->\n            <xsl:otherwise>\n                <xsl:text>static</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:attribute>\n</xsl:template>\n\n<!-- Insert a default correct \"test\" for a FITB \"exercise\" or -->\n<!-- PROJECT-LIKE when an \"evaluate\" has no explicit correct  -->\n<!-- \"test\": the corresponding \"fillin\" has a static @answer, -->\n<!-- so synthesize a \"test\" and let all downstream processing -->\n<!-- follow a single code path.  Only @mode \"string\" and      -->\n<!-- \"number\" are handled here; \"math\" uses separate logic.   -->\n<xsl:template match=\"evaluation/evaluate[\n    not(@all = 'yes') and\n    not(test[@correct = 'yes']) and\n    not(\n        count(../../statement//fillin) > 1\n        and\n        ../evaluate[@all = 'yes']/test\n    )\n    ]\" mode=\"exercise\">\n    <xsl:param name=\"division\"/>\n\n    <!-- Identify this evaluate's position among its siblings and its name, -->\n    <!-- to locate the corresponding fillin by name first, position second. -->\n    <xsl:variable name=\"eval-position\" select=\"count(preceding-sibling::evaluate[not(@all='yes')]) + 1\"/>\n    <xsl:variable name=\"eval-name\" select=\"@name\"/>\n\n    <!-- Navigate to the exercise/project/task parent of evaluation -->\n    <xsl:variable name=\"exercise-parent\" select=\"parent::evaluation/parent::*\"/>\n\n    <!-- Find the corresponding fillin (name-based match takes priority) -->\n    <xsl:variable name=\"match-fillin\">\n        <xsl:choose>\n            <xsl:when test=\"$eval-name != '' and\n                            $exercise-parent/statement//fillin[@name = $eval-name]\">\n                <xsl:copy-of select=\"$exercise-parent/statement//fillin[@name = $eval-name]\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:copy-of select=\"($exercise-parent/statement//fillin)[$eval-position]\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"fillin\" select=\"exsl:node-set($match-fillin)/fillin\"/>\n\n    <xsl:copy>\n        <xsl:apply-templates select=\"@*\" mode=\"exercise\">\n            <xsl:with-param name=\"division\" select=\"$division\"/>\n        </xsl:apply-templates>\n        <!-- Synthesize a correct test when the fillin has a static @answer -->\n        <!-- and a recognized mode. Place it first so it takes precedence.  -->\n        <xsl:if test=\"$fillin/@answer and not($fillin/@ansobj)\">\n            <xsl:choose>\n                <xsl:when test=\"$fillin/@mode = 'number'\">\n                    <test correct=\"yes\">\n                        <numcmp use-answer=\"yes\"/>\n                    </test>\n                </xsl:when>\n                <xsl:when test=\"$fillin/@mode = 'string'\">\n                    <test correct=\"yes\">\n                        <strcmp use-answer=\"yes\"/>\n                    </test>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:WARNING: fillin in \"<xsl:value-of\n                        select=\"$exercise-parent/@pi:original-id\"/>\" has @answer but\n                        @mode is missing or not recognized (expected 'number' or\n                        'string'). No default correct test synthesized.</xsl:message>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:if>\n        <!-- Copy existing children (non-correct tests, feedback, etc.) -->\n        <xsl:apply-templates select=\"node()\" mode=\"exercise\">\n            <xsl:with-param name=\"division\" select=\"$division\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<!-- ##################################################### -->\n<!-- Dynamic Substitutions                                 -->\n<!-- Cut out dynamic setup and evaluation for static mode. -->\n<!-- NB: a new match in this mode must be reflected in the -->\n<!-- $b-has-dynamic-markup presence test gating the pass.  -->\n<!-- ##################################################### -->\n<xsl:template match=\"setup[de-object|setupScript]\" mode=\"dynamic-substitution\">\n    <xsl:if test=\"$exercise-style = 'dynamic'\">\n        <xsl:copy>\n            <xsl:apply-templates select=\"node()|@*\" mode=\"dynamic-substitution\"/>\n        </xsl:copy>\n    </xsl:if>\n</xsl:template>\n\n<xsl:template match=\"numcmp|strcmp|jscmp|mathcmp|logic[parent::test]\" mode=\"dynamic-substitution\">\n    <xsl:if test=\"$exercise-style = 'dynamic'\">\n        <xsl:copy>\n            <xsl:apply-templates select=\"node()|@*\" mode=\"dynamic-substitution\"/>\n        </xsl:copy>\n    </xsl:if>\n</xsl:template>\n\n<xsl:template match=\"fillin[@ansobj]\" mode=\"dynamic-substitution\">\n    <xsl:choose>\n        <xsl:when test=\"($exercise-style = 'static') and not($b-extracting)\">\n            <!-- The substitutions file is keyed by @pi:assembly-id, which      -->\n            <!-- extract-dynamic.xsl writes as the exercise_id.  This pass      -->\n            <!-- runs after the @pi:assembly-id stamp, so the owner carries it. -->\n            <xsl:variable name=\"owner\" select=\"ancestor::statement/..\"/>\n            <xsl:variable name=\"parent-id\">\n                <xsl:apply-templates select=\"$owner\" mode=\"assembly-id\"/>\n            </xsl:variable>\n            <xsl:variable name=\"eval-subs\" select=\"document($dynamic-substitutions-file,$original)\"/>\n            <xsl:variable name=\"object\" select=\"@ansobj\"/>\n            <xsl:variable name=\"recorded\" select=\"$eval-subs//dynamic-substitution[@id=$parent-id]/eval-subst[@obj=$object]\"/>\n            <!-- An answer is typeset as mathematics for the same modes that   -->\n            <!-- \"fillin-solution\" in  pretext-runestone-static.xsl  wraps in  -->\n            <!-- \"m\", so the two have to agree on which representation to use. -->\n            <xsl:variable name=\"substitution\">\n                <xsl:apply-templates select=\"$recorded\" mode=\"dynamic-representation\">\n                    <xsl:with-param name=\"b-latex\" select=\"(@mode = 'math') or (@mode = 'number')\"/>\n                </xsl:apply-templates>\n            </xsl:variable>\n            <xsl:copy>\n                <xsl:attribute name=\"answer\">\n                    <xsl:value-of select=\"$substitution\"/>\n                </xsl:attribute>\n                <xsl:apply-templates select=\"@*|node()\" mode=\"dynamic-substitution\"/>\n            </xsl:copy>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:copy>\n                <xsl:apply-templates select=\"node()|@*\" mode=\"dynamic-substitution\"/>\n            </xsl:copy>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"eval[@obj]\" mode=\"dynamic-substitution\">\n    <xsl:choose>\n        <!-- static, for multiple conversions, but primarily LaTeX -->\n        <xsl:when test=\"($exercise-style = 'static') and not($b-extracting)\">\n            <!-- The substitutions file is keyed by @pi:assembly-id, which      -->\n            <!-- extract-dynamic.xsl writes as the exercise_id.  This pass      -->\n            <!-- runs after the @pi:assembly-id stamp, so the owner carries it. -->\n            <xsl:variable name=\"owner\" select=\"(ancestor::statement|ancestor::solution|ancestor::evaluation)/..\"/>\n            <xsl:variable name=\"parent-id\">\n               <xsl:apply-templates select=\"$owner\" mode=\"assembly-id\"/>\n            </xsl:variable>\n            <xsl:variable name=\"eval-subs\" select=\"document($dynamic-substitutions-file,$original)\"/>\n            <xsl:variable name=\"object\" select=\"@obj\"/>\n            <xsl:variable name=\"recorded\" select=\"$eval-subs//dynamic-substitution[@id=$parent-id]/eval-subst[@obj=$object]\"/>\n            <!-- The value lands wherever the \"eval\" stood, so the surrounding  -->\n            <!-- markup decides which representation is wanted.  This is the    -->\n            <!-- same test the HTML version makes when it wraps a reference in  -->\n            <!-- \"toTeX\" in  pretext-runestone-fitb.xsl , and the two must      -->\n            <!-- agree.  \"md\" is included because its single-line form holds    -->\n            <!-- text directly, with no \"mrow\" for an ancestor step to find.    -->\n            <xsl:variable name=\"substitution\">\n                <xsl:apply-templates select=\"$recorded\" mode=\"dynamic-representation\">\n                    <xsl:with-param name=\"b-latex\" select=\"boolean(ancestor::m|ancestor::md|ancestor::mrow)\"/>\n                </xsl:apply-templates>\n            </xsl:variable>\n            <xsl:value-of select=\"$substitution\"/>\n        </xsl:when>\n        <!-- dynamic (aka HTML), needs static previews, server base64, etc, -->\n        <!-- so just copy as-is with \"webwork-reps\" to signal and organize  -->\n        <!-- to/for HTML conversion                                         -->\n        <xsl:otherwise>\n            <xsl:copy>\n                <xsl:apply-templates select=\"node()|@*\" mode=\"dynamic-substitution\"/>\n            </xsl:copy>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Pick a recorded substitution's representation.                       -->\n<!--                                                                      -->\n<!-- One generated object is routinely referenced more than once, and     -->\n<!-- not always in the same way: as the answer of a \"fillin\" and again    -->\n<!-- inside an \"m\" in the solution, say.  Those want different strings    -->\n<!-- from the same object, and the substitutions file is keyed only by    -->\n<!-- the object, so it cannot record which was meant.  Instead it records -->\n<!-- both, and the caller, which does know its own context, chooses.      -->\n<!--                                                                      -->\n<!-- Substitution files generated before this distinction existed hold    -->\n<!-- text and no children; that text is used for either request.          -->\n<xsl:template match=\"eval-subst\" mode=\"dynamic-representation\">\n    <xsl:param name=\"b-latex\" select=\"false()\"/>\n    <!-- Each representation is independent: a request for one never looks -->\n    <!-- at whether the other happens to be present.  A v1 substitution    -->\n    <!-- carries both children together, or neither (the legacy case,      -->\n    <!-- below), never just one, but the fallback is written per-child     -->\n    <!-- regardless, since that is the contract, not an assumption about   -->\n    <!-- which files exist.                                                -->\n    <xsl:choose>\n        <xsl:when test=\"$b-latex\">\n            <xsl:choose>\n                <xsl:when test=\"latex\">\n                    <xsl:value-of select=\"latex\"/>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:value-of select=\".\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:choose>\n                <xsl:when test=\"plain\">\n                    <xsl:value-of select=\"plain\"/>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:value-of select=\".\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- An #eval child of test is implicit mathcmp. -->\n<xsl:template match=\"test/eval[@obj]\" mode=\"dynamic-substitution\">\n    <xsl:choose>\n        <xsl:when test=\"$exercise-style = 'static'\">\n            <evaluation/>\n        </xsl:when>\n        <xsl:when test=\"$exercise-style = 'dynamic'\">\n            <xsl:copy>\n                <xsl:apply-templates select=\"node()|@*\" mode=\"dynamic-substitution\"/>\n            </xsl:copy>\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n<!-- ############### -->\n<!-- Representations -->\n<!-- ############### -->\n\n<!-- Build multiple (two) representations of exercises that are produced  -->\n<!-- in static (almost everything) and dynamic (HTML) versions.            -->\n<!-- Generally these templates are parameterized by the $exercise-style   -->\n<!-- variable/parameter.  We need the parameterization, since we do not   -->\n<!-- want to make *multiple* copies of each exercise in the source, since -->\n<!-- then duplicate items might confuse later templates e.g numbering).   -->\n<!--                                                                      -->\n<!-- A \"static\" version should be entirely in the style of a \"regular\"    -->\n<!-- PreTeXt exercise, having a statement|hint|answer|solution structure. -->\n<!-- Then it can be leveraged through all the infrastructure for things   -->\n<!-- like solutions manuals and non-capable output formats.               -->\n<!--                                                                      -->\n<!-- A \"dynamic\" version is simply a duplicate of the author's source,    -->\n<!-- which is handled by templates elsewhere, applied in the HTML         -->\n<!-- conversion itself.                                                   -->\n\n<!-- True/False        -->\n<!-- Multiple Choice   -->\n<!-- Parson problems   -->\n<!-- Cardsort problems -->\n<!-- Matching problems -->\n<!-- Clickable Area    -->\n<!-- ActiveCode        -->\n\n<!-- The pattern grammar does not permit variable references, so the      -->\n<!-- list of Runestone interactivity types is a literal, fenced string    -->\n<!-- repeated for each element that can carry one.  Match exactly         -->\n<!-- whenever  @pi:exercise-interactive  is one of the fenced values.     -->\n<!-- NB: also consulted in Runestone manifest creation.                   -->\n\n<xsl:template match=\"exercise[contains('|truefalse|multiplechoice|parson|parson-horizontal|cardsort|matching|clickablearea|fillin-basic|fillin|coding|shortanswer|', concat('|', @pi:exercise-interactive, '|'))]\n                   | project[contains('|truefalse|multiplechoice|parson|parson-horizontal|cardsort|matching|clickablearea|fillin-basic|fillin|coding|shortanswer|', concat('|', @pi:exercise-interactive, '|'))]\n                   | activity[contains('|truefalse|multiplechoice|parson|parson-horizontal|cardsort|matching|clickablearea|fillin-basic|fillin|coding|shortanswer|', concat('|', @pi:exercise-interactive, '|'))]\n                   | exploration[contains('|truefalse|multiplechoice|parson|parson-horizontal|cardsort|matching|clickablearea|fillin-basic|fillin|coding|shortanswer|', concat('|', @pi:exercise-interactive, '|'))]\n                   | investigation[contains('|truefalse|multiplechoice|parson|parson-horizontal|cardsort|matching|clickablearea|fillin-basic|fillin|coding|shortanswer|', concat('|', @pi:exercise-interactive, '|'))]\n                   | task[contains('|truefalse|multiplechoice|parson|parson-horizontal|cardsort|matching|clickablearea|fillin-basic|fillin|coding|shortanswer|', concat('|', @pi:exercise-interactive, '|'))]\" mode=\"representations\">\n    <!-- always preserve \"exercise/project\" container here, with attributes -->\n    <xsl:copy>\n        <xsl:apply-templates select=\"@*\" mode=\"representations\"/>\n        <xsl:choose>\n            <!-- make a static version, in a PreTeXt   -->\n            <!-- statement|hint|answer|solution style  -->\n            <!-- for use naturally by most conversions -->\n            <xsl:when test=\"$exercise-style = 'static'\">\n                <!-- overwrite classification as purely static now -->\n                <xsl:attribute name=\"pi:exercise-interactive\">\n                    <xsl:text>static</xsl:text>\n                </xsl:attribute>\n                <xsl:apply-templates select=\".\" mode=\"runestone-to-static\"/>\n            </xsl:when>\n            <!-- duplicate for a dynamic version -->\n            <xsl:when test=\"$exercise-style = 'dynamic'\">\n                <xsl:apply-templates select=\"node()\" mode=\"representations\"/>\n            </xsl:when>\n        </xsl:choose>\n    </xsl:copy>\n</xsl:template>\n\n<!-- A select question is only really capable on a Runestone server.  So when    -->\n<!-- assembling for dynamic exercises, and not hosting on Runestone, go instead  -->\n<!-- with the static version.  We have three scenarios, handled with variations. -->\n<!-- Note that these matches have been carved out from the above massive match.  -->\n<xsl:template match=\"exercise[(@pi:exercise-interactive = 'select')]\n                   | project[(@pi:exercise-interactive = 'select')]\n                   | activity[(@pi:exercise-interactive = 'select')]\n                   | exploration[(@pi:exercise-interactive = 'select')]\n                   | investigation[(@pi:exercise-interactive = 'select')]\n                   | task[(@pi:exercise-interactive = 'select')]\" mode=\"representations\">\n    <xsl:copy>\n        <xsl:choose>\n            <xsl:when test=\"($exercise-style = 'static')\">\n                <xsl:apply-templates select=\"@*\" mode=\"representations\"/>\n                <!-- overwrite classification as purely static now -->\n                <xsl:attribute name=\"pi:exercise-interactive\">\n                    <xsl:text>static</xsl:text>\n                </xsl:attribute>\n                <xsl:apply-templates select=\".\" mode=\"runestone-to-static\"/>\n            </xsl:when>\n            <!-- Use static version when making dynamic exercises *that are -->\n            <!-- not hosted on Runestone*.  Classify as now being 'static'. -->\n            <xsl:when test=\"($exercise-style = 'dynamic') and not($b-host-runestone)\">\n                <xsl:apply-templates select=\"@*\" mode=\"representations\"/>\n                <!-- overwrite classification as purely static now -->\n                <xsl:attribute name=\"pi:exercise-interactive\">\n                    <xsl:text>static</xsl:text>\n                </xsl:attribute>\n                <xsl:apply-templates select=\".\" mode=\"runestone-to-static\"/>\n            </xsl:when>\n            <!-- duplicate for a dynamic version -->\n            <xsl:when test=\"$exercise-style = 'dynamic'\">\n                <xsl:apply-templates select=\"@*\" mode=\"representations\"/>\n                <xsl:apply-templates select=\"node()\" mode=\"representations\"/>\n            </xsl:when>\n        </xsl:choose>\n    </xsl:copy>\n</xsl:template>\n\n<!-- dual copy (not copy-of) -->\n\n<xsl:template match=\"exercise[(@pi:exercise-interactive = 'dual')]\n                   | project[(@pi:exercise-interactive = 'dual')]\n                   | activity[(@pi:exercise-interactive = 'dual')]\n                   | exploration[(@pi:exercise-interactive = 'dual')]\n                   | investigation[(@pi:exercise-interactive = 'dual')]\n                   | task[(@pi:exercise-interactive = 'dual')]\" mode=\"representations\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"@*\" mode=\"representations\"/>\n        <xsl:choose>\n            <xsl:when test=\"($exercise-style = 'static')\">\n                <!-- make a \"static\" classification, over-writing a \"dual\" -->\n                <xsl:attribute name=\"pi:exercise-interactive\">\n                    <xsl:text>static</xsl:text>\n                </xsl:attribute>\n                <!-- copy overall title and idx, METADATA-FILTER feels too broad  -->\n                <xsl:apply-templates select=\"title|idx\" mode=\"representations\"/>\n                <xsl:apply-templates select=\"static/*\" mode=\"representations\"/>\n            </xsl:when>\n            <xsl:when test=\"($exercise-style = 'dynamic')\">\n                <!-- copy overall title and idx, METADATA-FILTER feels too broad  -->\n                <xsl:apply-templates select=\"title|idx\" mode=\"representations\"/>\n                <xsl:apply-templates select=\"dynamic/*\" mode=\"representations\"/>\n            </xsl:when>\n        </xsl:choose>\n    </xsl:copy>\n</xsl:template>\n\n\n<!-- Static (non-interactive)                                 -->\n<!-- @pi:exercise-interactive = 'static' needs no adjustments -->\n\n<!-- Mine webwork-reps for relevant application -->\n\n<!-- WeBWorK exercises retain a \"webwork\" child element through the    -->\n<!-- pipeline.  Here in the representations pass, we look up the       -->\n<!-- corresponding \"webwork-reps\" from the representations file using  -->\n<!-- the parent exercise's @pi:assembly-id, and substitute it in place -->\n<!-- of the \"webwork\" element.  We then split three ways, for PGML,    -->\n<!-- static, and dynamic (HTML) employment, via modal templates.       -->\n<!-- During extraction, the \"webwork\" child is left intact.            -->\n<!-- NB: including \"task\" though this may not be supported.            -->\n<xsl:template match=\"exercise[(@pi:exercise-interactive = 'webwork')]\n                   | project[(@pi:exercise-interactive = 'webwork')]\n                   | activity[(@pi:exercise-interactive = 'webwork')]\n                   | exploration[(@pi:exercise-interactive = 'webwork')]\n                   | investigation[(@pi:exercise-interactive = 'webwork')]\" mode=\"representations\">\n    <xsl:choose>\n        <!-- During extraction, pass through the exercise with its    -->\n        <!-- \"webwork\" child intact for the extraction stylesheet     -->\n        <!-- to process the authored content.                         -->\n        <xsl:when test=\"$b-extracting\">\n            <xsl:copy>\n                <xsl:apply-templates select=\"node()|@*\" mode=\"representations\"/>\n            </xsl:copy>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- Load the per-exercise representation file for this    -->\n            <!-- exercise, identified by its @pi:assembly-id.          -->\n            <xsl:variable name=\"webwork-rep-uri\"\n                select=\"concat($webwork-representations-dir, @pi:assembly-id, '.xml')\"/>\n            <xsl:variable name=\"the-webwork-rep\"\n                select=\"document($webwork-rep-uri, $original)/webwork-reps\"/>\n            <xsl:choose>\n                <!-- An empty string for $webwork-representations-dir, and       -->\n                <!-- the \"document()\" still succeeds (returns the source file?). -->\n                <!-- But this is hopeless. So just totally bail out repeatedly   -->\n                <!-- and leave the containing \"exercise\" hollow.                 -->\n                <xsl:when test=\"$webwork-representations-dir = ''\">\n                    <xsl:copy>\n                        <xsl:apply-templates select=\"node()|@*\" mode=\"representations\"/>\n                    </xsl:copy>\n                    <xsl:message>PTX:ERROR:   no WeBWorK representations directory configured in the publication file; WeBWorK exercise with @pi:assembly-id \"<xsl:value-of select=\"@pi:assembly-id\"/>\" will be empty.</xsl:message>\n                </xsl:when>\n                <!-- This should only fail if the file is missing or stale.  Repeatedly. -->\n                <xsl:when test=\"not($the-webwork-rep)\">\n                    <xsl:copy>\n                        <xsl:apply-templates select=\"node()|@*\" mode=\"representations\"/>\n                    </xsl:copy>\n                    <xsl:message>PTX:ERROR:   could not load WeBWorK representation file \"<xsl:value-of select=\"$webwork-rep-uri\"/>\" for @pi:assembly-id \"<xsl:value-of select=\"@pi:assembly-id\"/>\"; re-generate the WeBWorK representations.  A \"webwork-representations.xml\" in that directory indicates old-format files that need replacing.</xsl:message>\n                </xsl:when>\n                <xsl:otherwise>\n                    <!-- The representation file may record a server failure   -->\n                    <!-- from when the WeBWorK representations were generated. -->\n                    <!-- In that case the file holds a placeholder \"faux       -->\n                    <!-- problem\" (statement only) so assembly still proceeds, -->\n                    <!-- but warn the author so the failure does not go        -->\n                    <!-- unnoticed in later builds.                            -->\n                    <xsl:if test=\"$the-webwork-rep/static/@failure\">\n                        <xsl:message>PTX:WARNING:   the WeBWorK problem with @pi:assembly-id \"<xsl:value-of select=\"@pi:assembly-id\"/>\" has a stored \"<xsl:value-of select=\"$the-webwork-rep/static/@failure\"/>\" failure recorded when the WeBWorK representations were last generated.  A placeholder is being rendered in its place.  Re-generate the WeBWorK representations (and watch for errors) to retry.</xsl:message>\n                    </xsl:if>\n                    <!-- Build a temporary exercise with \"webwork-reps\" from the  -->\n                    <!-- representations file substituted in place of \"webwork\".   -->\n                    <!-- This preserves the parent-child relationship that         -->\n                    <!-- downstream templates rely on (e.g. \"../introduction\" in   -->\n                    <!-- webwork-rep-to-static navigates from webwork-reps up to   -->\n                    <!-- the exercise).                                            -->\n                    <xsl:variable name=\"exercise-with-reps-rtf\">\n                        <xsl:copy>\n                            <xsl:copy-of select=\"@*\"/>\n                            <xsl:for-each select=\"node()\">\n                                <xsl:choose>\n                                    <xsl:when test=\"self::webwork\">\n                                        <xsl:copy-of select=\"$the-webwork-rep\"/>\n                                    </xsl:when>\n                                    <xsl:otherwise>\n                                        <xsl:copy-of select=\".\"/>\n                                    </xsl:otherwise>\n                                </xsl:choose>\n                            </xsl:for-each>\n                        </xsl:copy>\n                    </xsl:variable>\n                    <xsl:variable name=\"exercise-with-reps\" select=\"exsl:node-set($exercise-with-reps-rtf)/*\"/>\n\n                    <xsl:choose>\n                        <!-- destined for creating problem sets, really just need PG code -->\n                        <xsl:when test=\"$exercise-style = 'pg-problems'\">\n                            <xsl:copy>\n                                <xsl:apply-templates select=\"@*\" mode=\"webwork-rep-to-pg\"/>\n                                <xsl:apply-templates select=\"title\" mode=\"webwork-rep-to-pg\"/>\n                                <xsl:apply-templates select=\"$exercise-with-reps/webwork-reps\" mode=\"webwork-rep-to-pg\"/>\n                            </xsl:copy>\n                        </xsl:when>\n                        <!-- static, for multiple conversions, but primarily LaTeX -->\n                        <xsl:when test=\"$exercise-style = 'static'\">\n                            <xsl:copy>\n                                <xsl:apply-templates select=\"@*\" mode=\"webwork-rep-to-static\"/>\n                                <xsl:attribute name=\"pi:exercise-interactive\">\n                                    <xsl:text>static</xsl:text>\n                                </xsl:attribute>\n                                <xsl:apply-templates select=\"$exercise-with-reps/node()\" mode=\"webwork-rep-to-static\"/>\n                            </xsl:copy>\n                        </xsl:when>\n                        <!-- dynamic (aka HTML), needs static previews, server base64, etc -->\n                        <xsl:otherwise>\n                            <xsl:copy>\n                                <xsl:apply-templates select=\"@*\" mode=\"webwork-rep-to-html\"/>\n                                <xsl:apply-templates select=\"$exercise-with-reps/node()\" mode=\"webwork-rep-to-html\"/>\n                            </xsl:copy>\n                        </xsl:otherwise>\n                    </xsl:choose>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Edit a \"webwork-reps\" from the server into just PG material -->\n<xsl:template match=\"node()|@*\" mode=\"webwork-rep-to-pg\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"webwork-rep-to-pg\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- Promote \"pg\" specific information to \"webwork-reps\" -->\n<xsl:template match=\"webwork-reps\" mode=\"webwork-rep-to-pg\">\n    <xsl:copy>\n        <!-- copy existing attributes -->\n        <xsl:apply-templates select=\"@*\" mode=\"webwork-rep-to-pg\"/>\n        <!-- promote \"pg\" attributes (@source, @copied-from) -->\n        <xsl:apply-templates select=\"pg/@*\" mode=\"webwork-rep-to-pg\"/>\n        <!-- attributes done, recurse into child *elements*  -->\n        <!-- no node() here, so drops interstial whitespace  -->\n        <!-- that accumulates into the textual PG code, even -->\n        <!-- if it does get sanitized in its use/application -->\n        <xsl:apply-templates select=\"*\" mode=\"webwork-rep-to-pg\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- Attributes preserved, drop \"pg\" element, duplicate the guts -->\n<!-- which should just be the actual PG version of the problem   -->\n<xsl:template match=\"webwork-reps/pg\" mode=\"webwork-rep-to-pg\">\n    <xsl:apply-templates select=\"node()\" mode=\"webwork-rep-to-pg\"/>\n</xsl:template>\n\n<!-- Drop \"webwork-reps\" children we don't need for problem sets -->\n<xsl:template match=\"webwork-reps/static\" mode=\"webwork-rep-to-pg\"/>\n<xsl:template match=\"webwork-reps/server-data\" mode=\"webwork-rep-to-pg\"/>\n\n\n<!-- Static from webwork-reps as a generic exercise  -->\n<!-- Edit a \"webwork-reps\" from the server into guts -->\n<!-- of a static exercise or PROJECT-LIKE            -->\n\n<!-- Kill author's lead-in/lead-out material on sight, we recreate -->\n<!-- their children with \"node()\" in main reorganization template  -->\n<xsl:template match=\"introduction[following-sibling::webwork-reps]\" mode=\"webwork-rep-to-static\"/>\n<xsl:template match=\"conclusion[preceding-sibling::webwork-reps]\" mode=\"webwork-rep-to-static\"/>\n\n<!-- Meld an author's \"introduction\" and \"conclusion\" into          -->\n<!-- (a) the similarly-named items of a task-structured object      -->\n<!-- (b) the statement of an object with a simpler structure        -->\n<!-- We recurse into (many, principal) selected components of       -->\n<!-- webwork-reps/static which effectively ignores  webwork-reps/pg -->\n<!-- and  webwork-reps/server  so these pieces never make it into   -->\n<!-- the assembled source.                                          -->\n<!--                                                                -->\n<!-- NB: we lose some attributes attached above to                  -->\n<!-- \"introduction\" and \"conclusion\" (not \"exercise\"), BUT          -->\n<!--   (i) we cannot point *into* a WW problem (no targets)         -->\n<!--   (ii) we do not have numbered items (eg Figure)               -->\n<!--   (iii) by removing them, we just disrupt any                  -->\n<!--         sequences, and uniqueness is preserved                 -->\n<!--   (iv) we could figure out which ones to copy where, if needed -->\n<!-- NB: a possible refactor here:                                  -->\n<!-- (i)  kill all the children of \"webwork-reps\", barring \"static\" -->\n<!--      (currently they are just ignored)                         -->\n<!-- (ii) rerwrite this template to have \"static\" as the context.   -->\n<!--      This would mean adjust some paths to go one more step up  -->\n<!--      to find things like \"introduction\".                       -->\n<!-- Consequence: when leveraged for HTML previews this rearrangment-->\n<!-- will be a big change.  Not clear if it is a desirable change.  -->\n<xsl:template match=\"webwork-reps\" mode=\"webwork-rep-to-static\">\n    <xsl:choose>\n        <!-- a WW \"staged\" exercise, may have an top-level introduction and -->\n        <!-- conclusion already, and does not have a top-level statement    -->\n        <xsl:when test=\"static/task\">\n            <xsl:if test=\".//introduction|static/introduction\">\n                <introduction>\n                    <xsl:apply-templates select=\"../introduction/node()\" mode=\"webwork-rep-to-static\"/>\n                    <xsl:apply-templates select=\"static/introduction/node()\" mode=\"webwork-rep-to-static\"/>\n                </introduction>\n            </xsl:if>\n            <xsl:apply-templates select=\"static/task\" mode=\"webwork-rep-to-static\"/>\n            <xsl:if test=\"../conclusion|static/conclusion\">\n                <conclusion>\n                    <xsl:apply-templates select=\"../conclusion/node()\" mode=\"webwork-rep-to-static\"/>\n                    <xsl:apply-templates select=\"static/conclusion/node()\" mode=\"webwork-rep-to-static\"/>\n                </conclusion>\n            </xsl:if>\n        </xsl:when>\n        <xsl:otherwise>\n            <statement>\n                <xsl:apply-templates select=\"../introduction/node()\" mode=\"webwork-rep-to-static\"/>\n                <xsl:apply-templates select=\"static/statement/node()\" mode=\"webwork-rep-to-static\"/>\n                <xsl:apply-templates select=\"../conclusion/node()\" mode=\"webwork-rep-to-static\"/>\n            </statement>\n            <xsl:apply-templates select=\"static/hint\" mode=\"webwork-rep-to-static\"/>\n            <xsl:apply-templates select=\"static/answer\" mode=\"webwork-rep-to-static\"/>\n            <xsl:apply-templates select=\"static/solution\" mode=\"webwork-rep-to-static\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Good time to clean-up what came back from a WW server.     -->\n<!-- As part of the \"webwork-rep-to-static\" mode, we can be     -->\n<!-- sure that only returns from the server are being adjusted. -->\n\n<!-- From the code comment when this was done with Python: \"p with -->\n<!-- only a single fillin, not counting those inside an li without -->\n<!-- preceding siblings\"                                           -->\n<!-- We likewise prune the \"p\" that only have a var with           -->\n<!-- @form=\"essay. These come from WeBWorK essay questions         -->\n<!-- starting with v2.19                                           -->\n<xsl:template match=\"p\" mode=\"webwork-rep-to-static\">\n    <!-- Substantially faster to have a simple match and then selectively -->\n    <!-- filter matched elements. Start with the tests that are cheapest  -->\n    <!-- and hope short-circuit evaluation avoids expensive ones.         -->\n    <xsl:variable name=\"prune\">\n        <xsl:if test=\"(count(fillin)=1 or count(var[@form='essay'])=1) and\n                      count(*)=1 and \n                      not(normalize-space(text())) and\n                      (not(parent::li) or preceding-sibling::*)\">\n            <xsl:value-of select=\"true()\"/>\n        </xsl:if>\n    </xsl:variable>\n    <xsl:if test=\"$prune != 'true'\">\n        <xsl:copy>\n            <xsl:apply-templates select=\"node()|@*\" mode=\"webwork-rep-to-static\"/>\n        </xsl:copy>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- Some answer forms return a default/initial choice that is -->\n<!-- simply a question-mark.  We scrub them here, with care.   -->\n<xsl:template match=\"statement//var[@form = 'popup']/li[(p[. = '?']) or (normalize-space(.) = '?')]\" mode=\"webwork-rep-to-static\"/>\n<xsl:template match=\"statement//ul[@form = 'popup']/li[(p[. = '?']) or (normalize-space(.) = '?')]\" mode=\"webwork-rep-to-static\"/>\n<!-- This may only be needed as support for older servers' generated PreTeXt. -->\n<xsl:template match=\"statement//var[@form = 'checkboxes']/li[(p[. = '?']) or (normalize-space(.) = '?')]\" mode=\"webwork-rep-to-static\"/>\n\n<!-- @form comes back from the server as a result of authored      -->\n<!-- \"answer forms\" and should be rendered as lists in static      -->\n<!-- representations.                                              -->\n<!-- NB: this does not preclude the match below (scrubbing default -->\n<!-- items) from functioning.                                      -->\n<xsl:template match=\"statement//ul[@form]|statement//var[@form]\" mode=\"webwork-rep-to-static\">\n    <ul>\n        <!-- duplicate attributes, but for @form -->\n        <xsl:apply-templates select=\"@*[not(name() = 'form')]\" mode=\"repair\"/>\n        <!-- internal attribute to indicate WW origins -->\n        <xsl:attribute name=\"pi:ww-form\">\n            <xsl:value-of select=\"@form\"/>\n        </xsl:attribute>\n        <!-- add a marker for an unordered list -->\n        <xsl:attribute name=\"marker\">\n            <xsl:choose>\n                <xsl:when test=\"@form = 'popup'\">\n                    <xsl:text>square</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"@form = 'buttons'\">\n                    <xsl:text>circle</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"@form = 'checkboxes'\">\n                    <xsl:text>square</xsl:text>\n                </xsl:when>\n            </xsl:choose>\n        </xsl:attribute>\n        <xsl:apply-templates select=\"node()\" mode=\"webwork-rep-to-static\"/>\n    </ul>\n</xsl:template>\n\n<xsl:template match=\"statement//ol[@form]\" mode=\"webwork-rep-to-static\">\n    <ol>\n        <!-- duplicate attributes, but for @form -->\n        <xsl:apply-templates select=\"@*[not(name() = 'form')]\" mode=\"repair\"/>\n        <!-- internal attribute to indicate WW origins -->\n        <xsl:attribute name=\"pi:ww-form\">\n            <xsl:value-of select=\"@form\"/>\n        </xsl:attribute>\n        <xsl:apply-templates select=\"node()\" mode=\"webwork-rep-to-static\"/>\n    </ol>\n</xsl:template>\n\n<xsl:template match=\"statement//dl[@form]\" mode=\"webwork-rep-to-static\">\n    <dl>\n        <!-- duplicate attributes, but for @form -->\n        <xsl:apply-templates select=\"@*[not(name() = 'form')]\" mode=\"repair\"/>\n        <!-- internal attribute to indicate WW origins -->\n        <xsl:attribute name=\"pi:ww-form\">\n            <xsl:value-of select=\"@form\"/>\n        </xsl:attribute>\n        <xsl:apply-templates select=\"node()\" mode=\"webwork-rep-to-static\"/>\n    </dl>\n</xsl:template>\n\n<!-- Default xeroxing template -->\n<xsl:template match=\"node()|@*\" mode=\"webwork-rep-to-static\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"webwork-rep-to-static\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- Edit a \"webwork-reps\" from the server into just HTML material -->\n\n<!-- We have a static version that gets employed in the HTML conversion -->\n<!-- as a \"preview\" before a reader hits an \"Activate\" button.  We are  -->\n<!-- leveraging the clean-up of static versions here.                   -->\n<!-- NB: for historical reasons, and so as to get a clean refactor, we  -->\n<!-- apply this modal template to \"static\" which is a level lower down  -->\n<!-- than its complete implementation, which starts at \"webwork-reps\".  -->\n<!-- This means that there is no rearrangement of the overall           -->\n<!-- \"introduction\" into the \"statement\".  But see the comments about a -->\n<!-- potential refactor of the \"webwork-rep-to-static\" templates.       -->\n<xsl:template match=\"static\" mode=\"webwork-rep-to-html\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"webwork-rep-to-static\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- Default xeroxing template -->\n<xsl:template match=\"node()|@*\" mode=\"webwork-rep-to-html\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"webwork-rep-to-html\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- MyOpenMath (MOM) to static -->\n\n<!-- Static versions come from a MOM server, and have been stored  -->\n<!-- as a \"generated\" component of a project.  We meld with a      -->\n<!-- PreTeXt introduction and conclusion, into a \"regular\" PreTeXt -->\n<!-- format, for any conversion to a static format to use.         -->\n<!-- NB: very similar to STACK template below                      -->\n<xsl:template match=\"exercise[(@pi:exercise-interactive = 'myopenmath')]\n                   | project[(@pi:exercise-interactive = 'myopenmath')]\n                   | activity[(@pi:exercise-interactive = 'myopenmath')]\n                   | exploration[(@pi:exercise-interactive = 'myopenmath')]\n                   | investigation[(@pi:exercise-interactive = 'myopenmath')]\" mode=\"representations\">\n    <!-- duplicate the exercise/project -->\n    <xsl:copy>\n        <!-- and preserve attributes on the exercise/project -->\n        <xsl:apply-templates select=\"@*\" mode=\"representations\"/>\n        <!-- Now bifurcate on static/dynamic.  PG problem creation should not fall in here. -->\n        <xsl:choose>\n            <xsl:when test=\"($exercise-style = 'static') and not($b-extracting)\">\n                <!-- overwrite classification as purely static now -->\n                <xsl:attribute name=\"pi:exercise-interactive\">\n                    <xsl:text>static</xsl:text>\n                </xsl:attribute>\n                <!-- locate the static representation in a file, generated independently -->\n                <!-- NB: this filename is relative to the author's source                -->\n                <xsl:variable name=\"filename\">\n                    <xsl:value-of select=\"$generated-directory-source\"/>\n                    <xsl:text>problems/mom-</xsl:text>\n                    <xsl:value-of select=\"myopenmath/@problem\"/>\n                    <xsl:text>.xml</xsl:text>\n                </xsl:variable>\n                <!-- \"myopenmath\" child guaranteed by @pi:exercise-interactive value -->\n                <xsl:variable name=\"mom-static-rep\" select=\"document($filename, $original)/myopenmath\"/>\n                <!-- duplicate metadata first -->\n                <xsl:apply-templates select=\"title|idx\" mode=\"representations\"/>\n                <!-- Meld PreTeXt introduction, conclusion with MOM statement. We could -->\n                <!-- duplicate MOM/statement attributes here, if there were any.        -->\n                <statement>\n                    <xsl:apply-templates select=\"introduction/node()\" mode=\"representations\"/>\n                    <xsl:apply-templates select=\"$mom-static-rep/statement/node()\" mode=\"representations\"/>\n                    <xsl:apply-templates select=\"conclusion/node()\" mode=\"representations\"/>\n                </statement>\n                <!-- these might not all be present, ever, but just to be safe -->\n                <xsl:apply-templates select=\"$mom-static-rep/hint\" mode=\"representations\"/>\n                <xsl:apply-templates select=\"$mom-static-rep/answer\" mode=\"representations\"/>\n                <xsl:apply-templates select=\"$mom-static-rep/solution\" mode=\"representations\"/>\n                <!-- NB: the \"myopenmath\" element has been ignored is now gone -->\n            </xsl:when>\n            <xsl:otherwise>\n                <!-- Duplicate authored content for the non-static conversions   -->\n                <!-- and let the conversions handle dynamic content.  Also, when -->\n                <!-- extracting MOM we need the authored source unmolested.      -->\n                <xsl:apply-templates select=\"node()\" mode=\"representations\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:copy>\n</xsl:template>\n\n<!-- STACK questions to static -->\n\n<!-- Static versions crom a STACK server, and have been stored     -->\n<!-- as a \"generated\" component of a project.  We meld with a      -->\n<!-- PreTeXt introduction and conclusion, into a \"regular\" PreTeXt -->\n<!-- format, for any conversion to a static format to use.         -->\n<!-- NB: very similar to MyOpenMath template above                 -->\n<xsl:template match=\"exercise[(@pi:exercise-interactive = 'stack')]\n                   | project[(@pi:exercise-interactive = 'stack')]\n                   | activity[(@pi:exercise-interactive = 'stack')]\n                   | exploration[(@pi:exercise-interactive = 'stack')]\n                   | investigation[(@pi:exercise-interactive = 'stack')]\" mode=\"representations\">\n    <!-- duplicate the exercise/project -->\n    <xsl:copy>\n        <!-- and preserve attributes on the exercise/project -->\n        <xsl:apply-templates select=\"@*\" mode=\"representations\"/>\n        <!-- Now bifurcate on static/dynamic.  PG problem creation should not fall in here. -->\n        <xsl:choose>\n            <xsl:when test=\"($exercise-style = 'static') and not($b-extracting)\">\n                <!-- overwrite classification as purely static now -->\n                <xsl:attribute name=\"pi:exercise-interactive\">\n                    <xsl:text>static</xsl:text>\n                </xsl:attribute>\n                <!-- locate the static representation in a file, generated independently -->\n                <!-- NB: this filename is relative to the author's source in \"generated\" -->\n                <xsl:variable name=\"filename\">\n                    <xsl:value-of select=\"$generated-directory-source\"/>\n                    <xsl:text>stack/</xsl:text>\n                    <xsl:apply-templates select=\"stack\" mode=\"assembly-id\"/>\n                    <xsl:text>.ptx</xsl:text>\n                </xsl:variable>\n                <xsl:variable name=\"stack-static-rep\" select=\"document($filename, $original)/stack-static\"/>\n                <!-- duplicate metadata first -->\n                <xsl:apply-templates select=\"title|idx\" mode=\"representations\"/>\n                <!-- Meld PreTeXt introduction, conclusion with STACK statement. We      -->\n                <!-- could duplicate stack/statement attributes here, if there were any. -->\n                <statement>\n                    <xsl:apply-templates select=\"introduction/node()\" mode=\"representations\"/>\n                    <xsl:apply-templates select=\"$stack-static-rep/statement/node()\" mode=\"representations\"/>\n                    <xsl:apply-templates select=\"conclusion/node()\" mode=\"representations\"/>\n                </statement>\n                <!-- these might not all be present, ever, but just to be safe -->\n                <xsl:apply-templates select=\"$stack-static-rep/hint\" mode=\"representations\"/>\n                <xsl:apply-templates select=\"$stack-static-rep/answer\" mode=\"representations\"/>\n                <xsl:apply-templates select=\"$stack-static-rep/solution\" mode=\"representations\"/>\n                <!-- NB: the \"stack\" element has been ignored is now gone -->\n            </xsl:when>\n            <xsl:otherwise>\n                <!-- Duplicate authored content for the non-static conversions   -->\n                <!-- and let the conversions handle dynamic content.  Also, when -->\n                <!-- extracting STACK we need the authored source unmolested.    -->\n                <xsl:apply-templates select=\"node()\" mode=\"representations\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:copy>\n</xsl:template>\n\n<!-- A \"program\" is \"made\" interactive by setting a value of the        -->\n<!-- @interactive attribute.  For static (incapable) formats, code      -->\n<!-- simply does not even consult the @interactive attribute.  By       -->\n<!-- explicitly dropping it here, we insure that even if we are         -->\n<!-- making HTML, but with static contents (e.g. EPUB), a \"program\"     -->\n<!-- will not get routed into templates that make Runestone components. -->\n<xsl:template match=\"program/@interactive\" mode=\"representations\">\n    <xsl:choose>\n        <!-- drop  @interactive  for static formats -->\n        <xsl:when test=\"$exercise-style = 'static'\"/>\n        <xsl:otherwise>\n            <xsl:copy/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"datafile|query\" mode=\"representations\">\n    <xsl:choose>\n        <!-- make a static version, in a PreTeXt style -->\n        <!-- for use naturally by most conversions     -->\n        <xsl:when test=\"$exercise-style = 'static'\">\n            <xsl:apply-templates select=\".\" mode=\"runestone-to-static\"/>\n        </xsl:when>\n        <!-- duplicate for a dynamic version -->\n        <xsl:when test=\"$exercise-style = 'dynamic'\">\n            <xsl:copy>\n                <xsl:apply-templates select=\"node()|@*\" mode=\"representations\"/>\n            </xsl:copy>\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Static versions of Audio, Video, Interactives -->\n\n<!-- Form a PreTeXt side-by-side with an image, a QR code and links -->\n\n<xsl:template match=\"audio|video|interactive[not(static)]\" mode=\"representations\">\n    <xsl:choose>\n        <xsl:when test=\"($exercise-style = 'static') and not($b-extracting)\">\n            <!-- Read pre-computed URLs from sidecar file -->\n            <!-- But not if doing an extraction           -->\n            <xsl:variable name=\"url-file\"\n                select=\"document(concat($generated-directory-source, 'qrcode/', @pi:assembly-id, '-url.xml'), $original)\"/>\n            <!-- panel widths are experimental -->\n            <sidebyside margins=\"7.5% 7.5%\" widths=\"47% 21%\" valign=\"top\" halign=\"center\">\n                <!-- copy over @xml:id, which may be in use by -->\n                <!-- page-breaking mechanism for LaTeX output  -->\n                <xsl:copy-of select=\"@xml:id\"/>\n                <!-- A @label could mask an authored @xml:id           -->\n                <!-- Note: this may be manufactured by an earlier pass -->\n                <xsl:copy-of select=\"@label\"/>\n                <xsl:choose>\n                    <!-- @preview present, so author provides a static image  -->\n                    <!--                                                      -->\n                    <!-- \"video\" is exceptional, we allow for a generic image -->\n                    <xsl:when test=\"self::video and (@preview = 'generic')\">\n                        <image>\n                            <xsl:attribute name=\"pi:generated\">\n                                <xsl:text>play-button/play-button.png</xsl:text>\n                            </xsl:attribute>\n                        </image>\n                    </xsl:when>\n                    <!--  -->\n                    <xsl:when test=\"@preview\">\n                        <image>\n                            <xsl:attribute name=\"source\">\n                                <xsl:value-of select=\"@preview\"/>\n                            </xsl:attribute>\n                        </image>\n                    </xsl:when>\n                    <!-- semi-automatic images vary by format     -->\n                    <!--                                          -->\n                    <!-- interactive: screenshots with playwright -->\n                    <!-- video: we scrape YouTube, only           -->\n                    <!--        YouTube playlist gets generic     -->\n                    <!-- audio: immature                          -->\n                    <xsl:when test=\"self::interactive\">\n                        <image>\n                            <xsl:attribute name=\"pi:generated\">\n                                <xsl:text>preview/</xsl:text>\n                                <xsl:apply-templates select=\".\" mode=\"assembly-id\"/>\n                                <xsl:text>-preview.png</xsl:text>\n                            </xsl:attribute>\n                        </image>\n                    </xsl:when>\n                    <!--  -->\n                    <xsl:when test=\"self::video and @youtube\">\n                        <image>\n                            <xsl:attribute name=\"pi:generated\">\n                                <xsl:text>youtube/</xsl:text>\n                                <xsl:apply-templates select=\".\" mode=\"assembly-id\"/>\n                                <xsl:text>.jpg</xsl:text>\n                            </xsl:attribute>\n                        </image>\n                    </xsl:when>\n                    <!--  -->\n                    <xsl:when test=\"self::video and @youtubeplaylist\">\n                        <image>\n                            <xsl:attribute name=\"pi:generated\">\n                                <xsl:text>play-button/play-button.png</xsl:text>\n                            </xsl:attribute>\n                        </image>\n                    </xsl:when>\n                    <!--  -->\n                    <xsl:when test=\"self::audio\">\n                        <p>No static image provided via <c>@preview</c> attribute</p>\n                    </xsl:when>\n                    <!--  -->\n                    <xsl:otherwise>\n                        <p>BUG: PREVIEW NOT HANDLED</p>\n                    </xsl:otherwise>\n                </xsl:choose>\n                <stack>\n                    <!-- 2023-02-07: wrapping in a URL failed    -->\n                    <!-- for a LaTeX build of the sample article -->\n                    <image>\n                        <xsl:attribute name=\"pi:generated\">\n                            <xsl:text>qrcode/</xsl:text>\n                            <xsl:apply-templates select=\".\" mode=\"assembly-id\"/>\n                            <xsl:text>.png</xsl:text>\n                        </xsl:attribute>\n                    </image>\n                    <!-- We kill the automatic footnotes, a debatable decision -->\n                    <!--  -->\n                    <xsl:variable name=\"standalone-url\">\n                        <xsl:value-of select=\"$url-file/pi:qrcode-urls/pi:standalone-url\"/>\n                    </xsl:variable>\n                    <xsl:if test=\"not($standalone-url = '')\">\n                        <p pi:indent=\"no\">\n                            <url href=\"{$standalone-url}\" visual=\"\">\n                                <pi:localize string-id=\"standalone\"/>\n                            </url>\n                        </p>\n                    </xsl:if>\n                    <!--  -->\n                    <xsl:variable name=\"context-url\">\n                        <xsl:value-of select=\"$url-file/pi:qrcode-urls/pi:context-url\"/>\n                    </xsl:variable>\n                    <xsl:if test=\"not($context-url = '')\">\n                        <p pi:indent=\"no\">\n                            <url href=\"{$context-url}\" visual=\"\">\n                                <pi:localize string-id=\"incontext\"/>\n                            </url>\n                        </p>\n                    </xsl:if>\n                    <!--  -->\n                    <xsl:variable name=\"embed-iframe-url\">\n                        <xsl:value-of select=\"$url-file/pi:qrcode-urls/pi:embed-iframe-url\"/>\n                    </xsl:variable>\n                    <xsl:if test=\"not($embed-iframe-url = '')\">\n                        <p pi:indent=\"no\">\n                            <!-- Kill the automatic footnote -->\n                            <url href=\"{$embed-iframe-url}\" visual=\"\">\n                                <pi:localize string-id=\"embed\"/>\n                            </url>\n                        </p>\n                    </xsl:if>\n                    <!--  -->\n                </stack>\n            </sidebyside>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- duplicate authored content for the non-static conversions and extractions-->\n            <xsl:copy>\n                <xsl:apply-templates select=\"node()|@*\" mode=\"representations\"/>\n            </xsl:copy>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- If a \"static\" is given, just copy it's children -->\n<xsl:template match=\"interactive[static]\" mode=\"representations\">\n    <xsl:choose>\n        <!-- duplicate the contents of an alternative \"static\" element -->\n        <xsl:when test=\"$exercise-style = 'static'\">\n            <xsl:apply-templates select=\"static\" mode=\"representations\"/>\n        </xsl:when>\n        <xsl:when test=\"($exercise-style = 'dynamic') or ($exercise-style = 'pg-problems')\">\n            <!-- duplicate authored content for the non-static conversions -->\n            <xsl:copy>\n                <xsl:apply-templates select=\"node()|@*\" mode=\"representations\"/>\n            </xsl:copy>\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n<!-- ############# -->\n<!-- Source Repair -->\n<!-- ############# -->\n\n<!-- We unilaterally make various changes to an author's source -->\n<!-- so a conversion (every conversion?) can assume more        -->\n<!-- accurately that the source has certain characteristics.    -->\n\n<!-- 2019-04-02  \"mathbook\" replaced by \"pretext\" -->\n<xsl:template match=\"/mathbook\" mode=\"repair\">\n    <pretext>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"repair\"/>\n    </pretext>\n</xsl:template>\n\n<!-- 2017-02-05  \"hyphen\" replaced by a bare hyphen.  Added 2026-06-25. -->\n<xsl:template match=\"hyphen\" mode=\"repair\">\n    <xsl:text>-</xsl:text>\n</xsl:template>\n\n<!-- 2017-07-18  \"@tex_size\" was renamed \"@tex-size\" (cosmetic), which in  -->\n<!-- turn became ignored (2017-11-09) in favor of a percentage \"@width\".   -->\n<!-- The legacy attribute now does nothing, so drop it.  Added 2026-06-25. -->\n<xsl:template match=\"@tex_size\" mode=\"repair\"/>\n\n<!-- 2017-07-25  \"autoname\" on \"xref\" deprecated in favor of \"text\".  -->\n<!-- Silently repair the legacy attribute to its modern functional    -->\n<!-- equivalent.  Every other attribute, and any content, is left to  -->\n<!-- the identity template, and so is preserved.  Added 2026-06-25.   -->\n<xsl:template match=\"xref/@autoname\" mode=\"repair\">\n    <xsl:attribute name=\"text\">\n        <xsl:choose>\n            <xsl:when test=\". = 'yes'\">\n                <xsl:text>type-global</xsl:text>\n            </xsl:when>\n            <xsl:when test=\". = 'no'\">\n                <xsl:text>global</xsl:text>\n            </xsl:when>\n            <xsl:when test=\". = 'title'\">\n                <xsl:text>title</xsl:text>\n            </xsl:when>\n        </xsl:choose>\n    </xsl:attribute>\n</xsl:template>\n\n<!-- 2017-12-07  \"@latexsep\" on \"c\"/\"cd\" is ignored; drop it.  Added 2026-06-25. -->\n<xsl:template match=\"c/@latexsep|cd/@latexsep\" mode=\"repair\"/>\n\n<!-- 2018-02-05  \"booktitle\" replaced by \"pubtitle\".  Added 2026-06-25. -->\n<xsl:template match=\"booktitle\" mode=\"repair\">\n    <pubtitle>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"repair\"/>\n    </pubtitle>\n</xsl:template>\n\n<!-- 2019-02-20  \"rename/@lang\" replaced by \"@xml:lang\".  Added 2026-06-25. -->\n<xsl:template match=\"rename/@lang\" mode=\"repair\">\n    <xsl:attribute name=\"xml:lang\">\n        <xsl:value-of select=\".\"/>\n    </xsl:attribute>\n</xsl:template>\n\n<!-- 2021-07-02 wrap notation/usage in \"m\" if not present -->\n<xsl:template match=\"notation/usage[not(m)]\" mode=\"repair\">\n    <!-- duplicate \"usage\" w/ attributes, insert \"m\" as repair -->\n    <usage>\n        <xsl:apply-templates select=\"@*\" mode=\"repair\"/>\n        <m>\n            <xsl:apply-templates select=\"node()|@*\" mode=\"repair\"/>\n        </m>\n    </usage>\n</xsl:template>\n\n<!-- 2021-10-04 \"glossary\" was finalized, so old-style preserved -->\n\n<!-- glossary introductions become headnotes -->\n<xsl:template match=\"glossary/introduction\" mode=\"repair\">\n    <headnote>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"repair\"/>\n    </headnote>\n</xsl:template>\n\n<!-- \"terms\" only ever had \"defined-term\" as children    -->\n<!-- and is now obsolete, so dropped as excess structure -->\n<xsl:template match=\"glossary/terms\" mode=\"repair\">\n    <xsl:apply-templates select=\"defined-term\" mode=\"repair\"/>\n</xsl:template>\n\n<!-- \"defined-term\" was structured, so we just select elements -->\n<xsl:template match=\"glossary/terms/defined-term\" mode=\"repair\">\n    <gi>\n        <xsl:apply-templates select=\"*|@*\" mode=\"repair\"/>\n    </gi>\n</xsl:template>\n\n<!-- no more \"conclusion\", so drop it here; deprecation will warn -->\n<xsl:template match=\"glossary/conclusion\" mode=\"repair\"/>\n\n<!-- 2022-04-22 replace Python Tutor with Runestone CodeLens -->\n<xsl:template match=\"program/@interactive\" mode=\"repair\">\n    <xsl:choose>\n        <xsl:when test=\". = 'pythontutor'\">\n            <xsl:attribute name=\"interactive\">\n                <xsl:text>codelens</xsl:text>\n            </xsl:attribute>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:copy/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- 2022-04-25 @label deprecated, slated for renewal in starring  -->\n<!-- role. Lists with markers (not description lists) -->\n<xsl:template match=\"ol/@label|ul/@label\" mode=\"repair\">\n    <xsl:attribute name=\"marker\">\n        <xsl:value-of select=\".\"/>\n    </xsl:attribute>\n</xsl:template>\n\n<!-- 2022-04-24 An exception, label on video tracks mimicing HTML -->\n<xsl:template match=\"video/track/@label\" mode=\"repair\">\n    <xsl:attribute name=\"listing\">\n        <xsl:value-of select=\".\"/>\n    </xsl:attribute>\n</xsl:template>\n\n<!-- 2022-06-09 WeBWorK \"stage\" deprecated in favor of \"task\"       -->\n<!-- We could use  match=\"webwork/stage\"  but then this would only  -->\n<!-- happen to the author's source while being prepared for the     -->\n<!-- \"extract-pg.xsl\" worksheet.  But we also want to catch \"stage\" -->\n<!-- coming back from an old WeBWorK server, which may be various   -->\n<!-- places after we algorithmically manipulate the \"webwork-reps\"  -->\n<!-- structure.  Instead, we just wait until now.  If necessary,    -->\n<!-- perhaps \"exercise/stage\" for the post-server pass.             -->\n<xsl:template match=\"stage\" mode=\"repair\">\n    <task>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"repair\"/>\n    </task>\n</xsl:template>\n\n<!-- 2022-07-10 webwork//latex-image[syntax='PGtikz'] deprecated    -->\n<!-- to just a normal latex-image. The text content for the code    -->\n<!-- must be wrapped in a tikzpicture environment.                  -->\n<xsl:template match=\"latex-image[@syntax='PGtikz']\" mode=\"repair\">\n    <xsl:copy>\n        <!-- we drop the @syntax attribute -->\n        <xsl:apply-templates select=\"node()|@*[not(local-name(.) = 'syntax')]\" mode=\"repair\"/>\n    </xsl:copy>\n</xsl:template>\n<xsl:template match=\"latex-image[@syntax='PGtikz']/text()\" mode=\"repair\">\n    <xsl:text>\\begin{tikzpicture}&#xa;</xsl:text>\n    <xsl:call-template name=\"sanitize-latex\">\n        <xsl:with-param name=\"text\">\n            <xsl:copy>\n                <xsl:apply-templates select=\".\"/>\n            </xsl:copy>\n        </xsl:with-param>\n    </xsl:call-template>\n    <xsl:text>&#xa;\\end{tikzpicture}&#xa;</xsl:text>\n</xsl:template>\n\n<!-- Deprecated 2018-12-30 in favor of \"ca\"   -->\n<!-- Copy attributes...because you never know -->\n<xsl:template match=\"circa\" mode=\"repair\">\n    <ca>\n        <xsl:apply-templates select=\"@*\" mode=\"repair\"/>\n    </ca>\n</xsl:template>\n\n<!-- Due to naivete, we had empty templates for \"keyboard characters\"    -->\n<!-- we did not have the skills to handle.  A good example was <dollar/> -->\n<!-- simply because it is a (very) special character in LaTeX.  These    -->\n<!-- were deprecated on 2019-02-06.  Beginning in 2022-12-26, we are     -->\n<!-- providing fixes here, and removing all the (dead) code meant for    -->\n<!-- backward compatibility.                                             -->\n\n<!-- XML characters -->\n\n<xsl:template match=\"less\" mode=\"repair\">\n    <xsl:text>&lt;</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"greater\" mode=\"repair\">\n    <xsl:text>&gt;</xsl:text>\n</xsl:template>\n\n<!-- Ten LaTeX characters -->\n<!-- # $ % ^ & _ { } ~ \\  -->\n\n<xsl:template match=\"hash\" mode=\"repair\">\n    <xsl:text>#</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"ampersand\" mode=\"repair\">\n    <xsl:text>&amp;</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"dollar\" mode=\"repair\">\n    <xsl:text>$</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"percent\" mode=\"repair\">\n    <xsl:text>%</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"circumflex\" mode=\"repair\">\n    <xsl:text>^</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"underscore\" mode=\"repair\">\n    <xsl:text>_</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"lbrace\" mode=\"repair\">\n    <xsl:text>{</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"rbrace\" mode=\"repair\">\n    <xsl:text>}</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"tilde\" mode=\"repair\">\n    <xsl:text>~</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"backslash\" mode=\"repair\">\n    <xsl:text>\\</xsl:text>\n</xsl:template>\n\n<!-- Lesser keyboard characters -->\n<!-- [, ], *, /, `,             -->\n\n<xsl:template match=\"lbracket\" mode=\"repair\">\n    <xsl:text>[</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"rbracket\" mode=\"repair\">\n    <xsl:text>]</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"asterisk\" mode=\"repair\">\n    <xsl:text>*</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"slash\" mode=\"repair\">\n    <xsl:text>/</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"backtick\" mode=\"repair\">\n    <xsl:text>`</xsl:text>\n</xsl:template>\n\n<!-- Grouping constructions  -->\n<!-- \"braces\" and \"brackets\" -->\n\n<xsl:template match=\"braces\" mode=\"repair\">\n    <xsl:text>{</xsl:text>\n    <!-- attributes will be lost -->\n    <xsl:apply-templates select=\"node()\" mode=\"repair\"/>\n    <xsl:text>}</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"brackets\" mode=\"repair\">\n    <xsl:text>[</xsl:text>\n    <!-- attributes will be lost -->\n    <xsl:apply-templates select=\"node()\" mode=\"repair\"/>\n    <xsl:text>]</xsl:text>\n</xsl:template>\n\n<!-- 2023-01-27: deprecate \"datafile\" to make way for a better    -->\n<!-- Runestone-powered version.  Cosmetic replacement: \"dataurl\". -->\n<!-- 2023-01-30: refine deprecation repair just after a minor CLI -->\n<!-- release. A \"datafile\" element may be OK as a \"new\" use,      -->\n<!-- with the presence of @label indicating use/application with  -->\n<!-- Runestone Javascript.  So only automatically upgrade \"old\"   -->\n<!-- uses lacking @label.                                         -->\n<xsl:template match=\"datafile[not(@label)]\" mode=\"repair\">\n    <dataurl>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"repair\"/>\n    </dataurl>\n</xsl:template>\n\n<xsl:template match=\"colophon/website[address]\" mode=\"repair\">\n    <website>\n        <xsl:apply-templates select=\"@*\" mode=\"repair\"/>\n        <url>\n            <xsl:attribute name=\"href\">\n                <xsl:value-of select=\"address\"/>\n            </xsl:attribute>\n            <xsl:apply-templates select=\"name/node()\" mode=\"repair\"/>\n        </url>\n    </website>\n</xsl:template>\n\n<!-- 2023-08-28: deprecate the \"console\" \"prompt\" element -->\n\n<!-- Removing this entire line typically orphans a text node    -->\n<!-- just prior with a newline and indentation, but this should -->\n<!-- not harm subsequent processing since we do not assume      -->\n<!-- source is carefully authored as one element per line.      -->\n<xsl:template match=\"console/prompt\" mode=\"repair\"/>\n\n<!-- If there was a \"prompt\" element just preceding an \"input\"      -->\n<!-- element, then we reach up and grab it and make it an attribute -->\n<!-- of the \"input\" - but not if somebody happened to already start -->\n<!-- using a @prompt attribute.                                     -->\n<!-- https://www.oxygenxml.com/archives/xsl-list/199910/msg00541.html -->\n<xsl:template match=\"console/input\" mode=\"repair\">\n    <xsl:copy>\n        <xsl:if test=\"not(@prompt) and preceding-sibling::*[1][self::prompt]\">\n            <xsl:attribute name=\"prompt\">\n                <xsl:value-of select=\"preceding-sibling::*[1][self::prompt]\"/>\n            </xsl:attribute>\n        </xsl:if>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"repair\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- 2023-09-07: move \"description\" to \"shortdescription\" -->\n<!-- 2026-06-26: support this move for \"description\" inside \"interactive\" -->\n<xsl:template match=\"image/description[not(*[not(self::var)])]|interactive/description[not(*[not(self::var)])]\" mode=\"repair\">\n    <xsl:element name=\"shortdescription\" namespace=\"\">\n        <xsl:apply-templates select=\"node()|@*\" mode=\"repair\"/>\n    </xsl:element>\n</xsl:template>\n\n<!-- 2023-10-17: docinfo/latex-preamble is history -->\n\n<xsl:template match=\"docinfo/latex-preamble\" mode=\"repair\">\n    <!-- any attributes (no such thing?) are simply  -->\n    <!-- orphaned and we just process child elements -->\n    <xsl:apply-templates select=\"node()\" mode=\"repair\"/>\n</xsl:template>\n\n<!-- 2023-10-17: and \"extra\" LaTeX packages are re-worked -->\n\n<xsl:template match=\"docinfo/latex-preamble/package\" mode=\"repair\">\n    <xsl:element name=\"math-package\">\n        <xsl:attribute name=\"latex-name\">\n            <xsl:value-of select=\".\"/>\n        </xsl:attribute>\n        <xsl:attribute name=\"mathjax-name\">\n            <xsl:value-of select=\".\"/>\n        </xsl:attribute>\n    </xsl:element>\n</xsl:template>\n\n<!-- 2026-07-30: authored-attribute defaults gather under \"defaults\" -->\n\n<!-- A \"programs\", \"parsons\", or \"cross-references\" element, as   -->\n<!-- a child of \"docinfo\", moves inside a \"defaults\" element.     -->\n<!-- The first of the trio present builds the container for all,  -->\n<!-- and the same match then suppresses the others.  The retired  -->\n<!-- \"cross-references\" element is renamed \"xrefs\" on the way in. -->\n<xsl:template match=\"docinfo/programs | docinfo/parsons | docinfo/cross-references\" mode=\"repair\">\n    <xsl:if test=\"count(preceding-sibling::programs | preceding-sibling::parsons | preceding-sibling::cross-references) = 0\">\n        <xsl:element name=\"defaults\">\n            <xsl:for-each select=\"../programs | ../parsons | ../cross-references\">\n                <xsl:choose>\n                    <xsl:when test=\"self::cross-references\">\n                        <xsl:element name=\"xrefs\">\n                            <xsl:copy-of select=\"@*\"/>\n                        </xsl:element>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:copy>\n                            <xsl:copy-of select=\"@*\"/>\n                        </xsl:copy>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:for-each>\n        </xsl:element>\n    </xsl:if>\n</xsl:template>\n\n<!-- The old \"image-width\" element, whose content was the width,  -->\n<!-- becomes a \"width\" attribute on an \"images\" element.          -->\n<xsl:template match=\"docinfo/defaults/image-width\" mode=\"repair\">\n    <xsl:element name=\"images\">\n        <xsl:attribute name=\"width\">\n            <xsl:value-of select=\"normalize-space(.)\"/>\n        </xsl:attribute>\n    </xsl:element>\n</xsl:template>\n\n<!-- 2026-07-31: a footnote within a \"tabular\" cell becomes a \"tn\" -->\n<!-- table note, lettered and placed at the bottom of the table    -->\n<!-- (Notes to tables: CMoS 18th ed., 3.77-3.81; specific notes    -->\n<!-- at 3.80).  Any identification attributes are orphaned: a      -->\n<!-- \"tn\" is not a cross-reference target.                         -->\n<xsl:template match=\"tabular//fn\" mode=\"repair\">\n    <tn>\n        <xsl:apply-templates select=\"node()\" mode=\"repair\"/>\n    </tn>\n</xsl:template>\n\n<!-- A \"tn\" authored as a block sibling of a cell's paragraphs is -->\n<!-- relocated to the tail of the paragraph it follows, where its -->\n<!-- mark belongs typographically; conversions then treat every   -->\n<!-- \"tn\" as inline.  A \"tn\" amid the mixed text of a cell is     -->\n<!-- already inline, and is untouched.                            -->\n<xsl:template match=\"cell[p]/tn\" mode=\"repair\"/>\n\n<xsl:template match=\"cell/p\" mode=\"repair\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"@*|node()\" mode=\"repair\"/>\n        <xsl:apply-templates select=\"following-sibling::tn[count(preceding-sibling::p[1] | current()) = 1]\" mode=\"tn-relocate\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- A faithful copy, since the \"repair\" mode on the same   -->\n<!-- element is its suppression at the original location.   -->\n<xsl:template match=\"cell/tn\" mode=\"tn-relocate\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"@*|node()\" mode=\"repair\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- 2026-07-30: an \"event\" is bibliographic content, so it -->\n<!-- belongs in \"bibinfo\", already its home for slideshows. -->\n<!-- Suppressed at its origin within \"docinfo\"...           -->\n<xsl:template match=\"docinfo/event\" mode=\"repair\"/>\n\n<!-- ...and lands in an authored \"bibinfo\" without its own. -->\n<xsl:template match=\"frontmatter/bibinfo[not(event)]\" mode=\"repair\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"@*\" mode=\"repair\"/>\n        <xsl:apply-templates select=\"node()\" mode=\"repair\"/>\n        <xsl:apply-templates select=\"/*/docinfo/event\" mode=\"event-relocate\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- A faithful copy, since the \"repair\" mode on the same   -->\n<!-- element is its suppression at the original location.   -->\n<xsl:template match=\"docinfo/event\" mode=\"event-relocate\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"@*\" mode=\"repair\"/>\n        <xsl:apply-templates select=\"node()\" mode=\"repair\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- 2024-10-29: program is reworked -->\n\n<!-- Add code element around text in program when missing -->\n<xsl:template match=\"program[not(input|code)]\" mode=\"repair\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"@*\" mode=\"repair\"/>\n        <code>\n            <xsl:value-of select=\"text()\"/>\n        </code>\n    </xsl:copy>\n</xsl:template>\n\n<xsl:template match=\"program[not(code)]/input\" mode=\"repair\">\n    <xsl:element name=\"code\">\n        <xsl:apply-templates select=\"node()|@*\" mode=\"repair\"/>\n    </xsl:element>\n</xsl:template>\n\n<!-- Index deprecations -->\n<!-- The way an index was constructed changed in 2017-07-14.  At 2024-08-08  -->\n<!-- we are using the \"repair\" phase to move the old style to the new.  The  -->\n<!-- old style looked like a \"index-part\" division with a mandatory          -->\n<!-- \"index-list\" child.  Elements sprinkled into the text were an           -->\n<!-- unstructured \"index\" or an \"index\" with up to three headings: \"main\",   -->\n<!-- followed by possibly two \"sub\".  Now the division is \"index\" (as it     -->\n<!-- should be!) and the entries are \"idx\".  A structured \"idx\" can have     -->\n<!-- one to three \"h\" elements as the headings.                              -->\n\n<!-- Change the division element -->\n<xsl:template match=\"index-part\" mode=\"repair\">\n    <index>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"repair\"/>\n    </index>\n</xsl:template>\n\n<!-- Change tne entry element, but avoid a new division name -->\n<xsl:template match=\"index[not(index-list)]\" mode=\"repair\">\n    <idx>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"repair\"/>\n    </idx>\n</xsl:template>\n\n<!-- Change first old style heading -->\n<xsl:template match=\"index[not(index-list)]/main\" mode=\"repair\">\n    <h>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"repair\"/>\n    </h>\n</xsl:template>\n\n<!-- Change second and third old style headings -->\n<xsl:template match=\"index[not(index-list)]/sub\" mode=\"repair\">\n    <h>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"repair\"/>\n    </h>\n</xsl:template>\n\n<!-- Frontmatter repairs -->\n<!-- 2024-10-10: we will no longer require an author to decide  -->\n<!-- which frontmatter elements belong on a titlepage or in the -->\n<!-- front colophon.  All the elements from both titlepage and  -->\n<!-- colophon should now go in bibinfo. We run repair whenever  -->\n<!-- the author has an existing titlepage or colophon without   -->\n<!-- the new titlepage-items or colophon-items children.        -->\n<xsl:template match=\"frontmatter[titlepage[not(titlepage-items)] or colophon[not(colophon-items)]]\" mode=\"repair\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"@*\" mode=\"repair\"/>\n        <bibinfo>\n            <!-- Include deprecated children of titlepage and colophon -->\n            <xsl:apply-templates select=\"titlepage/author\" mode=\"repair\"/>\n            <xsl:apply-templates select=\"titlepage/editor\" mode=\"repair\"/>\n            <xsl:apply-templates select=\"titlepage/credit\" mode=\"repair\"/>\n            <xsl:apply-templates select=\"titlepage/date\" mode=\"repair\"/>\n            <!-- for slides, we allowed an \"event\" -->\n            <xsl:apply-templates select=\"titlepage/event\" mode=\"repair\"/>\n            <!-- 2026-07-30: an \"event\" may also arrive from \"docinfo\" -->\n            <xsl:apply-templates select=\"/*/docinfo/event[not(current()/titlepage/event)]\" mode=\"event-relocate\"/>\n            <xsl:apply-templates select=\"colophon/credit\" mode=\"repair\"/>\n            <xsl:apply-templates select=\"colophon/edition\" mode=\"repair\"/>\n            <xsl:apply-templates select=\"colophon/website\" mode=\"repair\"/>\n            <xsl:apply-templates select=\"colophon/copyright\" mode=\"repair\"/>\n        </bibinfo>\n        <!-- We (pretty much) duplicate everything, except two templates -->\n        <!-- below hollow-out old-style \"titlepage\" and \"colophon\" to    -->\n        <!-- match the new style with generators.                        -->\n        <xsl:apply-templates select=\"node()\" mode=\"repair\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- We repair a \"titlepage\" that is not in the new style using a text   -->\n<!-- generator.  The \"titlepage\" is structural and the empty text        -->\n<!-- generator will be implemented in conversions to do the right thing. -->\n<xsl:template match=\"titlepage[not(titlepage-items)]\" mode=\"repair\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"@*\" mode=\"repair\"/>\n        <titlepage-items/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- We repair a front \"colophon\" that is not in the new style using a   -->\n<!-- text generator.  The \"colophon\" is structural and the empty text    -->\n<!-- generator will be implemented in conversions to do the right thing. -->\n<!-- NB: \"frontmatter\" is necessary so we don't clobber a BACK colophon! -->\n<xsl:template match=\"frontmatter/colophon[not(colophon-items)]\" mode=\"repair\">\n    <xsl:copy>\n        <xsl:choose>\n            <!-- Keep authored xml:id or label -->\n            <xsl:when test=\"@xml:id|@label\">\n                <xsl:apply-templates select=\"@xml:id|@label\" mode=\"repair\"/>\n            </xsl:when>\n            <!-- Otherwise, use the label \"front-colophon\" -->\n            <xsl:otherwise>\n                <xsl:attribute name=\"label\">\n                    <xsl:text>front-colophon</xsl:text>\n                </xsl:attribute>\n            </xsl:otherwise>\n        </xsl:choose>\n        <!-- Include the colophon-items generator -->\n        <colophon-items/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- We allow an author/editor/contributor to have their affiliation information not -->\n<!-- wrapped in affiliation tags, but in that case we put them in affiliation tags.  -->\n<xsl:template match=\"frontmatter//author[not(affiliation)]|frontmatter//editor[not(affiliation)]|frontmatter//contributor[not(affiliation)]\" mode=\"repair\">\n    <xsl:copy>\n        <!-- Include \"personname\" first -->\n        <xsl:apply-templates select=\"personname|@*\" mode=\"repair\"/>\n        <!-- If there are bare position/department/institution/address, wrap them in affiliation -->\n        <xsl:if test=\"position or department or institution or location\">\n            <affiliation>\n                <xsl:apply-templates select=\"position|department|institution|location\" mode=\"repair\"/>\n            </affiliation>\n        </xsl:if>\n        <!-- Include all additional elements as they are -->\n        <xsl:apply-templates select=\"*[not(self::personname or self::position or self::department or self::institution or self::location)]\" mode=\"repair\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- 2025-03-08:  \"commentary\" is deprecated.  Authors should remove it, -->\n<!-- but we have suggested that it could be used with version support.   -->\n<!-- So, if extant here in the repair phase, then it must have had a     -->\n<!-- @component value that a publication file suggested retaining.       -->\n<!-- So, just like the previous (now gone) \"component\" pass, we just     -->\n<!-- unwrap the element.                                                 -->\n<xsl:template match=\"commentary\" mode=\"repair\">\n    <!-- do not duplicate \"commentary\", do not replicate   -->\n    <!-- @component, do replicate element and text children -->\n    <xsl:apply-templates select=\"node()\" mode=\"repair\"/>\n</xsl:template>\n\n<!-- Change listing captions to titles if there is not already a title -->\n<xsl:template match=\"listing/caption\" mode=\"repair\">\n    <xsl:if test=\"not(parent::listing/title)\">\n        <title>\n            <xsl:apply-templates select=\"node()|@*\" mode=\"repair\"/>\n        </title>\n    </xsl:if>\n</xsl:template>\n\n<!-- 2025-08-15: Ensure that interactives all have a @pi:interactive-platform -->\n<!-- that identifies their basic type                                         -->\n<xsl:template match=\"interactive\" mode=\"repair\">\n    <xsl:copy>\n        <xsl:attribute name=\"pi:interactive-platform\">\n            <xsl:choose>\n                <xsl:when test=\"@platform\">\n                    <xsl:value-of select=\"@platform\"/>\n                </xsl:when>\n                <xsl:when test=\"@desmos\">desmos</xsl:when>\n                <xsl:when test=\"@geogebra\">geogebra</xsl:when>\n                <xsl:when test=\"@calcplot3d\">calcplot3d</xsl:when>\n                <xsl:when test=\"@circuitjs\">circuitjs</xsl:when>\n                <xsl:when test=\"@iframe\">iframe</xsl:when>\n                <xsl:otherwise>unknown</xsl:otherwise>\n            </xsl:choose>\n        </xsl:attribute>\n        <xsl:apply-templates select=\"@*\" mode=\"repair\"/>\n        <xsl:apply-templates select=\"node()\" mode=\"repair\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- 2025-11-04: a @runestone attribute was used to point into a file      -->\n<!-- of raw HTML versions of Runestone exercises.  This was a              -->\n<!-- transitional device to allow conversions of Runestone books into      -->\n<!-- PreTeXt books as work progressed on better integration of Runestone.  -->\n<!-- We make a dead simple replacment exercise, so numbering is preserved, -->\n<!-- etc, and authors can adapt at their leisure.  We remove the offending -->\n<!-- @runestone attribute via a very specialized template.                 -->\n\n<!-- applies to exercise, PROJECT-LIKE, task -->\n<xsl:template match=\"exercise[@runestone]|project[@runestone]|activity[@runestone]|exploration[@runestone]|investigation[@runestone]|task[@runestone]\" mode=\"repair\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"@*\" mode=\"repair\"/>\n        <p>There was once a (temporary) Runestone exercise here, which would only render in <init>HTML</init> output, and never in static output forms.  That (temporary) device is no longer supported as of 2025-11-04, since the exercise should now be authored in supported <pretext/> syntax.  You might alert the author to this situation.</p>\n    </xsl:copy>\n</xsl:template>\n\n<!-- remove the @runestone, just in case -->\n<xsl:template match=\"@runestone\" mode=\"repair\"/>\n\n\n<!-- Deprecate \"me\", \"men\", \"mdn\" in favor of \"md\" (w/ \"mrow\" or bare) -->\n\n<!-- Strategy: only two forms may be authored:                       -->\n<!--                                                                 -->\n<!--   Regular \"md\" with (multiple) \"mrow\" children                  -->\n<!--     - @xml:id goes on the \"mrow\"                                -->\n<!--     - @number may go on individual \"mrow\"                       -->\n<!--     - @number may go on overall \"md\" (to mimic \"mdn\")           -->\n<!--                                                                 -->\n<!--   Bare \"md\" with content (like old \"me\" and \"men\")              -->\n<!--     - @xml:id goes on the \"md\"                                  -->\n<!--     - md/@number allows for me/men dichotomy                    -->\n<!--     - md/@number is not assumed                                 -->\n<!--                                                                 -->\n<!-- Conversion here makes every existing display math construction  -->\n<!-- look like the \"regular\" version described above.                -->\n\n<!-- Not always a \"repair\" function, but we take the opportunity to  -->\n<!-- record if an \"mrow\" is numbered or not, via a  @pi:numbered     -->\n<!-- attribute, which is in our private namespace. For deprecations, -->\n<!-- we just do it.  For authored forms, we interpret an authored    -->\n<!-- @number attribute on authored \"mrow\" (status quo), on a regular -->\n<!-- or bare \"md\" (new), and a global specification in \"docinfo\"     -->\n<!-- (new).  These new features compensate for the deprecation       -->\n<!-- of the \"n\"-series elements.                                     -->\n<!-- The @tag attribute is a \"local tag\" formed with symbols,        -->\n<!-- and precludes a number.                                         -->\n\n<!-- Replace \"me\" and \"me\" by an \"md\" with one \"mrow\"    -->\n<!--   - @xml:id will live on the \"md\" (new)             -->\n<!--   - forcible  @npi:umbered  attribute for each,     -->\n<!--       to preserve old behavior                      -->\n<!--   - @pi:authored-one-line as empty sentinel, to     -->\n<!--       distinguish from an *authored* single \"mrow\"  -->\n<xsl:template match=\"me|men\" mode=\"repair\">\n    <xsl:element name=\"md\">\n        <xsl:apply-templates select=\"@*\" mode=\"repair\"/>\n        <!-- note origin as single-line display math -->\n        <xsl:attribute name=\"pi:authored-one-line\"/>\n        <!-- manufacture an \"mrow\" to hold content -->\n        <xsl:element name=\"mrow\">\n            <xsl:attribute name=\"pi:numbered\">\n                <xsl:choose>\n                    <xsl:when test=\"self::me\">\n                        <xsl:text>no</xsl:text>\n                    </xsl:when>\n                    <xsl:when test=\"self::men\">\n                        <xsl:text>yes</xsl:text>\n                    </xsl:when>\n                </xsl:choose>\n            </xsl:attribute>\n            <xsl:apply-templates select=\"node()\" mode=\"repair\"/>\n        </xsl:element>\n    </xsl:element>\n</xsl:template>\n\n<!-- \"md\" with \"mrow\" needs no adjustment (status quo),   -->\n<!-- the default \"repair\" templates are correct.  But     -->\n<!-- see \"mrow\" template below for @pi:numbered behavior. -->\n\n<!-- Replace \"mdn\" with \"mrow\" , by an \"md\" with @number     -->\n<!--   - see \"mrow\" template below for @pi:numbered behavior -->\n<!--   - @xml:id  was only ever allowed on individual \"mrow\" -->\n<xsl:template match=\"mdn[mrow]\" mode=\"repair\">\n    <xsl:element name=\"md\">\n        <xsl:apply-templates select=\"@*\" mode=\"repair\"/>\n        <!-- copy the mrows -->\n        <xsl:apply-templates select=\"node()\" mode=\"repair\"/>\n    </xsl:element>\n</xsl:template>\n\n<!-- A bare \"mdn\" was just a transitional device during all    -->\n<!-- the deprecation of the majority of math display elements  -->\n<!-- and the introduction of more robust numbering options.    -->\n<!-- It *never* enjoyed full support and was only in the wild  -->\n<!-- for a couple of weeks.  We warn about this removal (as a  -->\n<!-- deprecation) and suggest the \"md\" replacement.            -->\n<xsl:template match=\"mdn[not(mrow)]\" mode=\"repair\"/>\n\n<!-- Replace bare \"md\" by \"md\" with one \"mrow\"          -->\n<!--   - @xml:id will live on the \"md\" (new)            -->\n<!--   - md/@number  respected first                    -->\n<!--   - md/@tag  transferred to the manufactured       -->\n<!--       \"mrow\", where downstream processing expects  -->\n<!--       it; @tag and @number are mutually exclusive  -->\n<!--   - @pi:authored-one-line as empty sentinel, to    -->\n<!--       distinguish from an *authored* single \"mrow\" -->\n<xsl:template match=\"md[not(mrow)]\" mode=\"repair\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"@*[not(local-name(.) = 'tag')]\" mode=\"repair\"/>\n        <!-- note origin as single-line display math -->\n        <xsl:attribute name=\"pi:authored-one-line\"/>\n        <!-- manufacture an \"mrow\" to hold content -->\n        <xsl:element name=\"mrow\">\n            <!-- a @tag on the bare \"md\" is transferred to the \"mrow\" -->\n            <xsl:copy-of select=\"@tag\"/>\n            <xsl:attribute name=\"pi:numbered\">\n                <xsl:choose>\n                    <!-- a local @tag precludes a number -->\n                    <xsl:when test=\"@tag\">\n                        <xsl:text>no</xsl:text>\n                    </xsl:when>\n                    <!-- possibly authored with @number -->\n                    <xsl:when test=\"@number = 'yes'\">\n                        <xsl:text>yes</xsl:text>\n                    </xsl:when>\n                    <xsl:when test=\"@number = 'no'\">\n                        <xsl:text>no</xsl:text>\n                    </xsl:when>\n                    <!-- Now the global default set in \"docinfo\".  It would be -->\n                    <!-- nice to store this choice in a global variable, but   -->\n                    <!-- the mechanics of that result in erroneous recursion.  -->\n                    <!-- So we simply repeatedly consult the \"docinfo\" built   -->\n                    <!-- in the previous tree.                                 -->\n                    <xsl:when test=\"$representations/pretext/docinfo/numbering/@equations = 'yes'\">\n                        <xsl:text>yes</xsl:text>\n                    </xsl:when>\n                    <xsl:when test=\"$representations/pretext/docinfo/numbering/@equations = 'no'\">\n                        <xsl:text>no</xsl:text>\n                    </xsl:when>\n                    <!-- the default default is to not number equations -->\n                    <xsl:otherwise>\n                        <xsl:text>no</xsl:text>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:attribute>\n            <xsl:apply-templates select=\"node()\" mode=\"repair\"/>\n        </xsl:element>\n    </xsl:copy>\n</xsl:template>\n\n<!-- Authored \"mrow\", inside \"md\" or \"mdn\", get a @pi: numbered -->\n<!-- attribute, according to hierarchy of specifications.       -->\n<!-- (\"md\" and \"mdn\" parents in \"match\" could be overkill.)     -->\n<xsl:template match=\"md/mrow|mdn/mrow\" mode=\"repair\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"@*\" mode=\"repair\"/>\n        <xsl:attribute name=\"pi:numbered\">\n            <xsl:choose>\n                <xsl:when test=\"@tag\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"@number = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"@number = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <!-- now look to a (possible) \"mdn\" element as the      -->\n                <!-- container, the @number attribute is not supported, -->\n                <!-- the \"n\" implies a number by default                -->\n                <xsl:when test=\"parent::mdn\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <!-- now look to the (certain) \"md\" element as the container -->\n                <xsl:when test=\"parent::md[@number = 'yes']\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"parent::md[@number = 'no']\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <!-- Now the global default set in \"docinfo\".  It would be -->\n                <!-- nice to store this choice in a global variable, but   -->\n                <!-- the mechanics of that result in erroneous recursion.  -->\n                <!-- So we simply repeatedly consult the \"docinfo\" built   -->\n                <!-- in the previous tree.                                 -->\n                <xsl:when test=\"$representations/pretext/docinfo/numbering/@equations = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$representations/pretext/docinfo/numbering/@equations = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <!-- the default default is to not number equations -->\n                <xsl:otherwise>\n                    <xsl:text>no</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:attribute>\n        <xsl:apply-templates select=\"node()\" mode=\"repair\"/>\n    </xsl:copy>\n</xsl:template>\n\n\n<!-- Display math with \"intertext\"                           -->\n<!-- We explode display math with \"inertext\" into a series   -->\n<!-- of \"md\" interspered with \"pi:intertext\" elements.       -->\n<!-- Note that $nodes only selects \"mrow\" and \"intertext\".   -->\n<!-- Note:                                                   -->\n<!-- *  This really is a \"repair\" for \"mdn\" with intertext   -->\n<!--    there is a transformation to many \"md\".              -->\n<!-- *  When the \"mrow\" get hit by the \"repair\" template,    -->\n<!--    the numbering is recorded, based on the usual        -->\n<!--     hierarchy,including the \"md\" or \"mdn\" container.    -->\n<!-- *  The text of the \"intertext\" also gets hit by         -->\n<!--   \"repair\"s of any sentence-level changes will be made. -->\n\n<xsl:template match=\"md[intertext]|mdn[intertext]\" mode=\"repair\">\n\n    <!-- We are going to explode an \"md\" with \"intertext\" into  -->\n    <!-- multiple \"md\".  But for LaTeX, only, we are going to   -->\n    <!-- basically put them all back together again.  But as we -->\n    <!-- come up to each exploded \"md\" in the LaTeX conversion  -->\n    <!-- it will not be so easy to see if the *original* \"md\"   -->\n    <!-- had numbers or local tags.  So we determine this       -->\n    <!-- prior to the explosion and record it onto each \"md\".   -->\n    <!--                                                        -->\n    <!-- The logic of deprecations here means it is perhaps     -->\n    <!-- best to construct all the \"mrow\" in a disposable       -->\n    <!-- node-set and analyze it for numbers and tags, recorded -->\n    <!-- as a single boolean we can replicate.                  -->\n\n    <xsl:variable name=\"trial-mrow-rtf\">\n        <xsl:apply-templates select=\"mrow\" mode=\"repair\"/>\n    </xsl:variable>\n    <xsl:variable name=\"trial-mrow\" select=\"exsl:node-set($trial-mrow-rtf)\"/>\n    <xsl:variable name=\"b-needs-tags\" select=\"boolean($trial-mrow/mrow[@pi:numbered = 'yes' or @tag])\"/>\n\n    <xsl:apply-templates select=\".\" mode=\"intertext-exploder\">\n        <xsl:with-param name=\"nodes\" select=\"mrow|intertext\"/>\n        <xsl:with-param name=\"location\" select=\"'first'\"/>\n        <xsl:with-param name=\"b-needs-tags\" select=\"$b-needs-tags\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<xsl:template match=\"md[intertext]|mdn[intertext]\" mode=\"intertext-exploder\">\n    <xsl:param name=\"nodes\"/>\n    <xsl:param name=\"location\"/>\n    <xsl:param name=\"b-needs-tags\"/>\n\n    <!-- No nodes, no action, so recursion ends, -->\n    <!-- AND there is no $lead-node to switch on. -->\n    <xsl:if test=\"$nodes\">\n        <!-- will switch on if $lead node is \"mrow\" or \"interext\" -->\n        <xsl:variable name=\"lead-node\" select=\"$nodes[1]\"/>\n        <xsl:choose>\n            <xsl:when test=\"$lead-node[self::mrow]\">\n                <!-- The first intertext after $lead-node (if any) -->\n                <!-- marks the end of a non-empty run of \"mrow\"    -->\n                <!-- (we know $lead-node is an \"mrow\")             -->\n                <xsl:variable name=\"break\" select=\"$lead-node/following-sibling::intertext[1]\"/>\n                <!-- A maximal run of contiguous \"mrow\" starting at $lead-node.    -->\n                <!-- All \"mrow\" including $lead-node, and those coming afterwards. -->\n                <!-- $break is empty for the last run, so \"not($break)\" will be    -->\n                <!-- true and there is no filtering.  Otherwise we compare an      -->\n                <!-- \"mrow\"'s following \"intertext\" to see if it is $break or not. -->\n                <xsl:variable name=\"md-block\" select=\"$lead-node |\n                    $lead-node/following-sibling::mrow[not($break) or (count(following-sibling::intertext[1] | $break) = count(following-sibling::intertext[1]))]\"/>\n                <!-- put the maximal run into a fresh \"md\"     -->\n                <!-- Location helps with reconstruction in     -->\n                <!-- the LaTeX conversion, where we un-explode -->\n                <md pi:location=\"{$location}\">\n                    <xsl:attribute name=\"pi:latex-intertext-needs-tags\">\n                        <xsl:choose>\n                            <xsl:when test=\"$b-needs-tags\">\n                                <xsl:text>yes</xsl:text>\n                            </xsl:when>\n                            <xsl:otherwise>\n                                <xsl:text>no</xsl:text>\n                            </xsl:otherwise>\n                        </xsl:choose>\n                    </xsl:attribute>\n                    <xsl:apply-templates select=\"$md-block\" mode=\"repair\"/>\n                </md>\n                <!-- \"first\" is never repeated, and  -->\n                <!-- \"last\" only happens in one case -->\n                <xsl:variable name=\"next-location\">\n                    <xsl:choose>\n                        <xsl:when test=\"not($break/following-sibling::intertext)\">\n                            <xsl:text>last</xsl:text>\n                        </xsl:when>\n                        <xsl:otherwise>\n                            <xsl:text>intermediate</xsl:text>\n                        </xsl:otherwise>\n                    </xsl:choose>\n                </xsl:variable>\n                <!-- We strip down the set of $nodes, starting at the     -->\n                <!-- last \"mrow\" of the $md-block, so the remainder will  -->\n                <!-- normally start with an \"intertext\", or the remainder -->\n                <!-- might be empty (which will halt the recursion).      -->\n                <xsl:apply-templates select=\".\" mode=\"intertext-exploder\">\n                    <xsl:with-param name=\"nodes\" select=\"$md-block[last()]/following-sibling::*\"/>\n                    <xsl:with-param name=\"location\" select=\"$next-location\"/>\n                    <xsl:with-param name=\"b-needs-tags\" select=\"$b-needs-tags\"/>\n                </xsl:apply-templates>\n            </xsl:when>\n            <xsl:when test=\"$lead-node[self::intertext]\">\n                <!-- We place the text of the intertext into a custom      -->\n                <!-- internal element for handling by the common templates -->\n                <pi:intertext>\n                    <xsl:apply-templates select=\"$lead-node/node()\" mode=\"repair\"/>\n                </pi:intertext>\n                <!-- Strip down $nodes by simply removing the leading \"intertext\" -->\n                <xsl:apply-templates select=\".\" mode=\"intertext-exploder\">\n                    <xsl:with-param name=\"nodes\" select=\"$lead-node/following-sibling::*\"/>\n                    <xsl:with-param name=\"location\" select=\"$location\"/>\n                    <xsl:with-param name=\"b-needs-tags\" select=\"$b-needs-tags\"/>\n                </xsl:apply-templates>\n            </xsl:when>\n            <!-- orioginal  $nodes  ensures we never get here -->\n            <xsl:otherwise/>\n        </xsl:choose>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- ############################## -->\n<!-- Killed, in Chronological Order -->\n<!-- ############################## -->\n\n<!-- 2017-07-16  killed, from 2015-03-13 deprecation -->\n<xsl:template match=\"paragraph\" mode=\"repair\"/>\n\n<!-- 2019-02-20  deprecated and killed simultaneously -->\n<xsl:template match=\"todo\" mode=\"repair\"/>\n\n<!-- A \"pagebreak\" should have had limited -->\n<!-- uptake, so no real care taken,        -->\n<!-- Deprecated 2021-03-17                 -->\n<xsl:template match=\"pagebreak\" mode=\"repair\"/>\n\n<!-- @permid experiments retired 2024-07-24, -->\n<!-- so eliminated in this phase             -->\n<xsl:template match=\"@permid\" mode=\"repair\"/>\n\n<!-- 2024-08-05: remove metadata elements from a sidebyside, -->\n<!-- which have not been schema-compliant since circa 2017   -->\n<xsl:template match=\"sidebyside/*[&METADATA-FILTER;]\" mode=\"repair\"/>\n\n<!-- 2026-07-08  \"title\" deprecated on \"introduction\"/\"conclusion\" of a traditional division -->\n\n<!-- The title is dropped, silently; conversions provide a localized -->\n<!-- heading whenever a heading is called for.  Titles remain within -->\n<!-- specialized divisions, which are never structured, and so are   -->\n<!-- never summary pages (the situation that demands the heading)    -->\n<xsl:template match=\"introduction[parent::article or parent::chapter or parent::appendix or parent::section or parent::subsection]/title|conclusion[parent::article or parent::chapter or parent::appendix or parent::section or parent::subsection]/title\" mode=\"repair\"/>\n\n<!-- 2026-08-06  a \"references\" preface is a \"headnote\" -->\n\n<!-- The \"introduction\" becomes a \"headnote\", which never carries a  -->\n<!-- \"title\", so any title is discarded; the deprecation warning     -->\n<!-- says so plainly                                                 -->\n<xsl:template match=\"references/introduction\" mode=\"repair\">\n    <headnote>\n        <xsl:apply-templates select=\"node()[not(self::title)]|@*\" mode=\"repair\"/>\n    </headnote>\n</xsl:template>\n\n<!-- A \"references\" has no \"conclusion\": the element is dropped -->\n<!-- whole, and the deprecation warning says so plainly         -->\n<xsl:template match=\"references/conclusion\" mode=\"repair\"/>\n\n<!-- 2026-08-20  \"ol\" structuring an \"exercise\" is deprecated -->\n\n<!-- An \"ol\" as a child of an \"exercise\", or of its \"statement\",  -->\n<!-- once lettered its items like exercise parts.  The list is    -->\n<!-- wrapped in a \"p\" here, like any other list in running prose. -->\n<!-- Within the divisions that historically lettered these lists, -->\n<!-- a stamp preserves the extra list level for existing sources; -->\n<!-- new sources letter a list with marker=\"(a)\", or structure    -->\n<!-- real parts with \"task\".  The deprecation warning says so.    -->\n<xsl:template match=\"exercise/ol|exercise/statement/ol\" mode=\"repair\">\n    <p>\n        <xsl:copy>\n            <xsl:if test=\"ancestor::exercises or ancestor::reading-questions or ancestor::worksheet or ancestor::handout\">\n                <xsl:attribute name=\"pi:legacy-parts\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:attribute>\n            </xsl:if>\n            <xsl:apply-templates select=\"node()|@*\" mode=\"repair\"/>\n        </xsl:copy>\n    </p>\n</xsl:template>\n\n<!-- ########## -->\n<!-- Enrichment -->\n<!-- ########## -->\n\n<!-- Certain markup can be translated into more primitive versions using      -->\n<!-- existing markup, so we do a translation of certain forms into more       -->\n<!-- potentially verbose forms that an author might tire of doing repeatedly. -->\n<!-- See below for examples.  This is better than making a result-tree        -->\n<!-- fragment and applying templates, since all context is lost that way.     -->\n\n<!-- Visual URLs -->\n<!-- A great way to present a URL is with some clickable text.  But that    -->\n<!-- is useless in print.  And maybe a reader really would like to see the  -->\n<!-- actual URL.  So \"@visual\" is a version of the URL that is pleasing to  -->\n<!-- look at, maybe just a TLD, no protocol (e.g \"https://\"), no \"www.\"     -->\n<!-- if unnecessary, etc.  This \"visual URL\"  may be provided by an author  -->\n<!-- through a @visual attribute.  When this attribute is not provided, we  -->\n<!-- manufacture a reasonable version from the real, actual URL that must   -->\n<!-- necessarily be given.  To prevent consideration of a visual version,   -->\n<!-- an author can set @visual=\"\" and no manufactured version will be made. -->\n<xsl:template match=\"url[node() and not(@visual)]|dataurl[node() and not(@visual)]\" mode=\"enrichment\">\n    <!-- We create a new \"default-ish\" visual URL for a  -->\n    <!-- content-full \"url\" when none has been authored -->\n    <!--  -->\n    <!-- We get a candidate visual URI             -->\n    <!--   @href: external link/reference/location -->\n    <!--   dataurl[@source]:  internal link        -->\n    <xsl:variable name=\"uri\">\n        <xsl:choose>\n            <!-- \"url\" and \"dataurl\" both support external @href -->\n            <xsl:when test=\"@href\">\n                <xsl:value-of select=\"@href\"/>\n            </xsl:when>\n            <!-- a \"dataurl\" might be local, @source is         -->\n            <!-- indication, so prefix with a base URL,         -->\n            <!-- add \"external\" directory, via template useful  -->\n            <!-- also for visual URL formulation in -assembly   -->\n            <!-- N.B. we are using the base URL, since this is  -->\n            <!-- the most likely need by employing conversions. -->\n            <!-- It would eem duplicative in a conversion to    -->\n            <!-- HTML, so could perhaps be killed in that case. -->\n            <!-- But it is what we want for LaTeX, and perhaps  -->\n            <!-- for EPUB, etc.                                 -->\n            <xsl:when test=\"self::dataurl and @source\">\n                <xsl:apply-templates select=\".\" mode=\"static-url\"/>\n            </xsl:when>\n            <!-- empty will be non-functional -->\n            <xsl:otherwise/>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- And clean-up automatically in the prevalent cases -->\n    <xsl:variable name=\"truncated-href\">\n        <xsl:choose>\n            <xsl:when test=\"substring(@href, 1, 8) = 'https://'\">\n                <xsl:value-of select=\"substring($uri, 9)\"/>\n            </xsl:when>\n            <xsl:when test=\"substring(@href, 1, 7) = 'http://'\">\n                <xsl:value-of select=\"substring($uri, 8)\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$uri\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!--  -->\n    <xsl:copy>\n        <!-- copy all the attributes, which might include a @visual,      -->\n        <!-- and that @visual could be empty (a signal it is not desired) -->\n        <xsl:apply-templates select=\"@*\" mode=\"enrichment\"/>\n        <!-- Provide the \"missing\" @visual (see match above),  -->\n        <!-- so now *every* content-full \"url\" has an @visual, -->\n        <!-- either authored or provided automatically here.   -->\n        <!-- Conversions decide what to do with it.            -->\n        <xsl:attribute name=\"visual\">\n            <xsl:value-of select=\"$truncated-href\"/>\n        </xsl:attribute>\n        <!-- done with attributes, copy the content -->\n        <xsl:apply-templates select=\"node()\" mode=\"enrichment\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- ######################################## -->\n<!-- Enrichment of Geogebra interactives      -->\n<!-- ######################################## -->\n\n<!-- Expand reference to Geogebra by material-id to use -->\n<!-- an implicit applet approach with a slate to better -->\n<!-- facilitate all of the applet control parameters.   -->\n<xsl:template match=\"interactive[@geogebra]\" mode=\"enrichment\">\n    <xsl:param name=\"default-aspect\" select=\"'1:1'\" />\n    <xsl:variable name=\"ggbMaterialWidth\">\n        <xsl:choose>\n            <xsl:when test=\"@material-width\">\n                <xsl:value-of select=\"@material-width\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>800</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"aspect-ratio\">\n        <xsl:apply-templates select=\".\" mode=\"get-aspect-ratio\">\n            <xsl:with-param name=\"default-aspect\" select=\"$default-aspect\" />\n        </xsl:apply-templates>\n    </xsl:variable>\n    <xsl:variable name=\"ggbMaterialHeight\">\n        <xsl:choose>\n            <xsl:when test=\"@material-height\">\n                <xsl:value-of select=\"@material-height\"/>\n            </xsl:when>\n            <xsl:when test=\"$aspect-ratio=''\"/>\n            <xsl:otherwise>\n                <xsl:value-of select=\"round($ggbMaterialWidth div $aspect-ratio)\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"slate-copy-attr\" select=\"'toolbar algebra-input reset-icon shift-drag-zoom zoom-buttons'\"/>\n    <xsl:variable name=\"interactive-drop-attr\" select=\"concat($slate-copy-attr, ' ', 'geogebra material-width material-height')\"/>\n    <interactive>\n        <xsl:attribute name=\"platform\">\n            <xsl:text>geogebra</xsl:text>\n        </xsl:attribute>\n        <xsl:if test=\"not(@aspect)\">\n            <xsl:attribute name=\"aspect\">\n                <xsl:value-of select=\"$aspect-ratio\"/>\n            </xsl:attribute>\n        </xsl:if>\n        <!-- Restore all of the original attributes not processed separately -->\n        <xsl:copy-of select=\"@*[not(contains(concat(' ', $interactive-drop-attr, ' '), concat(' ', local-name(), ' ')))]\"/>\n        <!-- done with attributes, copy the content -->\n        <xsl:apply-templates select=\"node()\" mode=\"enrichment\"/>\n        <slate>\n            <!-- A manufactured \"slate\" carries a genuine @xml:id (not a  -->\n            <!-- pi: stamp): the interactive machinery locates slates by  -->\n            <!-- id, and the derived name keeps it stable and             -->\n            <!-- collision-free.                                          -->\n            <xsl:attribute name=\"xml:id\">\n                <xsl:value-of select=\"@pi:assembly-id\"/>\n                <xsl:text>-ggb-slate</xsl:text>\n            </xsl:attribute>\n            <xsl:attribute name=\"surface\">\n                <xsl:text>geogebra</xsl:text>\n            </xsl:attribute>\n            <xsl:attribute name=\"material\">\n                <xsl:value-of select=\"@geogebra\"/>\n            </xsl:attribute>\n            <xsl:attribute name=\"material-width\">\n                <xsl:value-of select=\"$ggbMaterialWidth\"/>\n            </xsl:attribute>\n            <xsl:if test=\"$ggbMaterialHeight != ''\">\n                <xsl:attribute name=\"material-height\">\n                    <xsl:value-of select=\"$ggbMaterialHeight\"/>\n                </xsl:attribute>\n            </xsl:if>\n            <xsl:copy-of select=\"@*[contains(concat(' ', $slate-copy-attr, ' '), concat(' ', local-name(), ' '))]\"/>\n        </slate>\n    </interactive>\n</xsl:template>\n\n<!-- ###### -->\n<!-- Labels -->\n<!-- ###### -->\n\n<!-- The \"labels\" pass (pass 11).  It promotes an authored         -->\n<!-- @xml:id to @label and records localization support.  It is    -->\n<!-- deliberately separate from the id-attribute mechanism in      -->\n<!-- \"Identification\": it runs after @pi:assembly-id is stamped and-->\n<!-- before @pi:unique-id, and the @label values created here are  -->\n<!-- read by that final @pi:unique-id stamp.                       -->\n\n<!-- Reader-facing identification switched to prefer @label,      -->\n<!-- rather than @xml:id (at 1779e6dbc84c6ecc).  So to preserve   -->\n<!-- authored (crafted) identifier strings, we copy the old over  -->\n<!-- into the new.  This preserves identifiers in output          -->\n<!-- (filenames, fragment identifiers).  Subsequent passes        -->\n<!-- should not introduce or remove elements.                     -->\n\n<!-- 2023-03-30: This is old commentary about the use of the -->\n<!-- \"unique-id\" identifier in the LaTeX conversion, which   -->\n<!-- has now become more universal.  Once identifiers settle -->\n<!-- down, we can clean up the parts of this worth keeping.  -->\n<!--  -->\n<!-- This produces unique strings that are internal to the  -->\n<!-- LaTeX (intermediate) file.  Since neither author nor   -->\n<!-- reader will ever see these, they can be as fast and as -->\n<!-- wild as necessary.  But for mature works, likely with  -->\n<!-- @permid on many relevant objects, or many @xml:id      -->\n<!-- provided for URLs in HTML, these can be predictable    -->\n<!-- across runs (and therefore help with tweaking the LaTeX-->\n<!-- output under revision control) These are employed with -->\n<!-- \\label{}, \\ref{}, \\cite{}, \\pageref{}, \\eqref{}, etc.  -->\n<!-- We can change this at will, with no adverse effects    -->\n<!-- NB: colons are banned from PTX @xml:id, and will not   -->\n<!-- appear in @permid, though we could use dashes instead  -->\n<!-- without getting duplicates.  The prefixes guarantee    -->\n<!-- that the three uniqueness schemes do not overlap.      -->\n\n<!-- First, we upgrade an authored @xml:id to a @label,       -->\n<!-- WHEN there is no authored @label present.  This is a     -->\n<!-- sort of backward-compatibility maneuver.  An @xml:id     -->\n<!-- now serves only as a sort of internal name for a target  -->\n<!-- node (like a cross-reference, \"xref\"), while it formerly -->\n<!-- served as a string to generate various bits of output,   -->\n<!-- such as filenames in HTML output.                        -->\n\n<!-- This same walk also records language support (see the    -->\n<!-- \"Languages\" section for the $locales variable), since    -->\n<!-- both jobs are simple attribute additions and do not      -->\n<!-- deserve separate passes through the entire source.       -->\n\n<xsl:template match=\"*\" mode=\"labels\">\n    <xsl:copy>\n        <!-- duplicate all attributes -->\n        <xsl:apply-templates select=\"@*\" mode=\"labels\"/>\n        <!-- Case: an authored @xml:id, not an authored @label -->\n        <xsl:if test=\"@xml:id and not(@label)\">\n            <xsl:attribute name=\"label\">\n                <xsl:value-of select=\"@xml:id\"/>\n            </xsl:attribute>\n        </xsl:if>\n        <!-- Case: a @label provided in source by author                 -->\n        <!-- It is helpful to distinguish between an authored @label and -->\n        <!-- one that this template creates by copying over a @xml:id.   -->\n        <!-- So we drop an (empty) attribute as a boolean indicator.     -->\n        <!-- This form will simplify checks later at \"run-time\".         -->\n        <xsl:if test=\"@label\">\n            <xsl:attribute name=\"pi:authored-label\"/>\n        </xsl:if>\n        <!-- A supported @xml:lang is recorded in an internal attribute -->\n        <!-- for use by localizations.  The root element is the         -->\n        <!-- fail-safe node on a language query up the tree, so there   -->\n        <!-- an absent, or unsupported, @xml:lang becomes the default,  -->\n        <!-- en-US.  An unsupported @xml:lang below the root is left    -->\n        <!-- alone, as it might be relevant for future features.        -->\n        <xsl:choose>\n            <xsl:when test=\"@xml:lang = $locales\">\n                <xsl:attribute name=\"pi:locale-lang\">\n                    <xsl:value-of select=\"@xml:lang\"/>\n                </xsl:attribute>\n            </xsl:when>\n            <xsl:when test=\"not(parent::*)\">\n                <xsl:attribute name=\"xml:lang\">\n                    <xsl:text>en-US</xsl:text>\n                </xsl:attribute>\n                <xsl:attribute name=\"pi:locale-lang\">\n                    <xsl:text>en-US</xsl:text>\n                </xsl:attribute>\n            </xsl:when>\n            <xsl:otherwise/>\n        </xsl:choose>\n        <!-- recurse -->\n        <xsl:apply-templates select=\"node()\" mode=\"labels\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- We look for duplicate identifiers both right after    -->\n<!-- assembly and right after automatic generation.  The   -->\n<!-- application of these templates is mixed-in to the     -->\n<!-- creation of the trees.                                -->\n<!-- NB: these were built as regular templates and the     -->\n<!-- root of the relevant tree was passed in, this created -->\n<!-- some error with the construction of the final tree:   -->\n<!-- \"Recursive definition of root\"                        -->\n<xsl:template name=\"duplication-check-xmlid\">\n    <!-- pass in all elements with @xml:id attributes -->\n    <xsl:param name=\"nodes\"/>\n    <!-- 'authored' or 'generated', just influences messages -->\n    <xsl:param name=\"purpose\"/>\n\n    <xsl:call-template name=\"duplication-check-attribute\">\n        <xsl:with-param name=\"nodes\" select=\"$nodes\"/>\n        <xsl:with-param name=\"purpose\" select=\"$purpose\"/>\n        <xsl:with-param name=\"target-attr\" select=\"'xml:id'\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<xsl:template name=\"duplication-check-label\">\n    <!-- pass in all elements with @label attributes -->\n    <xsl:param name=\"nodes\"/>\n    <!-- 'authored' or 'generated', just influences messages -->\n    <xsl:param name=\"purpose\"/>\n\n    <xsl:call-template name=\"duplication-check-attribute\">\n        <xsl:with-param name=\"nodes\" select=\"$nodes\"/>\n        <xsl:with-param name=\"purpose\" select=\"$purpose\"/>\n        <xsl:with-param name=\"target-attr\" select=\"'label'\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<xsl:template name=\"duplication-check-attribute\">\n    <xsl:param name=\"nodes\"/>\n    <!-- 'authored' or 'generated', just influences messages -->\n    <xsl:param name=\"purpose\"/>\n    <xsl:param name=\"target-attr\"/>\n\n    <!-- construct a list of just the sorted labels -->\n    <xsl:variable name=\"attr-values-sorted-rtf\">\n        <xsl:for-each select=\"$nodes/@*[name() = $target-attr]\">\n            <xsl:sort select=\".\"/>\n            <label>\n                <xsl:value-of select=\".\"/>\n            </label>\n        </xsl:for-each>\n    </xsl:variable>\n    <xsl:variable name=\"attr-values-sorted\" select=\"exsl:node-set($attr-values-sorted-rtf)\"/>\n\n    <!-- traverse sorted list to find duplicates -->\n    <xsl:for-each select=\"$attr-values-sorted/*\">\n        <!-- save off the string on current node -->\n        <xsl:variable name=\"attr-value\" select=\".\"/>\n        <!-- get previous two labels - will be '' if out of bounds -->\n        <xsl:variable name=\"prev-value\" select=\"string(preceding-sibling::*[1])\"/>\n        <xsl:variable name=\"prev-prev-value\" select=\"string(preceding-sibling::*[2])\"/>\n        <!-- identify only first instance of a duplicate for each label -->\n        <xsl:if test=\"($attr-value= $prev-value) and ($attr-value != $prev-prev-value)\">\n            <xsl:choose>\n                <xsl:when test=\"$purpose = 'authored'\">\n                    <xsl:message>PTX:ERROR: the @<xsl:value-of select=\"$target-attr\"/> value \"<xsl:value-of select=\"$attr-value\"/>\" should be unique, but is authored multiple times.</xsl:message>\n                </xsl:when>\n            </xsl:choose>\n            <xsl:message>           Results will be unpredictable, and likely incorrect.  Information on the locations follows:</xsl:message>\n            <!-- use the original nodes to report location of instances -->\n            <!-- select where they have an attr with the correct name and it has correct value -->\n            <xsl:for-each select=\"$nodes[@*[name() = $target-attr] = $attr-value]\">\n                <xsl:apply-templates select=\".\" mode=\"location-report\" />\n            </xsl:for-each>\n        </xsl:if>\n    </xsl:for-each>\n</xsl:template>\n\n<!-- ######### -->\n<!-- Languages -->\n<!-- ######### -->\n\n<!-- The variable $locales is a node-set of all the locales which have       -->\n<!-- supported localization files.  A comparison of an @xml:lang (string)    -->\n<!-- with $locales (node-set) will be true if the attribute value is a       -->\n<!-- string value of one of the nodes in the node-set.  So it is easy to     -->\n<!-- create a boolean value for localization support.                        -->\n<!-- The recording of language support in @pi:locale-lang attributes is part -->\n<!-- of the \"labels\" pass, since both jobs are simple attribute additions    -->\n<!-- and do not deserve separate passes through the entire source.           -->\n<xsl:variable name=\"locales\" select=\"document('localizations/localizations.xml')/localizations/locale\" />\n\n<!-- ######### -->\n<!-- Numbering -->\n<!-- ######### -->\n\n<!-- We use the \"augment\" pass to compute, and add, partially naïve           -->\n<!-- information about numbers of objects, to be interpreted later by         -->\n<!-- templates in the \"-common\" stylesheet.  By \"naïve\" we mean that          -->\n<!-- these routines may depend on publisher variables (e.g. specification     -->\n<!-- of roots of subtrees for serial numbers of blocks) but do not depend     -->\n<!-- on subtlties of numbering (such as the structured/unstructured           -->\n<!-- division dichotomy), which are addressed in the \"-common\" stylesheet.    -->\n<!-- In this way, this information could be interpreted in new ways by        -->\n<!-- additional conversions.                                                  -->\n<!--                                                                          -->\n<!-- The manufactured @pi:struct attribute is the (naïve) hierarchical number -->\n<!-- of the *container* of an element, known as the \"structure number\"        -->\n<!-- of an element.  The @pi:serial attribute is the computed serial number   -->\n<!-- of the element, known as the \"serial number\".  Typically combining       -->\n<!-- these two attributes forms teh number of an element.  As many            -->\n<!-- practical subtleties about these numbers is delayed until their          -->\n<!-- interpretation by templates in the \"-common\" stylesheet.                 -->\n\n<!-- For every type of division, everywhere, the \"division-serial-number\"   -->\n<!-- modal template will return a count of preceding peers at that level.   -->\n<!-- The @pi:struct attribute is the structure number of the *parent*       -->\n<!-- (container), which seems odd here, but fits the general scheme better. -->\n<!-- The @pi:level attribute is helpful, and trvislly to compute here.      -->\n<xsl:template match=\"part|chapter|appendix|section|subsection|subsubsection|exercises|solutions|reading-questions|references|glossary|worksheet|handout\" mode=\"augment\">\n    <xsl:param name=\"parent-struct\"/>\n    <xsl:param name=\"level\"/>\n\n    <xsl:variable name=\"the-serial\">\n        <xsl:apply-templates select=\".\" mode=\"division-serial-number\"/>\n    </xsl:variable>\n    <xsl:variable name=\"new-struct\">\n        <xsl:choose>\n            <!-- Parts as Roman numerals make for a lot of clutter.      -->\n            <!-- We tend to only use them when necessary to diambiguate  -->\n            <!-- a cross-reference in the case where these numbers are   -->\n            <!-- structural.  So rightly or wrongly, and owing to        -->\n            <!-- historical work, we squelch them as the lead item of a  -->\n            <!-- structural number.  So here the Roman numeral will be   -->\n            <!-- preserved as a serial number, but the construction of   -->\n            <!-- the structural numbers will be delayed one level.       -->\n            <!-- (It seems harder to strip these in -common.)            -->\n            <xsl:when test=\"self::part\"/>\n            <!-- Decorative specialized divisions are transparent:    -->\n            <!-- they do not extend the structure number chain, so    -->\n            <!-- blocks inside them use the parent division's chain.  -->\n            <!-- Specialized divisions are leaves of the division     -->\n            <!-- tree, so this does not affect any descendant         -->\n            <!-- division's @pi:struct.                               -->\n            <xsl:when test=\"&SPECIALIZED-DIVISION-FILTER;\">\n                <xsl:variable name=\"is-numbered\">\n                    <xsl:apply-templates select=\".\" mode=\"is-specialized-own-number\"/>\n                </xsl:variable>\n                <xsl:choose>\n                    <xsl:when test=\"$is-numbered = 'true'\">\n                        <xsl:value-of select=\"$parent-struct\"/>\n                        <xsl:if test=\"not($parent-struct='')\">\n                            <xsl:text>.</xsl:text>\n                        </xsl:if>\n                        <xsl:value-of select=\"$the-serial\"/>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:value-of select=\"$parent-struct\"/>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$parent-struct\"/>\n                <xsl:if test=\"not($parent-struct='')\">\n                    <xsl:text>.</xsl:text>\n                </xsl:if>\n                <xsl:value-of select=\"$the-serial\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"next-level\" select=\"$level + 1\"/>\n    <xsl:copy>\n        <xsl:attribute name=\"pi:struct\">\n            <xsl:value-of select=\"$parent-struct\"/>\n        </xsl:attribute>\n        <xsl:attribute name=\"pi:serial\">\n            <xsl:value-of select=\"$the-serial\"/>\n        </xsl:attribute>\n        <xsl:attribute name=\"pi:level\">\n            <xsl:value-of select=\"$next-level\"/>\n        </xsl:attribute>\n        <!-- Full structure chain including this division's       -->\n        <!-- contribution.  Decorative specialized divisions are  -->\n        <!-- transparent (pass through parent's chain).  Used by  -->\n        <!-- block elements to compute their structure numbers.   -->\n        <xsl:attribute name=\"pi:block-struct\">\n            <xsl:value-of select=\"$new-struct\"/>\n        </xsl:attribute>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"augment\">\n            <xsl:with-param name=\"parent-struct\" select=\"$new-struct\"/>\n            <xsl:with-param name=\"level\" select=\"$next-level\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<!-- The top-level division (book, article, ...) is the root of the   -->\n<!-- division tree, at level 0, which the catch-all does not record.  -->\n<!-- A level-0 numbering scheme counts continuously from the root.    -->\n<xsl:template match=\"book|article|slideshow|letter|memo\" mode=\"augment\">\n    <xsl:copy>\n        <xsl:attribute name=\"pi:level\">\n            <xsl:text>0</xsl:text>\n        </xsl:attribute>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"augment\">\n            <xsl:with-param name=\"parent-struct\" select=\"''\"/>\n            <xsl:with-param name=\"level\" select=\"0\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<!-- See the definitions of levels in -common.  For a book with parts   -->\n<!-- ($parts != 'absent') we consider parts as peers of frontmatter and -->\n<!-- backmatter.  So we need to increment the level in this case, only. -->\n<!-- NB: this might consolidate with above, but seems better solo.      -->\n<!-- NB: with some study and work, this situation might be improved?    -->\n<xsl:template match=\"frontmatter|backmatter\" mode=\"augment\">\n    <xsl:param name=\"parent-struct\"/>\n    <xsl:param name=\"level\"/>\n\n    <xsl:variable name=\"next-level\">\n        <xsl:choose>\n            <xsl:when test=\"($parts = 'decorative') or ($parts = 'structural')\">\n                <xsl:value-of select=\"$level + 1\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$level\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- we only add a level (not necessary?) -->\n    <!-- and just pass along structure number -->\n    <xsl:copy>\n        <xsl:attribute name=\"pi:level\">\n            <xsl:value-of select=\"$next-level\"/>\n        </xsl:attribute>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"augment\">\n            <xsl:with-param name=\"parent-struct\" select=\"$parent-struct\"/>\n            <xsl:with-param name=\"level\" select=\"$next-level\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<!-- Labels of ordered lists have formatting codes, which  -->\n<!-- we detect here and pass on to other more specialized  -->\n<!-- templates for implementation specifics                -->\n<!-- In order: Arabic (0-based), Arabic (1-based)          -->\n<!-- lower-case Latin, upper-case Latin,                   -->\n<!-- lower-case Roman numeral, upper-case Roman numeral    -->\n<!-- Absent a label attribute, defaults go 4 levels deep   -->\n<!-- (max for Latex) as: Arabic, lower-case Latin,         -->\n<!-- lower-case Roman numeral, upper-case Latin            -->\n<xsl:template match=\"ol\" mode=\"format-code\">\n    <xsl:param name=\"level\"/>\n    <xsl:choose>\n        <xsl:when test=\"@marker\">\n            <xsl:choose>\n                <xsl:when test=\"contains(@marker,'0')\">0</xsl:when>\n                <xsl:when test=\"contains(@marker,'1')\">1</xsl:when>\n                <xsl:when test=\"contains(@marker,'a')\">a</xsl:when>\n                <xsl:when test=\"contains(@marker,'A')\">A</xsl:when>\n                <xsl:when test=\"contains(@marker,'i')\">i</xsl:when>\n                <xsl:when test=\"contains(@marker,'I')\">I</xsl:when>\n                <!-- DEPRECATED 2015-12-12 -->\n                <xsl:when test=\"@marker=''\" />\n                <xsl:otherwise>\n                    <xsl:message>PTX:ERROR: ordered list label (<xsl:value-of select=\"@marker\" />) not recognized</xsl:message>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:choose>\n                <xsl:when test=\"$level='0'\">1</xsl:when>\n                <xsl:when test=\"$level='1'\">a</xsl:when>\n                <xsl:when test=\"$level='2'\">i</xsl:when>\n                <xsl:when test=\"$level='3'\">A</xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:ERROR: ordered list is more than 4 levels deep (at level <xsl:value-of select=\"$level\" />; a legacy exercise-parts list counts one level extra)</xsl:message>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"ol\" mode=\"augment\">\n    <!-- The list level is intrinsic: a count of enclosing ordered   -->\n    <!-- lists, raised by one within a list the repair phase stamped -->\n    <!-- as a legacy exercise-parts list (the stamp lifts the whole  -->\n    <!-- nest, so sublists letter as they always have).              -->\n    <xsl:variable name=\"ordered-list-level\" select=\"count(ancestor::ol) + number(boolean(ancestor-or-self::ol[@pi:legacy-parts]))\"/>\n    <xsl:variable name=\"format-code\">\n        <xsl:apply-templates select=\".\" mode=\"format-code\">\n            <xsl:with-param name=\"level\" select=\"$ordered-list-level\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <!-- deconstruct the left and right adornments of the label   -->\n    <!-- or provide default adornments, consistent with LaTeX     -->\n    <!-- then store them                                          -->\n    <xsl:variable name=\"marker-prefix\">\n        <xsl:choose>\n            <xsl:when test=\"@marker\">\n                <xsl:value-of select=\"substring-before(@marker, $format-code)\" />\n            </xsl:when>\n            <xsl:when test=\"$format-code = 'a' and $ordered-list-level = '1'\">\n                <xsl:text>(</xsl:text>\n            </xsl:when>\n            <xsl:otherwise />\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"marker-suffix\">\n        <xsl:choose>\n            <xsl:when test=\"@marker\">\n                <xsl:value-of select=\"substring-after(@marker, $format-code)\" />\n            </xsl:when>\n            <xsl:when test=\"$format-code = 'a' and $ordered-list-level = '1'\">\n                <xsl:text>)</xsl:text>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>.</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:copy>\n        <xsl:attribute name=\"pi:ordered-list-level\">\n            <xsl:value-of select=\"$ordered-list-level\"/>\n        </xsl:attribute>\n        <xsl:attribute name=\"pi:format-code\">\n            <xsl:value-of select=\"$format-code\"/>\n        </xsl:attribute>\n        <xsl:attribute name=\"pi:marker-prefix\">\n            <xsl:value-of select=\"$marker-prefix\"/>\n        </xsl:attribute>\n        <xsl:attribute name=\"pi:marker-suffix\">\n            <xsl:value-of select=\"$marker-suffix\"/>\n        </xsl:attribute>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"augment\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- The stamp has served its purpose once the level is recorded, -->\n<!-- so it does not survive into the assembled tree.              -->\n<xsl:template match=\"@pi:legacy-parts\" mode=\"augment\"/>\n\n<!-- List levels and format codes are ancestor-axis computations    -->\n<!-- that *could* be made at conversion time in -common; we simply  -->\n<!-- choose to make them once, here in assembly, and stamp the      -->\n<!-- results.  Unordered lists follow the pattern of ordered lists  -->\n<!-- above: an authored @marker wins, else defaults cycle by depth. -->\n\n<!-- Labels of unordered lists have format codes:   -->\n<!-- disc, circle, square, or none.  Default order: -->\n<!-- disc, circle, square, disc.                    -->\n<xsl:template match=\"ul\" mode=\"format-code\">\n    <xsl:param name=\"level\"/>\n    <xsl:choose>\n        <xsl:when test=\"@marker\">\n            <xsl:choose>\n                <xsl:when test=\"@marker='disc'\">disc</xsl:when>\n                <xsl:when test=\"@marker='circle'\">circle</xsl:when>\n                <xsl:when test=\"@marker='square'\">square</xsl:when>\n                <xsl:when test=\"@marker=''\">none</xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:ERROR: unordered list label (<xsl:value-of select=\"@marker\" />) not recognized</xsl:message>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:choose>\n                <xsl:when test=\"$level='0'\">disc</xsl:when>\n                <xsl:when test=\"$level='1'\">circle</xsl:when>\n                <xsl:when test=\"$level='2'\">square</xsl:when>\n                <xsl:when test=\"$level='3'\">disc</xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:ERROR: unordered list is more than 4 levels deep (at level <xsl:value-of select=\"$level\" />)</xsl:message>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"ul\" mode=\"augment\">\n    <xsl:variable name=\"format-code\">\n        <xsl:apply-templates select=\".\" mode=\"format-code\">\n            <xsl:with-param name=\"level\" select=\"count(ancestor::ul)\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <xsl:copy>\n        <xsl:attribute name=\"pi:format-code\">\n            <xsl:value-of select=\"$format-code\"/>\n        </xsl:attribute>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"augment\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- ##################### -->\n<!-- Serial Stamp Pass     -->\n<!-- ##################### -->\n\n<!-- Stamps @pi:serial during assembly, in one depth-first walk.  Each-->\n<!-- numbered family (equations and footnotes) is threaded as a       -->\n<!-- node-set: its items in the current counting scope, and each item -->\n<!-- is stamped with its position in that node-set.  How a scope is   -->\n<!-- chosen, and how the node-set is recomputed at each step, is      -->\n<!-- documented with the division templates below.                    -->\n\n<!-- The \"next\" node-set                                                    -->\n\n<!-- A numbered family is counted within a \"scope\": a division whose own    -->\n<!-- items form one flat, serially numbered pool.  A division opens a       -->\n<!-- scope for a family when it is terminal (has no traditional             -->\n<!-- subdivision) or has reached the family's numbering level.  A           -->\n<!-- structural division above that level recurses instead, and the         -->\n<!-- content it holds directly (its introduction and conclusion) pools      -->\n<!-- at the division's own level.                                           -->\n\n<!-- Each template threads one node-set per family (the family's items      -->\n<!-- in the current scope) and hands its children the \"next\" one, built     -->\n<!-- from the inherited node-set:                                           -->\n\n<!--     $b-open = not($nodes) and ($b-terminal or @pi:level >= LEVEL)      -->\n<!--     $next   = $nodes | self::*[$b-open]//ITEMS                         -->\n\n<!-- This is three cases.  Already in a scope ($nodes non-empty): $b-open   -->\n<!-- is false, so $next is $nodes and the scope threads down unchanged.     -->\n<!-- Opening a scope here: $next is this division's pool of items.  Still   -->\n<!-- above the level: $next is empty, the walk recurses, and a deeper       -->\n<!-- division opens the scope.                                              -->\n\n<!-- The self::*[$b-open] guard makes the descendant scan for the pool      -->\n<!-- happen only at the division that opens the scope; while a scope        -->\n<!-- merely threads down, $nodes is non-empty and nothing is scanned.       -->\n\n<!-- The introduction/conclusion template (below) has the same shape,       -->\n<!-- except its pool is the division's own introduction and conclusion      -->\n<!-- (siblings, not a descendant scan), taken only where the parent         -->\n<!-- recursed.                                                              -->\n\n<!-- ITEMS (the family's items) and LEVEL (its numbering switch) are the    -->\n<!-- only per-family inputs; $b-terminal and the case structure are shared. -->\n<!-- Seven families ride this structure: equations (\"-eq\") and footnotes    -->\n<!-- (\"-fn\") are single counters; the block families share the \"blocks\"     -->\n<!-- counter unless figure-likes, projects, inline exercises, or open       -->\n<!-- problems are set \"distinct\", each then opening its own counter.        -->\n<xsl:template match=\"book|article|part|chapter|appendix|frontmatter|backmatter|preface|section|subsection|subsubsection|exercises|worksheet|handout|reading-questions|references|glossary|solutions\" mode=\"serial-stamp\">\n    <xsl:param name=\"eq-nodes\"/>\n    <xsl:param name=\"fn-nodes\"/>\n    <xsl:param name=\"blocks-nodes\"/>\n    <xsl:param name=\"figure-nodes\"/>\n    <xsl:param name=\"project-nodes\"/>\n    <xsl:param name=\"exercise-nodes\"/>\n    <xsl:param name=\"openproblem-nodes\"/>\n    <!-- Terminal: this division's items pool into one flat scope  -->\n    <!-- here.  For a traditional division the authority is the    -->\n    <!-- two-model test \"is-structured-division\": an unstructured  -->\n    <!-- division (content, plus at most one of each specialized   -->\n    <!-- division) is terminal, its specialized divisions pooling  -->\n    <!-- into its scope; a structured division (traditional        -->\n    <!-- subdivisions, or only worksheets) recurses, and each      -->\n    <!-- worksheet then opens a scope apiece.  The test does not   -->\n    <!-- apply to \"frontmatter\", \"backmatter\", a \"preface\", or the -->\n    <!-- specialized divisions themselves, which keep the plain    -->\n    <!-- child-division inspection.                                -->\n    <xsl:variable name=\"terminal\">\n        <xsl:choose>\n            <xsl:when test=\"self::book or self::article or self::part or self::chapter or self::appendix or self::section or self::subsection or self::subsubsection\">\n                <xsl:variable name=\"is-structured\">\n                    <xsl:apply-templates select=\".\" mode=\"is-structured-division\"/>\n                </xsl:variable>\n                <xsl:value-of select=\"$is-structured = 'false'\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"not(part|chapter|appendix|section|subsection|subsubsection|preface|exercises|worksheet|handout|reading-questions|references|glossary|solutions)\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"b-terminal\" select=\"$terminal = 'true'\"/>\n    <xsl:variable name=\"b-open-eq\"          select=\"not($eq-nodes)          and ($b-terminal or (@pi:level &gt;= $numbering-equations))\"/>\n    <xsl:variable name=\"b-open-fn\"          select=\"not($fn-nodes)          and ($b-terminal or (@pi:level &gt;= $numbering-footnotes))\"/>\n    <xsl:variable name=\"b-open-blocks\"      select=\"not($blocks-nodes)      and ($b-terminal or (@pi:level &gt;= $numbering-blocks))\"/>\n    <xsl:variable name=\"b-open-figure\"      select=\"$b-number-figure-distinct      and not($figure-nodes)      and ($b-terminal or (@pi:level &gt;= $numbering-figures))\"/>\n    <xsl:variable name=\"b-open-project\"     select=\"$b-number-project-distinct     and not($project-nodes)     and ($b-terminal or (@pi:level &gt;= $numbering-projects))\"/>\n    <xsl:variable name=\"b-open-exercise\"    select=\"$b-number-exercise-distinct    and not($exercise-nodes)    and ($b-terminal or (@pi:level &gt;= $numbering-exercises))\"/>\n    <xsl:variable name=\"b-open-openproblem\" select=\"$b-number-openproblem-distinct and not($openproblem-nodes) and ($b-terminal or (@pi:level &gt;= $numbering-openproblems))\"/>\n    <xsl:variable name=\"next-eq\" select=\"$eq-nodes | self::*[$b-open-eq]//mrow[@pi:numbered = 'yes']\"/>\n    <xsl:variable name=\"next-fn\" select=\"$fn-nodes | self::*[$b-open-fn]//fn\"/>\n    <!-- The shared \"blocks\" pool also gathers figure-likes, projects,  -->\n    <!-- inline exercises, and open problems that are not run distinct. -->\n    <xsl:variable name=\"next-blocks\" select=\"$blocks-nodes\n        | self::*[$b-open-blocks]//*[&FUNDAMENTAL-BLOCK-FILTER;]\n        | self::*[$b-open-blocks and not($b-number-figure-distinct)]//*[&TOP-FIGURE-FILTER;]\n        | self::*[$b-open-blocks and not($b-number-project-distinct)]//*[&PROJECT-FILTER;]\n        | self::*[$b-open-blocks and not($b-number-exercise-distinct)]//exercise[&INLINE-EXERCISE-FILTER;]\n        | self::*[$b-open-blocks and not($b-number-openproblem-distinct)]//*[&OPENPROBLEM-FILTER;]\"/>\n    <xsl:variable name=\"next-figure\"      select=\"$figure-nodes      | self::*[$b-open-figure]//*[&TOP-FIGURE-FILTER;]\"/>\n    <xsl:variable name=\"next-project\"     select=\"$project-nodes     | self::*[$b-open-project]//*[&PROJECT-FILTER;]\"/>\n    <xsl:variable name=\"next-exercise\"    select=\"$exercise-nodes    | self::*[$b-open-exercise]//exercise[&INLINE-EXERCISE-FILTER;]\"/>\n    <xsl:variable name=\"next-openproblem\" select=\"$openproblem-nodes | self::*[$b-open-openproblem]//*[&OPENPROBLEM-FILTER;]\"/>\n    <xsl:copy>\n        <xsl:apply-templates select=\"@*|node()\" mode=\"serial-stamp\">\n            <xsl:with-param name=\"eq-nodes\" select=\"$next-eq\"/>\n            <xsl:with-param name=\"fn-nodes\" select=\"$next-fn\"/>\n            <xsl:with-param name=\"blocks-nodes\" select=\"$next-blocks\"/>\n            <xsl:with-param name=\"figure-nodes\" select=\"$next-figure\"/>\n            <xsl:with-param name=\"project-nodes\" select=\"$next-project\"/>\n            <xsl:with-param name=\"exercise-nodes\" select=\"$next-exercise\"/>\n            <xsl:with-param name=\"openproblem-nodes\" select=\"$next-openproblem\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<!-- Introduction and conclusion of a traditional division.  The match    -->\n<!-- is prefixed with the division names because PreTeXt also uses        -->\n<!-- introduction and conclusion inside exercises, exercisegroups,        -->\n<!-- objectives, and the like.  This is the pooling case above: where the -->\n<!-- parent recursed, the division's own introduction and conclusion pool -->\n<!-- into one scope, subdivisions excluded for free (siblings, not        -->\n<!-- descendants).                                                        -->\n<xsl:template match=\"article/introduction | chapter/introduction | section/introduction | subsection/introduction | appendix/introduction | article/conclusion | chapter/conclusion | section/conclusion | subsection/conclusion | appendix/conclusion\" mode=\"serial-stamp\">\n    <xsl:param name=\"eq-nodes\"/>\n    <xsl:param name=\"fn-nodes\"/>\n    <xsl:param name=\"blocks-nodes\"/>\n    <xsl:param name=\"figure-nodes\"/>\n    <xsl:param name=\"project-nodes\"/>\n    <xsl:param name=\"exercise-nodes\"/>\n    <xsl:param name=\"openproblem-nodes\"/>\n    <xsl:variable name=\"next-eq\" select=\"$eq-nodes | (../introduction | ../conclusion)[not($eq-nodes)]//mrow[@pi:numbered = 'yes']\"/>\n    <xsl:variable name=\"next-fn\" select=\"$fn-nodes | (../introduction | ../conclusion)[not($fn-nodes)]//fn\"/>\n    <xsl:variable name=\"next-blocks\" select=\"$blocks-nodes\n        | (../introduction | ../conclusion)[not($blocks-nodes)]//*[&FUNDAMENTAL-BLOCK-FILTER;]\n        | (../introduction | ../conclusion)[not($blocks-nodes) and not($b-number-figure-distinct)]//*[&TOP-FIGURE-FILTER;]\n        | (../introduction | ../conclusion)[not($blocks-nodes) and not($b-number-project-distinct)]//*[&PROJECT-FILTER;]\n        | (../introduction | ../conclusion)[not($blocks-nodes) and not($b-number-exercise-distinct)]//exercise[&INLINE-EXERCISE-FILTER;]\n        | (../introduction | ../conclusion)[not($blocks-nodes) and not($b-number-openproblem-distinct)]//*[&OPENPROBLEM-FILTER;]\"/>\n    <xsl:variable name=\"next-figure\"      select=\"$figure-nodes      | (../introduction | ../conclusion)[not($figure-nodes)      and $b-number-figure-distinct]//*[&TOP-FIGURE-FILTER;]\"/>\n    <xsl:variable name=\"next-project\"     select=\"$project-nodes     | (../introduction | ../conclusion)[not($project-nodes)     and $b-number-project-distinct]//*[&PROJECT-FILTER;]\"/>\n    <xsl:variable name=\"next-exercise\"    select=\"$exercise-nodes    | (../introduction | ../conclusion)[not($exercise-nodes)    and $b-number-exercise-distinct]//exercise[&INLINE-EXERCISE-FILTER;]\"/>\n    <xsl:variable name=\"next-openproblem\" select=\"$openproblem-nodes | (../introduction | ../conclusion)[not($openproblem-nodes) and $b-number-openproblem-distinct]//*[&OPENPROBLEM-FILTER;]\"/>\n    <xsl:copy>\n        <xsl:apply-templates select=\"@*|node()\" mode=\"serial-stamp\">\n            <xsl:with-param name=\"eq-nodes\" select=\"$next-eq\"/>\n            <xsl:with-param name=\"fn-nodes\" select=\"$next-fn\"/>\n            <xsl:with-param name=\"blocks-nodes\" select=\"$next-blocks\"/>\n            <xsl:with-param name=\"figure-nodes\" select=\"$next-figure\"/>\n            <xsl:with-param name=\"project-nodes\" select=\"$next-project\"/>\n            <xsl:with-param name=\"exercise-nodes\" select=\"$next-exercise\"/>\n            <xsl:with-param name=\"openproblem-nodes\" select=\"$next-openproblem\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<!-- Numbered mrow.  Stamp @pi:serial with the position within the -->\n<!-- inherited node-set.                                           -->\n<xsl:template match=\"mrow[@pi:numbered = 'yes']\" mode=\"serial-stamp\">\n    <xsl:param name=\"eq-nodes\"/>\n    <xsl:param name=\"fn-nodes\"/>\n    <xsl:param name=\"blocks-nodes\"/>\n    <xsl:param name=\"figure-nodes\"/>\n    <xsl:param name=\"project-nodes\"/>\n    <xsl:param name=\"exercise-nodes\"/>\n    <xsl:param name=\"openproblem-nodes\"/>\n    <xsl:copy>\n        <xsl:attribute name=\"pi:serial\">\n            <xsl:apply-templates select=\".\" mode=\"position-in-node-set\">\n                <xsl:with-param name=\"nodes\" select=\"$eq-nodes\"/>\n            </xsl:apply-templates>\n        </xsl:attribute>\n        <xsl:apply-templates select=\"@*|node()\" mode=\"serial-stamp\">\n            <xsl:with-param name=\"eq-nodes\" select=\"$eq-nodes\"/>\n            <xsl:with-param name=\"fn-nodes\" select=\"$fn-nodes\"/>\n            <xsl:with-param name=\"blocks-nodes\" select=\"$blocks-nodes\"/>\n            <xsl:with-param name=\"figure-nodes\" select=\"$figure-nodes\"/>\n            <xsl:with-param name=\"project-nodes\" select=\"$project-nodes\"/>\n            <xsl:with-param name=\"exercise-nodes\" select=\"$exercise-nodes\"/>\n            <xsl:with-param name=\"openproblem-nodes\" select=\"$openproblem-nodes\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<!-- Every fn is numbered.  Stamp @pi:serial with the position -->\n<!-- within the inherited footnote node-set.                   -->\n<xsl:template match=\"fn\" mode=\"serial-stamp\">\n    <xsl:param name=\"eq-nodes\"/>\n    <xsl:param name=\"fn-nodes\"/>\n    <xsl:param name=\"blocks-nodes\"/>\n    <xsl:param name=\"figure-nodes\"/>\n    <xsl:param name=\"project-nodes\"/>\n    <xsl:param name=\"exercise-nodes\"/>\n    <xsl:param name=\"openproblem-nodes\"/>\n    <xsl:copy>\n        <xsl:attribute name=\"pi:serial\">\n            <xsl:apply-templates select=\".\" mode=\"position-in-node-set\">\n                <xsl:with-param name=\"nodes\" select=\"$fn-nodes\"/>\n            </xsl:apply-templates>\n        </xsl:attribute>\n        <xsl:apply-templates select=\"@*|node()\" mode=\"serial-stamp\">\n            <xsl:with-param name=\"eq-nodes\" select=\"$eq-nodes\"/>\n            <xsl:with-param name=\"fn-nodes\" select=\"$fn-nodes\"/>\n            <xsl:with-param name=\"blocks-nodes\" select=\"$blocks-nodes\"/>\n            <xsl:with-param name=\"figure-nodes\" select=\"$figure-nodes\"/>\n            <xsl:with-param name=\"project-nodes\" select=\"$project-nodes\"/>\n            <xsl:with-param name=\"exercise-nodes\" select=\"$exercise-nodes\"/>\n            <xsl:with-param name=\"openproblem-nodes\" select=\"$openproblem-nodes\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<!-- Block stamps: serial from the group's distinct counter, else the shared \"blocks\". -->\n<!-- A subnumbered side-by-side panel is not a \"top\" figure, so it falls to the         -->\n<!-- catch-all (no @pi:serial) and earns a letter downstream instead.                   -->\n\n<!-- Fundamental blocks always share the \"blocks\" counter. -->\n<xsl:template match=\"&DEFINITION-LIKE;|&THEOREM-LIKE;|&AXIOM-LIKE;|&REMARK-LIKE;|&COMPUTATION-LIKE;|&EXAMPLE-LIKE;\" mode=\"serial-stamp\">\n    <xsl:param name=\"eq-nodes\"/>\n    <xsl:param name=\"fn-nodes\"/>\n    <xsl:param name=\"blocks-nodes\"/>\n    <xsl:param name=\"figure-nodes\"/>\n    <xsl:param name=\"project-nodes\"/>\n    <xsl:param name=\"exercise-nodes\"/>\n    <xsl:param name=\"openproblem-nodes\"/>\n    <xsl:copy>\n        <xsl:attribute name=\"pi:serial\">\n            <xsl:apply-templates select=\".\" mode=\"position-in-node-set\">\n                <xsl:with-param name=\"nodes\" select=\"$blocks-nodes\"/>\n            </xsl:apply-templates>\n        </xsl:attribute>\n        <xsl:apply-templates select=\"@*|node()\" mode=\"serial-stamp\">\n            <xsl:with-param name=\"eq-nodes\" select=\"$eq-nodes\"/>\n            <xsl:with-param name=\"fn-nodes\" select=\"$fn-nodes\"/>\n            <xsl:with-param name=\"blocks-nodes\" select=\"$blocks-nodes\"/>\n            <xsl:with-param name=\"figure-nodes\" select=\"$figure-nodes\"/>\n            <xsl:with-param name=\"project-nodes\" select=\"$project-nodes\"/>\n            <xsl:with-param name=\"exercise-nodes\" select=\"$exercise-nodes\"/>\n            <xsl:with-param name=\"openproblem-nodes\" select=\"$openproblem-nodes\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<!-- Projects: distinct counter when split out, else the \"blocks\" counter. -->\n<xsl:template match=\"&PROJECT-LIKE;\" mode=\"serial-stamp\">\n    <xsl:param name=\"eq-nodes\"/>\n    <xsl:param name=\"fn-nodes\"/>\n    <xsl:param name=\"blocks-nodes\"/>\n    <xsl:param name=\"figure-nodes\"/>\n    <xsl:param name=\"project-nodes\"/>\n    <xsl:param name=\"exercise-nodes\"/>\n    <xsl:param name=\"openproblem-nodes\"/>\n    <xsl:copy>\n        <xsl:attribute name=\"pi:serial\">\n            <xsl:apply-templates select=\".\" mode=\"position-in-node-set\">\n                <xsl:with-param name=\"nodes\" select=\"$project-nodes[$b-number-project-distinct] | $blocks-nodes[not($b-number-project-distinct)]\"/>\n            </xsl:apply-templates>\n        </xsl:attribute>\n        <xsl:apply-templates select=\"@*|node()\" mode=\"serial-stamp\">\n            <xsl:with-param name=\"eq-nodes\" select=\"$eq-nodes\"/>\n            <xsl:with-param name=\"fn-nodes\" select=\"$fn-nodes\"/>\n            <xsl:with-param name=\"blocks-nodes\" select=\"$blocks-nodes\"/>\n            <xsl:with-param name=\"figure-nodes\" select=\"$figure-nodes\"/>\n            <xsl:with-param name=\"project-nodes\" select=\"$project-nodes\"/>\n            <xsl:with-param name=\"exercise-nodes\" select=\"$exercise-nodes\"/>\n            <xsl:with-param name=\"openproblem-nodes\" select=\"$openproblem-nodes\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<!-- Top-level figure-likes: distinct counter when split out, else \"blocks\". -->\n<xsl:template match=\"*[&TOP-FIGURE-FILTER;]\" mode=\"serial-stamp\">\n    <xsl:param name=\"eq-nodes\"/>\n    <xsl:param name=\"fn-nodes\"/>\n    <xsl:param name=\"blocks-nodes\"/>\n    <xsl:param name=\"figure-nodes\"/>\n    <xsl:param name=\"project-nodes\"/>\n    <xsl:param name=\"exercise-nodes\"/>\n    <xsl:param name=\"openproblem-nodes\"/>\n    <xsl:copy>\n        <xsl:attribute name=\"pi:serial\">\n            <xsl:apply-templates select=\".\" mode=\"position-in-node-set\">\n                <xsl:with-param name=\"nodes\" select=\"$figure-nodes[$b-number-figure-distinct] | $blocks-nodes[not($b-number-figure-distinct)]\"/>\n            </xsl:apply-templates>\n        </xsl:attribute>\n        <xsl:apply-templates select=\"@*|node()\" mode=\"serial-stamp\">\n            <xsl:with-param name=\"eq-nodes\" select=\"$eq-nodes\"/>\n            <xsl:with-param name=\"fn-nodes\" select=\"$fn-nodes\"/>\n            <xsl:with-param name=\"blocks-nodes\" select=\"$blocks-nodes\"/>\n            <xsl:with-param name=\"figure-nodes\" select=\"$figure-nodes\"/>\n            <xsl:with-param name=\"project-nodes\" select=\"$project-nodes\"/>\n            <xsl:with-param name=\"exercise-nodes\" select=\"$exercise-nodes\"/>\n            <xsl:with-param name=\"openproblem-nodes\" select=\"$openproblem-nodes\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<!-- Inline exercises: distinct counter when split out, else \"blocks\". -->\n<xsl:template match=\"exercise[&INLINE-EXERCISE-FILTER;]\" mode=\"serial-stamp\">\n    <xsl:param name=\"eq-nodes\"/>\n    <xsl:param name=\"fn-nodes\"/>\n    <xsl:param name=\"blocks-nodes\"/>\n    <xsl:param name=\"figure-nodes\"/>\n    <xsl:param name=\"project-nodes\"/>\n    <xsl:param name=\"exercise-nodes\"/>\n    <xsl:param name=\"openproblem-nodes\"/>\n    <xsl:copy>\n        <xsl:attribute name=\"pi:serial\">\n            <xsl:apply-templates select=\".\" mode=\"position-in-node-set\">\n                <xsl:with-param name=\"nodes\" select=\"$exercise-nodes[$b-number-exercise-distinct] | $blocks-nodes[not($b-number-exercise-distinct)]\"/>\n            </xsl:apply-templates>\n        </xsl:attribute>\n        <xsl:apply-templates select=\"@*|node()\" mode=\"serial-stamp\">\n            <xsl:with-param name=\"eq-nodes\" select=\"$eq-nodes\"/>\n            <xsl:with-param name=\"fn-nodes\" select=\"$fn-nodes\"/>\n            <xsl:with-param name=\"blocks-nodes\" select=\"$blocks-nodes\"/>\n            <xsl:with-param name=\"figure-nodes\" select=\"$figure-nodes\"/>\n            <xsl:with-param name=\"project-nodes\" select=\"$project-nodes\"/>\n            <xsl:with-param name=\"exercise-nodes\" select=\"$exercise-nodes\"/>\n            <xsl:with-param name=\"openproblem-nodes\" select=\"$openproblem-nodes\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<!-- Open problems: distinct counter when split out, else \"blocks\". -->\n<xsl:template match=\"&OPENPROBLEM-LIKE;\" mode=\"serial-stamp\">\n    <xsl:param name=\"eq-nodes\"/>\n    <xsl:param name=\"fn-nodes\"/>\n    <xsl:param name=\"blocks-nodes\"/>\n    <xsl:param name=\"figure-nodes\"/>\n    <xsl:param name=\"project-nodes\"/>\n    <xsl:param name=\"exercise-nodes\"/>\n    <xsl:param name=\"openproblem-nodes\"/>\n    <xsl:copy>\n        <xsl:attribute name=\"pi:serial\">\n            <xsl:apply-templates select=\".\" mode=\"position-in-node-set\">\n                <xsl:with-param name=\"nodes\" select=\"$openproblem-nodes[$b-number-openproblem-distinct] | $blocks-nodes[not($b-number-openproblem-distinct)]\"/>\n            </xsl:apply-templates>\n        </xsl:attribute>\n        <xsl:apply-templates select=\"@*|node()\" mode=\"serial-stamp\">\n            <xsl:with-param name=\"eq-nodes\" select=\"$eq-nodes\"/>\n            <xsl:with-param name=\"fn-nodes\" select=\"$fn-nodes\"/>\n            <xsl:with-param name=\"blocks-nodes\" select=\"$blocks-nodes\"/>\n            <xsl:with-param name=\"figure-nodes\" select=\"$figure-nodes\"/>\n            <xsl:with-param name=\"project-nodes\" select=\"$project-nodes\"/>\n            <xsl:with-param name=\"exercise-nodes\" select=\"$exercise-nodes\"/>\n            <xsl:with-param name=\"openproblem-nodes\" select=\"$openproblem-nodes\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<!-- ############## -->\n<!-- Serial Numbers -->\n<!-- ############## -->\n\n<!-- These templates count the occurences of an element within a       -->\n<!-- subtree.  Sometimes that subtree is rooted just above the element -->\n<!-- (e.g. divisions) or sometimes it is many levels higher, such as   -->\n<!-- when an \"example\" might be in a \"subsubsection\" but they are      -->\n<!-- grouped (\"count within\" in LaTeX-speak) and counted across all    -->\n<!-- \"example\" within a chapter (ignoring the divisions by section,    -->\n<!-- subsection, and subsubsection).                                   -->\n<!--                                                                   -->\n<!-- All of the hard work of counting is done in these templates.      -->\n<!-- Elsewhere, serial numbers are combined with hierarchical          -->\n<!-- numbering of divisions to form \"full\" numbers.                    -->\n\n<!-- Traditional Divisions -->\n<!-- Mostly obvious, counting peers, including specialized         -->\n<!-- divisions.  Roman numerals for parts, letters for appendices. -->\n<xsl:template match=\"part\" mode=\"division-serial-number\">\n    <xsl:number format=\"I\" />\n</xsl:template>\n<xsl:template match=\"chapter\" mode=\"division-serial-number\">\n    <!-- chapters, in parts or not -->\n    <xsl:choose>\n        <xsl:when test=\"($parts = 'absent') or ($parts = 'decorative')\">\n            <xsl:variable name=\"true-count\">\n                <xsl:number from=\"book\" level=\"any\" count=\"chapter\" format=\"1\" />\n            </xsl:variable>\n            <!-- $chapter-start defaults to 1 -->\n            <xsl:value-of select=\"$true-count + $chapter-start - 1\" />\n        </xsl:when>\n        <!-- author-specified chapter start number does  -->\n        <!-- not really make sense for structural parts? -->\n        <xsl:when test=\"$parts = 'structural'\">\n            <xsl:number from=\"part\" count=\"chapter\" format=\"1\" />\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n<!-- A \"solutions\" is a specialized division, but is numbered -->\n<!-- as an appendix when present in the backmatter, so        -->\n<!-- included in the count here.                              -->\n<xsl:template match=\"appendix\" mode=\"division-serial-number\">\n    <xsl:number from=\"backmatter\" level=\"any\" count=\"appendix|solutions\" format=\"A\"/>\n</xsl:template>\n<!-- NB: following do not assume an ordering on the subdivisions,     -->\n<!-- since this has not been solidified in the schema. At that point, -->\n<!-- we might enforce some assumptions here, and elsewhere, by only   -->\n<!-- including predecessors in the @count attribute.                  -->\n<xsl:template match=\"section\" mode=\"division-serial-number\">\n    <xsl:number count=\"section|exercises|reading-questions|solutions|references|glossary|worksheet|handout\" format=\"1\" />\n</xsl:template>\n<xsl:template match=\"subsection\" mode=\"division-serial-number\">\n    <xsl:number count=\"subsection|exercises|reading-questions|solutions|references|glossary|worksheet|handout\" format=\"1\" />\n</xsl:template>\n<xsl:template match=\"subsubsection\" mode=\"division-serial-number\">\n    <xsl:number count=\"subsubsection|exercises|reading-questions|solutions|references|glossary|worksheet|handout\" format=\"1\" />\n</xsl:template>\n\n<!-- Specialized Divisions -->\n<!-- \"exercises\", \"solutions\", references, \"worksheet\",-->\n<!-- \"handout\", \"reading-questions\", \"glossary\"        -->\n<!-- This is the case of a \"structured\" division,      -->\n<!-- where we use the resulting number for the         -->\n<!-- division. (In the unstructured case, the number   -->\n<!-- will be inherited from the parent, so this number -->\n<!-- is incorrect, meaningless, and ignored.)  So we   -->\n<!-- simply count preceding peers.  Note that every    -->\n<!-- possible traditional division that could be a     -->\n<!-- peer is listed here in the \"match\", but only one  -->\n<!-- type will actually be present in the structured   -->\n<!-- division.                                         -->\n<xsl:template match=\"exercises|reading-questions|solutions|references|glossary|worksheet|handout\" mode=\"division-serial-number\">\n    <xsl:number count=\"chapter|section|subsection|subsubsection|exercises|reading-questions|solutions|references|glossary|worksheet|handout\" format=\"1\" />\n</xsl:template>\n<!-- Following \"backmatter\" matches will be more specific than above -->\n<!-- A \"solutions\" is a specialized division, but is numbered        -->\n<!-- as an appendix when present in the backmatter, see above        -->\n<xsl:template match=\"backmatter/solutions\" mode=\"division-serial-number\">\n    <xsl:number from=\"backmatter\" level=\"any\" count=\"appendix|solutions\" format=\"A\"/>\n</xsl:template>\n\n<!-- ######################### -->\n<!-- Structured vs. Decorative -->\n<!-- ######################### -->\n\n<!-- These templates determine the structure of divisions, needed    -->\n<!-- during assembly to compute block structure numbers.  They are   -->\n<!-- also used at render time from pretext-common.xsl and elsewhere, -->\n<!-- available via cross-import resolution (every conversion         -->\n<!-- stylesheet imports both pretext-assembly.xsl and                -->\n<!-- pretext-common.xsl).                                            -->\n\n<!-- There are two models for most of the divisions (part -->\n<!-- through subsubsection, plus appendix).  One has      -->\n<!-- subdivisions, and possibly specialized subdivisions. -->\n<!-- The other has no subdivisions, and then at most one  -->\n<!-- of each type of specialized subdivision, which       -->\n<!-- inherit numbers from their parent division. This is  -->\n<!-- the test, which is very similar to \"is-leaf\" in      -->\n<!-- pretext-common.xsl.                                  -->\n<!--                                                      -->\n<!-- A \"part\" must have chapters, so will always return   -->\n<!-- 'true' and for a 'subsubsection' there are no more   -->\n<!-- subdivisions to employ and so will return empty.     -->\n<!--                                                      -->\n<!-- An exception is a division of *only* worksheets.     -->\n<!-- Although there could be titles and the like.         -->\n<!-- So we compare all-children to  metadata + worksheet. -->\n<!-- TODO: should there be a similar exception for handouts? -->\n<xsl:template match=\"book|article|part|chapter|appendix|section|subsection|subsubsection\" mode=\"is-structured-division\">\n    <xsl:variable name=\"has-traditional\" select=\"boolean(&TRADITIONAL-DIVISION;)\"/>\n    <xsl:variable name=\"all-children\" select=\"*\"/>\n    <xsl:variable name=\"all-worksheet\" select=\"title|subtitle|shorttitle|plaintitle|idx|frontmatter|introduction|worksheet|handout|conclusion\"/>\n    <xsl:variable name=\"only-worksheets\" select=\"count($all-children) = count($all-worksheet)\"/>\n\n    <xsl:value-of select=\"$has-traditional or $only-worksheets\"/>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"is-structured-division\">\n    <xsl:message>PTX:BUG: asking if a non-traditional division (<xsl:value-of select=\"local-name(.)\"/>) is structured or not</xsl:message>\n</xsl:template>\n\n<!-- Specialized divisions sometimes inherit a number from their  -->\n<!-- parent (as part of an unstructured division) and sometimes   -->\n<!-- they do not even have a number (singleton \"references\" as    -->\n<!-- child of \"backmatter\").  This template returns \"true\" if a   -->\n<!-- specialized division \"owns\" its \"own\" number.                -->\n<xsl:template match=\"exercises|worksheet|handout|references|glossary|reading-questions|solutions\" mode=\"is-specialized-own-number\">\n    <xsl:choose>\n        <!-- *Some* specialized divisions can appear as a child of the    -->\n        <!-- \"backmatter\" too.  But only those below.  The rest are       -->\n        <!-- banned as top-level items in the backmatter, but might       -->\n        <!-- occur in an \"appendix\" or below, with or without structure.  -->\n        <!--   \"solutions\" will look like an appendix, thus numbered.     -->\n        <!--   \"references\" or \"glossary\" are singletons, never numbered. -->\n        <xsl:when test=\"parent::*[self::backmatter]\">\n            <xsl:choose>\n                <xsl:when test=\"self::solutions\">\n                    <xsl:text>true</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"self::references or self::glossary\">\n                    <xsl:text>false</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:ERROR:   encountered a specialized division (\"<xsl:value-of select=\"local-name(.)\"/>\") as a child of \"backmatter\" that was unexpected.  Results will be unpredictable</xsl:message>\n                    <!-- no idea if we should say true or false here -->\n                    <xsl:text>true</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- parent must now be a \"traditional\" division -->\n        <xsl:otherwise>\n            <xsl:apply-templates select=\"parent::*\" mode=\"is-structured-division\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"is-specialized-own-number\">\n    <xsl:message>PTX:BUG: asking if a non-specialized division (<xsl:value-of select=\"local-name(.)\"/>) is numbered or not</xsl:message>\n    <xsl:text>false</xsl:text>\n</xsl:template>\n\n<!-- ######################## -->\n<!-- Position In a Node-Set   -->\n<!-- ######################## -->\n\n<!-- Returns the document-order position (1-indexed) of the matched -->\n<!-- node within the given node-set.  Uses the union-count identity -->\n<!-- test: count(.|$here) = 1 iff the two are the same node.        -->\n<!-- Empty result if the node is not in the set.                    -->\n<!--                                                                -->\n<!-- Used by the serial-stamp passes to find a node's position -->\n<!-- within a precomputed node-set of its countable peers      -->\n<!-- (equations, footnotes, and the block families).           -->\n<xsl:template match=\"*\" mode=\"position-in-node-set\">\n    <xsl:param name=\"nodes\"/>\n    <!-- Save off the context node before the \"for-each\" switches it. -->\n    <xsl:variable name=\"here\" select=\".\"/>\n    <xsl:for-each select=\"$nodes\">\n        <xsl:if test=\"count(.|$here) = 1\">\n            <xsl:value-of select=\"position()\"/>\n        </xsl:if>\n    </xsl:for-each>\n</xsl:template>\n\n<!-- ########### -->\n<!-- Assembly ID -->\n<!-- ########### -->\n\n<!-- Some maniulations of source require stable identification *before*     -->\n<!-- we assign @pi:unique-id values for general use in the very late        -->\n<!-- \"identification\" phase.  This is a role for the \"@pi:assembly-id\" which-->\n<!-- is formed after the author's source has been versioned, customized,    -->\n<!-- repaired, but before replacements. It should suffice for \"big\" objects -->\n<!-- which are unlikely to change much (other than going away in a version) -->\n<!-- and may only be \"repaired\" in a one-to-one cosmetic rename.  We use    -->\n<!-- this sparingly, thus we are careful about the match, along with        -->\n<!-- documenting rationale for each object.                                 -->\n<!--                                                                        -->\n<!-- Another way to think about this is as an \"early\" id, versus the        -->\n<!-- more general \"late\" id.                                                -->\n<!--                                                                        -->\n<!-- audio|video|interactive                                                -->\n<!--     Static versions of these interactive elements have previews        -->\n<!--     (YouTube thumbnails, automatically generated screenshots),         -->\n<!--     generated QR codes, and various links meant for use in static      -->\n<!--     contexts.  So we form names of these related objects based on      -->\n<!--     an \"earlier\" id.                                                   -->\n<!--                                                                        -->\n<!-- datafile                                                               -->\n<!--     For static versions of this Runestone component, when the file is  -->\n<!--     a text file provided in the external directory, we need to         -->\n<!--     interrogate the file manufactured in the generated directory in    -->\n<!--     order to make a sample of its content.  This happens before we     -->\n<!--     construct unique-id.                                               -->\n\n<!-- NB: we believe the @pi:assembly-id will equal the @pi:unique-id -->\n<!-- (\"unique-id\" template) for objects at the level of blocks,      -->\n<!-- and certainly for any object replaced by a different static     -->\n<!-- representation.  But for generated objects, e.g. QR codes,      -->\n<!-- it would be best if the generation process used the             -->\n<!-- \"assembly-id\" template for guranteed consistency.  This *is*    -->\n<!-- being done for \"datafile\" but is technical debt otherwise.      -->\n\n<!-- [Ed. this once prefaced an early, weak forerunner of the         -->\n<!-- \"assembly-id\" template.  But the commentary                      -->\n<!-- is still good, so we have preserved it here.]                    -->\n<!-- This template produces identification that happens early in the  -->\n<!-- passes this stylesheet executes.  The idea is that some elements -->\n<!-- get replaced wholesale (such as an \"interactive\" being replaced  -->\n<!-- by a \"sidebyside\" in the creation of a static precursor.  But we -->\n<!-- want these ids, especially if automatic, to be consistent when   -->\n<!-- used in derived versions (such as manufacturing, or displaying,  -->\n<!-- a QR code file for a static \"interactive\").                      -->\n<!-- NB: this template needs to be defined in this stylesheet, since  -->\n<!-- we want the stylesheet to be independent, and the template is    -->\n<!-- also applied here.                                               -->\n\n<!-- Every element carrying an \"@pi:assembly-id\" stamp reports it  -->\n<!-- through this single template.  The match list is deliberately -->\n<!-- explicit — media and images, data files, STACK problems, and  -->\n<!-- the fill-in dynamic-substitution owners (the exercise-like    -->\n<!-- elements, or a \"task\" they contain, whichever holds \"setup\")  -->\n<!-- — so the BUG fallback below can catch an unexpected           -->\n<!-- application.                                                  -->\n<xsl:template match=\"audio|video|interactive|image\n                   | datafile\n                   | exercise/stack\n                   | exercise[@pi:exercise-interactive='fillin' and setup]\n                   | project[@pi:exercise-interactive='fillin' and setup]\n                   | activity[@pi:exercise-interactive='fillin' and setup]\n                   | exploration[@pi:exercise-interactive='fillin' and setup]\n                   | investigation[@pi:exercise-interactive='fillin' and setup]\n                   | exercise[.//task and .//task/@pi:exercise-interactive='fillin' and .//setup]\n                   | project[.//task and .//task/@pi:exercise-interactive='fillin' and .//setup]\n                   | activity[.//task and .//task/@pi:exercise-interactive='fillin' and .//setup]\n                   | exploration[.//task and .//task/@pi:exercise-interactive='fillin' and .//setup]\n                   | investigation[.//task and .//task/@pi:exercise-interactive='fillin' and .//setup]\n                   | exercise//task[@pi:exercise-interactive='fillin' and setup]\n                   | project//task[@pi:exercise-interactive='fillin' and setup]\n                   | activity//task[@pi:exercise-interactive='fillin' and setup]\n                   | exploration//task[@pi:exercise-interactive='fillin' and setup]\n                   | investigation//task[@pi:exercise-interactive='fillin' and setup]\" mode=\"assembly-id\">\n    <xsl:value-of select=\"@pi:assembly-id\"/>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"assembly-id\">\n    <xsl:message>\n        <xsl:text>PTX:BUG:  the \"assembly-id\" template was applied to an element it did not expect--</xsl:text>\n        <xsl:value-of select=\"name()\"/>\n        <xsl:text>.</xsl:text>\n        <xsl:value-of select=\"@pi:exercise-interactive\"/>\n        <xsl:text>.</xsl:text>\n        <xsl:value-of select=\"@pi:assembly-id\"/>\n    </xsl:message>\n    <xsl:text>unexpected-assembly-id-template-use-here</xsl:text>\n</xsl:template>\n\n<!-- ###################################### -->\n<!-- Static versions of Interactive Content -->\n<!-- ###################################### -->\n\n<!-- Templates for the pre-processor (and other stylesheets) to use -->\n<!-- for the creation of static versions of interactive content.    -->\n\n<!-- The HTML conversion generates \"standalone\" pages for videos   -->\n<!-- and other interactives.  Then the LaTeX conversion will make  -->\n<!-- links to these pages (eg, via QR codes).  And we might use    -->\n<!-- these pages as the basis for scraping preview images.  So we  -->\n<!-- place a template here to achieve consistency across uses.     -->\n<!--                                                               -->\n<!-- We need to always import this assembly stylesheet, so these   -->\n<!-- templates will be available in all conversions, but notably   -->\n<!-- in the creation of a \"universal\" static version of the        -->\n<!-- document (\"assembly-static\" in the pretext/pretext script)    -->\n<!-- which is fed to specific conversion into static output        -->\n<!-- formats (e.g. LaTeX, braille).  As such, these templates      -->\n<!-- should                                                        -->\n<!--   (a) be applied someplace as part of the assembly process    -->\n<!--   (b) produce only text (i.e. not XML, not HTML, not LaTeX)   -->\n\n\n<!-- NB: it could be tempting to change the next template to stuff -->\n<!-- these \"iframe\" files into a dedicated directory.  Even though -->\n<!-- this template ensures some consistency, a pile of links still -->\n<!-- need to change, such as the \"script\" tag for locations of     -->\n<!-- extra JS as part of making one of these go.                   -->\n<xsl:template match=\"audio|video|interactive\" mode=\"iframe-filename\">\n    <xsl:apply-templates select=\".\" mode=\"assembly-id\" />\n    <xsl:text>-if.html</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"audio|video|interactive\" mode=\"standalone-filename\">\n    <xsl:apply-templates select=\".\" mode=\"assembly-id\" />\n    <xsl:text>.html</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"exercise[@pi:exercise-interactive='fillin' and setup]\n                   | project[@pi:exercise-interactive='fillin' and setup]\n                   | activity[@pi:exercise-interactive='fillin' and setup]\n                   | exploration[@pi:exercise-interactive='fillin' and setup]\n                   | investigation[@pi:exercise-interactive='fillin' and setup]\"\n                   mode=\"standalone-filename\">\n    <xsl:apply-templates select=\".\" mode=\"assembly-id\" />\n    <xsl:text>.html</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"exercise[.//task/@pi:exercise-interactive='fillin' and .//task/setup]\n                   | project[.//task/@pi:exercise-interactive='fillin' and .//task/setup]\n                   | activity[.//task/@pi:exercise-interactive='fillin' and .//task/setup]\n                   | exploration[.//task/@pi:exercise-interactive='fillin' and .//task/setup]\n                   | investigation[.//task/@pi:exercise-interactive='fillin' and .//task/setup]\"\n                   mode=\"standalone-filename\">\n    <xsl:apply-templates select=\".\" mode=\"assembly-id\" />\n    <xsl:text>.html</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"standalone-filename\">\n    <xsl:apply-templates select=\".\" mode=\"unique-id\" />\n    <xsl:text>-ERROR-no-standalone-filename.html</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"audio|video|interactive\" mode=\"standalone-url\">\n    <xsl:if test=\"$b-has-baseurl\">\n        <xsl:value-of select=\"$baseurl\"/>\n        <xsl:apply-templates select=\".\" mode=\"standalone-filename\" />\n    </xsl:if>\n    <!-- empty without a baseurl -->\n</xsl:template>\n\n<xsl:template match=\"audio|video|interactive\" mode=\"embed-iframe-url\">\n    <xsl:if test=\"$b-has-baseurl\">\n        <xsl:value-of select=\"$baseurl\"/>\n        <xsl:apply-templates select=\".\" mode=\"iframe-filename\" />\n    </xsl:if>\n    <!-- empty without a baseurl -->\n</xsl:template>\n\n<!-- These interactives *are* iFrames, so we don't build a dedicated   -->\n<!-- page to make them into iFrames.  Over in -html we construct a URL -->\n<!-- for each one, embedded in a iFrame construction.  We need to work -->\n<!-- out the right thing to do for an \"Embed\" link in static formats.  -->\n<!-- For now, an empty result means no link in sttic formats.          -->\n<!-- NB: coordinate with \"create-iframe-page\" in -html                 -->\n<xsl:template match=\"audio|video\"  mode=\"embed-iframe-url\"/>\n<xsl:template match=\"interactive[@desmos|@geogebra|@calcplot3d|@circuitjs|@iframe]\"  mode=\"embed-iframe-url\"/>\n\n\n<!-- Static URL's -->\n<!-- Predictable and/or stable URLs for versions         -->\n<!-- of interactives available online.  These are        -->\n<!--                                                     -->\n<!--   (1) \"standalone\" pages for author/local material, -->\n<!--       as a product of the HTML conversion           -->\n<!--   (2) computable addresses of network resources,    -->\n<!--       eg the YouTube page of a resource             -->\n\n<!-- Point to HTML-produced, and canonically-hosted, standalone page -->\n<!-- NB: baseurl is assumed to have a trailing slash                 -->\n\n<xsl:template match=\"audio[@source|@href]|video[@source|@href]|interactive\" mode=\"static-url\">\n    <xsl:value-of select=\"$baseurl\"/>\n    <xsl:apply-templates select=\".\" mode=\"standalone-filename\" />\n</xsl:template>\n\n<!-- Natural override for YouTube videos               -->\n<!-- Better - standalone page, with \"View on You Tube\" -->\n\n<!-- NB: this is a genuine URL, with no escaping: consumers apply     -->\n<!-- their own (the LaTeX conversion escapes the ampersand for its    -->\n<!-- \"\\href\", HTML-derived conversions use it as-is, and the QR code  -->\n<!-- generator must encode exactly what a phone's camera should see). -->\n\n<xsl:template match=\"video[@youtube|@youtubeplaylist]\" mode=\"static-url\">\n    <xsl:apply-templates select=\".\" mode=\"youtube-view-url\" />\n    <xsl:if test=\"@start\">\n        <xsl:text>&amp;start=</xsl:text>\n        <xsl:value-of select=\"@start\" />\n    </xsl:if>\n    <xsl:if test=\"@end\">\n        <xsl:text>&amp;end=</xsl:text>\n        <xsl:value-of select=\"@end\" />\n    </xsl:if>\n</xsl:template>\n\n<xsl:template match=\"video[@youtube|@youtubeplaylist]\" mode=\"youtube-view-url\">\n    <xsl:variable name=\"youtube\">\n        <xsl:choose>\n            <xsl:when test=\"@youtubeplaylist\">\n                <xsl:value-of select=\"normalize-space(@youtubeplaylist)\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"normalize-space(str:replace(@youtube, ',', ' '))\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:text>https://www.youtube.com/</xsl:text>\n    <xsl:choose>\n        <xsl:when test=\"@youtubeplaylist\">\n            <xsl:text>playlist?list=</xsl:text>\n            <xsl:value-of select=\"$youtube\" />\n        </xsl:when>\n        <xsl:when test=\"contains($youtube, ' ')\">\n            <xsl:text>watch_videos?video_ids=</xsl:text>\n            <xsl:value-of select=\"str:replace($youtube, ' ', ',')\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>watch?v=</xsl:text>\n            <xsl:value-of select=\"$youtube\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Vimeo view URL -->\n<xsl:template match=\"video[@vimeo]\" mode=\"static-url\">\n    <xsl:text>https://vimeo.com/</xsl:text>\n    <xsl:value-of select=\"@vimeo\"/>\n</xsl:template>\n\n<!-- A bit different than above, but same mode -->\n<!-- When a \"datafile\" is produced in a static -->\n<!-- context, then we append the $baseurl, and -->\n<!-- provide the external directory.           -->\n<xsl:template match=\"dataurl[@source]\" mode=\"static-url\">\n    <xsl:value-of select=\"$baseurl\"/>\n    <!-- empty when not using managed directories -->\n    <xsl:value-of select=\"$external-directory\"/>\n    <xsl:apply-templates select=\"@source\" />\n</xsl:template>\n\n<!-- The contents of a datafile may be encoded as text in an XML   -->\n<!-- file within the generated/datafile directory.  The filename   -->\n<!-- has this construction, even if we do not always consult it.   -->\n<!-- NB: these XML files will be read with a \"document()\" call,    -->\n<!-- with a path relative to the author's main source file, hence  -->\n<!-- the filename uses the directory name in author's source.      -->\n<!-- NB: identical code in static constructions.                   -->\n<xsl:template match=\"datafile\" mode=\"datafile-filename\">\n    <xsl:value-of select=\"$generated-directory-source\"/>\n    <xsl:text>datafile/</xsl:text>\n    <!-- context is \"datafile\", the basis for identifier -->\n    <!-- ned an early identifier in assembly phase       -->\n    <xsl:apply-templates select=\".\" mode=\"assembly-id\"/>\n    <xsl:text>.xml</xsl:text>\n</xsl:template>\n\n<!-- The actual text contents of a \"datafile\", specified in a \"pre\" element.  -->\n<!-- We assume (enforce) a \"pre\" child.  Then actual text comes authored in   -->\n<!-- the source \"pre\" element or in an author-provided external file.         -->\n<xsl:template match=\"datafile[pre]\" mode=\"datafile-text-contents\">\n    <xsl:choose>\n        <!-- via an external file -->\n        <!-- Once upon a time, we hit the text from a file with   -->\n        <!-- \"sanitize-text\".  This was a bad idea because        -->\n        <!--   (a) the manipulations (especially pad-length (?) ) -->\n        <!--       caused a false infinite recursion warning, and -->\n        <!--   (b) the file should be *exactly* what is desired.  -->\n        <xsl:when test=\"pre/@source\">\n            <!-- filename is relative to author's source -->\n            <xsl:variable name=\"data-filename\">\n                <xsl:apply-templates select=\".\"  mode=\"datafile-filename\"/>\n            </xsl:variable>\n            <xsl:variable name=\"text-file-elt\" select=\"document($data-filename, $original)/pi:text-file\"/>\n            <xsl:value-of select=\"$text-file-elt\"/>\n        </xsl:when>\n        <!-- via source \"pre\" element content -->\n        <xsl:otherwise>\n            <xsl:call-template name=\"sanitize-text\">\n                <xsl:with-param name=\"text\">\n                    <xsl:value-of select=\"pre\"/>\n                </xsl:with-param>\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n</xsl:stylesheet>\n","pretext-common.xsl":"<?xml version='1.0'?> <!-- As XML file -->\n\n<!--********************************************************************\nCopyright (C) 2013-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- http://pimpmyxslt.com/articles/entity-tricks-part2/ -->\n<!DOCTYPE xsl:stylesheet [\n    <!ENTITY % entities SYSTEM \"entities.ent\">\n    %entities;\n]>\n\n<!-- Identify as a stylesheet -->\n<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\"\n    xmlns:xml=\"http://www.w3.org/XML/1998/namespace\"\n    xmlns:pi=\"http://pretextbook.org/2020/pretext/internal\"\n    xmlns:date=\"http://exslt.org/dates-and-times\"\n    xmlns:exsl=\"http://exslt.org/common\"\n    xmlns:str=\"http://exslt.org/strings\"\n    xmlns:dyn=\"http://exslt.org/dynamic\"\n    extension-element-prefixes=\"pi exsl date str dyn\"\n    xmlns:pf=\"https://prefigure.org\"\n>\n\n<!-- PreTeXt common templates                             -->\n<!-- Text creation/manipulation common to HTML, TeX, Sage -->\n\n<!-- This collection of XSL routines is like a base library,          -->\n<!-- it has no entry template and hence used by itself almost         -->\n<!-- nothing should happen.  Typically the situation looks like this: -->\n<!-- (example is LaTeX-specific but generalizes easily)               -->\n<!--                                                                  -->\n<!-- your-book-latex.xsl                                              -->\n<!--   (a) is what you use on the command line                        -->\n<!--   (b) contains very specific, atomic overrides for your project  -->\n<!--   (c) imports xsl/pretext-latex.xsl                             -->\n<!--                                                                  -->\n<!-- xsl/pretext-latex.xsl                                           -->\n<!--   (a) general conversion from PTX to LaTeX                       -->\n<!--   (b) could be used at the command line for default conversion   -->\n<!--   (c) imports xsl/pretext-common.xsl                            -->\n<!--                                                                  -->\n<!-- xsl/pretext-common.xsl                                          -->\n<!--   (a) this file                                                  -->\n<!--   (b) ensures commonality, such as text versions                 -->\n<!--       of numbers for theorems, equations, etc                    -->\n<!--   (c) has some abstract routines that require implementation     -->\n<!--       in files above, such as file wrapping for a LaTeX file     -->\n<!--       in this case                                               -->\n<!--                                                                  -->\n<!-- This creates a linear sequence of imports, so overrides          -->\n<!-- behave as you might expect or predict.                           -->\n<!-- To do otherwise is to invite confusion.                          -->\n\n<!-- Output methods here are just pure text -->\n<xsl:output method=\"text\" />\n\n<!-- Parameters to pass via xsltproc \"stringparam\" on command-line            -->\n<!-- Or make a thin customization layer and use 'select' to provide overrides -->\n<!-- These here are independent of the output format as well                  -->\n\n<!-- Author tools are for drafts, mostly \"todo\" items  -->\n<!-- and \"provisional\" citations and cross-references  -->\n<!-- Default is to hide todo's, inline provisionals    -->\n<!-- Otherwise ('yes'), todo's show in red paragraphs, -->\n<!-- provisional cross-references show in red          -->\n<xsl:param name=\"author.tools\" select=\"''\" />\n\n<!-- The Godot engine version used for GDScript.  Read both by the   -->\n<!-- conversion to Runestone, for the Web Assembly shell, and by the -->\n<!-- \"pck\" extraction, which runs as a separate command.  A default  -->\n<!-- in each would let the two silently disagree.                    -->\n<xsl:param name=\"godot.version\" select=\"'4.6.3'\"/>\n\n<!-- ######### -->\n<!-- Variables -->\n<!-- ######### -->\n\n<!-- The single quote character cannot be directly     -->\n<!-- used in a string in XSLT functions, not even as   -->\n<!-- &apos;. But if it is stored as a variable, then   -->\n<!-- XSLT 1.0 will be OK with using $apos.             -->\n<!-- Use like \"concat('L',$apos,'Hospital')\"           -->\n<!-- Unicode Character 'APOSTROPHE' (U+0027)           -->\n<xsl:variable name=\"apos\">&#x0027;</xsl:variable>\n\n<!-- Here we perform manipulations of math elements and subsequent  -->\n<!-- text nodes that lead with punctuation.  Basically, punctuation -->\n<!-- can migrate from the start of the text node and into the math, -->\n<!-- wrapped in a \\text{}.  We generally do this to display math as -->\n<!-- a service to authors.  MathJax needs help for inline math.     -->\n<!-- Braille and audio do not do so well with this manipulation.    -->\n<!-- These variables are meant to be set by other stylesheets in    -->\n<!-- various situations and there should be no cause for authors to -->\n<!-- change them (this no elaborate error-checking, etc.)           -->\n<xsl:variable name=\"math.punctuation.include\" select=\"'none'\"/>\n<xsl:variable name=\"b-include-inline\"\n    select=\"($math.punctuation.include = 'inline')  or ($math.punctuation.include = 'all')\"/>\n<xsl:variable name=\"b-include-display\"\n    select=\"($math.punctuation.include = 'display') or ($math.punctuation.include = 'all')\"/>\n\n<!-- We set this variable a bit differently -->\n<!-- for different conversions, so this is  -->\n<!-- basically an abstract implementation   -->\n<xsl:variable name=\"chunk-level\" select=\"number(0)\"/>\n\n<!-- The pre-processing stylesheet (\"pretext-assembly.xsl\") guarantees   -->\n<!-- a root \"pretext\" element with a valid @xml:lang, even if it is the  -->\n<!-- default \"en-US\".                                                    -->\n<xsl:variable name=\"document-language\">\n    <xsl:value-of select=\"$root/@xml:lang\"/>\n</xsl:variable>\n\n<!-- An author may elect to place a unique string into   -->\n<!-- the docinfo/document-id element and conversions may -->\n<!-- use this to distinguish one document from another.  -->\n<!-- The global variable here is empty to signal         -->\n<!-- \"no choice\" by the author.                          -->\n<!-- NB: at some point this should be specified as an    -->\n<!-- attribute, rather than as content, which would make -->\n<!-- things like newlines less likely to appear.  Much   -->\n<!-- as \"doucment-id/@edition\" is given.  Keep the       -->\n<!-- normalizationcan, it just becomes less necessary.   -->\n<xsl:variable name=\"document-id\">\n    <xsl:value-of select=\"normalize-space($docinfo/document-id)\"/>\n</xsl:variable>\n\n<!-- And an edition is critical for maintaing the -->\n<!-- Runestone database, though it may have other -->\n<!-- uses related to maintaining changes.         -->\n<xsl:variable name=\"edition\">\n    <xsl:value-of select=\"normalize-space($docinfo/document-id/@edition)\"/>\n</xsl:variable>\n\n<!-- The new version can return to the generic version  -->\n<!-- once we kill the dashed version for author use.    -->\n<xsl:variable name=\"author-tools-new\">\n    <xsl:choose>\n        <!-- respect old switch, if set properly -->\n        <!-- but don't error check or anything   -->\n        <xsl:when test=\"$author-tools = 'yes'\">\n            <xsl:text>yes</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$author-tools = 'no'\">\n            <xsl:text>no</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$author.tools = 'yes'\">\n            <xsl:text>yes</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$author.tools = 'no'\">\n            <xsl:text>no</xsl:text>\n        </xsl:when>\n        <!-- could error-check not-empty here -->\n        <!-- default is \"no\"                  -->\n        <xsl:otherwise>\n            <xsl:text>no</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n\n<!-- ############### -->\n<!-- Source Analysis -->\n<!-- ############### -->\n\n<!-- We check certain aspects of the source and record the results  -->\n<!-- in boolean ($b-has-*) variables or as particular nodes high    -->\n<!-- up in the structure ($document-root).  Scans here in -common   -->\n<!-- should be short and definite (no searching paths with //!),    -->\n<!-- and universally useful, largely conveniences for consistency.  -->\n<!-- Remember that many basic templates are shared out of this      -->\n<!-- file for often very simple conversions (e.g. extractions)      -->\n<!-- so excessive setup is an unnecessary drain on processing time. -->\n<!-- $root, $docinfo, $document-root are a product of the           -->\n<!-- \"pretext-assembly.xsl\" stylesheet                              -->\n\n<!-- \"book\" and \"article\" are sometimes different, esp. for LaTeX -->\n<xsl:variable name=\"b-is-book\"    select=\"$document-root/self::book\" />\n<xsl:variable name=\"b-is-article\" select=\"$document-root/self::article\" />\n<!-- w/, w/o parts induces variants                                   -->\n<!-- NB: computed from the *assembled* root; the version-tree analog, -->\n<!-- $version-has-parts in publisher-variables.xsl, is the            -->\n<!-- pre-assembly fact — same concept, deliberately distinct name.    -->\n<xsl:variable name=\"b-has-parts\" select=\"boolean($root/book/part)\" />\n\n<!-- File extensions can be set globally for a conversion, -->\n<!-- we set it here to something outlandish                -->\n<!-- This should be overridden in an importing stylesheet  -->\n<xsl:variable name=\"file-extension\" select=\"'.need-to-set-file-extension-variable'\" />\n\n<!-- We preserve action of the \"autoname\" parameter         -->\n<!-- But originally the default was \"no\", and now is        -->\n<!-- equivalent to \"yes\".  We set to blank on creation,     -->\n<!-- so we can see if there is command-line action          -->\n<!-- There is a warning that the default behavior has       -->\n<!-- changed, and a warning that setting this is deprecated -->\n<!-- (Deprecation 2017-07-25) -->\n<xsl:variable name=\"legacy-autoname\">\n    <xsl:choose>\n        <!-- nothing on command-line, nothing in docinfo    -->\n        <!-- then this is what will be used globally        -->\n        <!-- so preserve this behavior when this is removed -->\n        <xsl:when test=\"$autoname = ''\">\n            <xsl:text>unset</xsl:text>\n        </xsl:when>\n        <!-- legacy had zero error-checking -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$autoname\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- Employing variants of the text displayed for a cross-reference  -->\n<!-- affects the words shown to the reader, and hence is a choice    -->\n<!-- preserved in the source, and is not just a processing decision  -->\n<!-- $xref-text-style is the global choice, based on                 -->\n<!--   docinfo/defaults/xrefs/@text                                  -->\n<!-- The \"repair\" phase of assembly normalizes the retired           -->\n<!-- \"cross-references\" element to this location, so one path serves -->\n<!-- We control the possible values with the schema, allowing junk   -->\n<!-- NB: blank is not set, and is ignored so the legacy-autoname     -->\n<!-- scheme controls the global default.  When that goes away, we    -->\n<!-- should set the default here when there is no attribute.         -->\n<xsl:variable name=\"xref-text-style\">\n    <xsl:choose>\n        <xsl:when test=\"$docinfo/defaults/xrefs/@text\">\n            <xsl:value-of select=\"$docinfo/defaults/xrefs/@text\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <text />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- To forward-reference solutions to exercises, we need       -->\n<!-- to know which ones atually have solutions in place later.  -->\n<!-- So we build 30 node-lists according to the direct product  -->\n<!--                                                            -->\n<!--   {inline, divisional, worksheet, reading, project}        -->\n<!--     x                                                      -->\n<!--   {hint, answer, solution}                                 -->\n<!--     x                                                      -->\n<!--   {main, back}                                             -->\n<!--                                                            -->\n<!-- iff they are elected to be displayed at some point         -->\n<!-- (intra-division or back matter) via a \"solutions\" element. -->\n<!--                                                            -->\n<!-- First, we provide enough of a path to clearly identify the -->\n<!-- exercise component and its location, allowing steps where  -->\n<!-- there may be intervening structure (such as an             -->\n<!-- \"exercisegroup\").  Careful - a component in a \"worksheet\"  -->\n<!-- can be part of an \"exercise\" (worksheet exercise) or part  -->\n<!-- of \"project\" inside a worksheet.                           -->\n<!--                                                            -->\n<!-- Second, we condition on whether there is a                 -->\n<!-- backmatter/solutions  that elects inclusion of the         -->\n<!-- component, or if there is a containing division which      -->\n<!-- contains a solutions (ancestor::*/child::solutions)        -->\n<!-- with the same election.                                    -->\n\n<!-- Hint, Main Matter -->\n<xsl:variable name=\"inline-hint-main\"     select=\"$document-root//exercise[&INLINE-EXERCISE-FILTER;]//hint[ancestor::*/solutions[contains(@inline, 'hint')]]\"/>\n<xsl:variable name=\"divisional-hint-main\" select=\"$document-root//exercises//hint[ancestor::*/solutions[contains(@divisional, 'hint')]]\"/>\n<xsl:variable name=\"worksheet-hint-main\"  select=\"$document-root//worksheet//exercise//hint[ancestor::*/solutions[contains(@worksheet, 'hint')]]\"/>\n<xsl:variable name=\"reading-hint-main\"    select=\"$document-root//reading-questions//hint[ancestor::*/solutions[contains(@reading, 'hint')]]\"/>\n<xsl:variable name=\"project-hint-main\"    select=\"$document-root//*[&PROJECT-FILTER;]//hint[ancestor::*/solutions[contains(@project, 'hint')]]\"/>\n<!-- Hint, Back Matter -->\n<xsl:variable name=\"inline-hint-back\"     select=\"$document-root//exercise[&INLINE-EXERCISE-FILTER;]//hint[$document-root/backmatter/solutions[contains(@inline, 'hint')]]\"/>\n<xsl:variable name=\"divisional-hint-back\" select=\"$document-root//exercises//hint[$document-root/backmatter/solutions[contains(@divisional, 'hint')]]\"/>\n<xsl:variable name=\"worksheet-hint-back\"  select=\"$document-root//worksheet//exercise//hint[$document-root/backmatter/solutions[contains(@worksheet, 'hint')]]\"/>\n<xsl:variable name=\"reading-hint-back\"    select=\"$document-root//reading-questions//hint[$document-root/backmatter/solutions[contains(@reading, 'hint')]]\"/>\n<xsl:variable name=\"project-hint-back\"    select=\"$document-root//*[&PROJECT-FILTER;]//hint[$document-root/backmatter/solutions[contains(@project, 'hint')]]\"/>\n<!-- Answer, Main Matter -->\n<xsl:variable name=\"inline-answer-main\"     select=\"$document-root//exercise[&INLINE-EXERCISE-FILTER;]//answer[ancestor::*/solutions[contains(@inline, 'answer')]]\"/>\n<xsl:variable name=\"divisional-answer-main\" select=\"$document-root//exercises//answer[ancestor::*/solutions[contains(@divisional, 'answer')]]\"/>\n<xsl:variable name=\"worksheet-answer-main\"  select=\"$document-root//worksheet//exercise//answer[ancestor::*/solutions[contains(@worksheet, 'answer')]]\"/>\n<xsl:variable name=\"reading-answer-main\"    select=\"$document-root//reading-questions//answer[ancestor::*/solutions[contains(@reading, 'answer')]]\"/>\n<xsl:variable name=\"project-answer-main\"    select=\"$document-root//*[&PROJECT-FILTER;]//answer[ancestor::*/solutions[contains(@project, 'answer')]]\"/>\n<!-- Answer, Back Matter -->\n<xsl:variable name=\"inline-answer-back\"     select=\"$document-root//exercise[&INLINE-EXERCISE-FILTER;]//answer[$document-root/backmatter/solutions[contains(@inline, 'answer')]]\"/>\n<xsl:variable name=\"divisional-answer-back\" select=\"$document-root//exercises//answer[$document-root/backmatter/solutions[contains(@divisional, 'answer')]]\"/>\n<xsl:variable name=\"worksheet-answer-back\"  select=\"$document-root//worksheet//exercise//answer[$document-root/backmatter/solutions[contains(@worksheet, 'answer')]]\"/>\n<xsl:variable name=\"reading-answer-back\"    select=\"$document-root//reading-questions//answer[$document-root/backmatter/solutions[contains(@reading, 'answer')]]\"/>\n<xsl:variable name=\"project-answer-back\"    select=\"$document-root//*[&PROJECT-FILTER;]//answer[$document-root/backmatter/solutions[contains(@project, 'answer')]]\"/>\n<!-- Solution, Main Matter -->\n<xsl:variable name=\"inline-solution-main\"     select=\"$document-root//exercise[&INLINE-EXERCISE-FILTER;]//solution[ancestor::*/solutions[contains(@inline, 'solution')]]\"/>\n<xsl:variable name=\"divisional-solution-main\" select=\"$document-root//exercises//solution[ancestor::*/solutions[contains(@divisional, 'solution')]]\"/>\n<xsl:variable name=\"worksheet-solution-main\"  select=\"$document-root//worksheet//exercise//solution[ancestor::*/solutions[contains(@worksheet, 'solution')]]\"/>\n<xsl:variable name=\"reading-solution-main\"    select=\"$document-root//reading-questions//solution[ancestor::*/solutions[contains(@reading, 'solution')]]\"/>\n<xsl:variable name=\"project-solution-main\"    select=\"$document-root//*[&PROJECT-FILTER;]//solution[ancestor::*/solutions[contains(@project, 'solution')]]\"/>\n<!-- Solution, Back Matter -->\n<xsl:variable name=\"inline-solution-back\"     select=\"$document-root//exercise[&INLINE-EXERCISE-FILTER;]//solution[$document-root/backmatter/solutions[contains(@inline, 'solution')]]\"/>\n<xsl:variable name=\"divisional-solution-back\" select=\"$document-root//exercises//solution[$document-root/backmatter/solutions[contains(@divisional, 'solution')]]\"/>\n<xsl:variable name=\"worksheet-solution-back\"  select=\"$document-root//worksheet//exercise//solution[$document-root/backmatter/solutions[contains(@worksheet, 'solution')]]\"/>\n<xsl:variable name=\"reading-solution-back\"    select=\"$document-root//reading-questions//solution[$document-root/backmatter/solutions[contains(@reading, 'solution')]]\"/>\n<xsl:variable name=\"project-solution-back\"    select=\"$document-root//*[&PROJECT-FILTER;]//solution[$document-root/backmatter/solutions[contains(@project, 'solution')]]\"/>\n\n<!-- Combinations that are useful -->\n<!-- First: main matter placement vs. back matter placement -->\n<xsl:variable name=\"solutions-mainmatter\" select=\"\n$inline-hint-main    |$divisional-hint-main    |$worksheet-hint-main    |$reading-hint-main    |$project-hint-main|\n$inline-answer-main  |$divisional-answer-main  |$worksheet-answer-main  |$reading-answer-main  |$project-answer-main|\n$inline-solution-main|$divisional-solution-main|$worksheet-solution-main|$reading-solution-main|$project-solution-main\"/>\n<xsl:variable name=\"solutions-backmatter\" select=\"\n$inline-hint-back    |$divisional-hint-back    |$worksheet-hint-back    |$reading-hint-back    |$project-hint-back|\n$inline-answer-back  |$divisional-answer-back  |$worksheet-answer-back  |$reading-answer-back  |$project-answer-back|\n$inline-solution-back|$divisional-solution-back|$worksheet-solution-back|$reading-solution-back|$project-solution-back\"/>\n\n<!-- ################### -->\n<!-- Debugging Variables -->\n<!-- ################### -->\n\n<!-- Collect debugging and transition string parameters.   -->\n<!-- (1) Military style names: debug.*.*, finer purposes   -->\n<!-- (2) Minimal documentation here.                       -->\n<!-- (3) No error-checking, no deprecation plan            -->\n<!-- (4) Perhaps warnings on removal, migrate to Bad Bank  -->\n\n<!-- Look in \"publisher variables\" stylesheet for some -->\n<!-- (convenience) debugging switches that override    -->\n<!-- publisher/default settings                        -->\n\n<!-- Sometimes  xsltproc fails, and fails spectacularly,        -->\n<!-- setting this switch will dump lots of location info to the -->\n<!-- console, and perhaps will be helpful in locating a failure -->\n<!-- You might redirect stderror to a file with \"2> errors.txt\" -->\n<!-- appended to your command line                              -->\n<xsl:param name=\"debug\" select=\"'no'\" />\n<xsl:variable name=\"b-debug\" select=\"$debug = 'yes'\" />\n\n<xsl:param name=\"debug.datedfiles\" select=\"'yes'\" />\n<xsl:variable name=\"b-debug-datedfiles\" select=\"not($debug.datedfiles = 'no')\" />\n\n\n<!-- Single-use to display low-level info on whitespace manipulation -->\n<xsl:param name=\"ws.debug\" select=\"'no'\" />\n<xsl:variable name=\"wsdebug\" select=\"boolean($ws.debug = 'yes')\" />\n\n<!-- Colored boxes on panels -->\n<xsl:param name=\"sbs.debug\" select=\"'no'\" />\n<xsl:variable name=\"sbsdebug\" select=\"boolean($sbs.debug = 'yes')\" />\n\n<!-- very temporary, just for testing -->\n<xsl:param name=\"debug.exercises.forward\" select=\"''\"/>\n\n<!-- LaTeX display style in list items -->\n<xsl:param name=\"debug.displaystyle\" select=\"'yes'\"/>\n\n<!-- 2021-07-30: HTML only, experimental -->\n<!-- Switch to kill all knowls, intended to facilitate -->\n<!-- quick preview builds for use while authoring. -->\n<!-- Change to non-empty string to enable -->\n<xsl:param name=\"debug.skip-knowls\" select=\"''\"/>\n<xsl:variable name=\"b-skip-knowls\" select=\"not($debug.skip-knowls = '')\"/>\n\n<!-- MathJax SVG option (yes/no, could be generalized to -->\n<!-- specifying various options).  Totally unsupported.  -->\n<xsl:param name=\"debug.mathjax.svg\" select=\"''\"/>\n\n<!-- 2022-01-30: transition to React components, get ReactJS -->\n<!-- bundles, etc, locally or globally.  'yes' to activate.  -->\n<!-- Never use both, chaos might result, not error-checked   -->\n<xsl:param name=\"debug.react.local\" select=\"'no'\"/>\n<xsl:param name=\"debug.react.global\" select=\"'no'\"/>\n<!-- three derived internal variables, primarily use latter -->\n<xsl:variable name= \"b-debug-react-local\" select=\"not($debug.react.local = 'no')\"/>\n<xsl:variable name= \"b-debug-react-global\" select=\"not($debug.react.global = 'no')\"/>\n<xsl:variable name=\"b-debug-react\" select=\"$b-debug-react-local or $b-debug-react-global\"/>\n\n<!-- HTML only, a developer must elect to use this CSS file -->\n<xsl:param name=\"debug.developer.css\" select=\"'no'\"/>\n\n<!-- A permanent string parameter to control the creation of  -->\n<!-- \"View Source\" knowls, which is a developer task, not a   -->\n<!-- publisher task (though it could be?).  So permanent, but -->\n<!-- undocumented.                                            -->\n<xsl:param name=\"debug.html.annotate\" select=\"'no'\"/>\n<xsl:variable name=\"b-view-source\" select=\"$debug.html.annotate = 'yes'\"/>\n\n<!-- LaTeX only: verify PreTeXt-computed numbers match LaTeX counter numbers -->\n<xsl:param name=\"debug.numbering.check\" select=\"''\"/>\n<xsl:variable name=\"b-debug-numbering-check\" select=\"$debug.numbering.check = 'yes'\"/>\n\n<!-- Maybe not debugging, but transitional variables -->\n\n<!-- Prior to January 2017 we treated all whitespace as -->\n<!-- significant in mixed-content nodes.  With changes  -->\n<!-- in this policy we preserve the option to process   -->\n<!-- in this older style.  This could avoid frequent    -->\n<!-- applications of low-level text-processing routines -->\n<!-- and perhaps speed up processing.  Switch here      -->\n<!-- controls possible whitespace modes.                -->\n<xsl:param name=\"whitespace\" select=\"'flexible'\" />\n<xsl:variable name=\"whitespace-style\">\n    <xsl:choose>\n        <xsl:when test=\"$whitespace='strict' or $whitespace='flexible'\">\n            <xsl:value-of select=\"$whitespace\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message>\n                <xsl:text>PTX:FALLBACK: the whitespace parameter can be 'strict' or 'flexible', not '</xsl:text>\n                <xsl:value-of select=\"$whitespace\" />\n                <xsl:text>'.  Using the default ('flexible').</xsl:text>\n            </xsl:message>\n            <xsl:text>flexible</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- ############## -->\n<!-- Entry Template -->\n<!-- ############## -->\n\n<!-- We never process using just this file, and often want  -->\n<!-- to import it elsewhere for the utilities it contains.  -->\n<!-- So there is no entry template, nor should there be.    -->\n<!-- An importing file, designed for a specific conversion, -->\n<!-- can have an entry template and use the general         -->\n<!-- \"chunking\" templates defined below.                    -->\n\n\n<!-- ############################# -->\n<!-- Dimensions and Colors, Shared -->\n<!-- ############################# -->\n\n<!-- Distances and colors that should agree between the LaTeX   -->\n<!-- and XSL-FO conversions live here, defined once, so the     -->\n<!-- two stay consistent.  A distance is a bare number, and     -->\n<!-- each conversion attaches its own units; a color is a       -->\n<!-- six-hex-digit RRGGBB string, which each conversion         -->\n<!-- wraps in its own syntax.                                   -->\n\n<!-- An \"exercisegroup\" indents its exercises, to show the      -->\n<!-- scope of the group, by this fraction of the prevailing     -->\n<!-- text width.  The LaTeX conversion applies it through       -->\n<!-- \\ptxegindent (that many \\linewidth); the XSL-FO conversion    -->\n<!-- scales its text measure.                                   -->\n<xsl:variable name=\"exercisegroup-indentation\" select=\"0.05\"/>\n\n<!-- Each level of \"task\" nesting indents by this many \"em\"     -->\n<!-- of the body font.  (For comparison, the LaTeX task list    -->\n<!-- takes the \"enumerate\" default, roughly 2.5em.)             -->\n<xsl:variable name=\"task-indentation\" select=\"2\"/>\n\n<!-- A new paragraph is marked by indenting its first line by   -->\n<!-- this many \"em\", not by vertical space, the book-typography -->\n<!-- default (and what the LaTeX conversion does, through the   -->\n<!-- class \"\\parindent\"). The \"p\" template of the XSL-FO        -->\n<!-- conversion applies it, and makes Bringhurst's case for the -->\n<!-- indent and for which paragraphs take it.                   -->\n<xsl:variable name=\"paragraph-indentation\" select=\"1.5\"/>\n\n<!-- The background tint of a Sage cell's input box: a very     -->\n<!-- pale blue, a heavily lightened version of Sage's own.      -->\n<xsl:variable name=\"sage-input-background\" select=\"'F2F2FF'\"/>\n\n\n<!-- ###### -->\n<!-- Levels -->\n<!-- ###### -->\n\n<!-- Certain characteristics of the output can be configured    -->\n<!-- based on how deep they are in the hierachy of a structured -->\n<!-- document.  Authors specify these characteristics relative  -->\n<!-- to their own project, more specifically relative to the    -->\n<!-- logical top-level element, such as \"book\" or \"article\".    -->\n<!-- These are \"Level 0\". We normalize these numbers internally -->\n<!-- so that level 0 is the first possible division in any      -->\n<!-- document, which would be a \"part\"                          -->\n\n\n<!-- (Relative) Levels -->\n<!-- Input: an element that is a division of some kind -->\n<!-- Output: its relative level, eg \"book\" is 0        -->\n<!-- Front and back matter are faux divisions, so we   -->\n<!-- filter them out.                                  -->\n\n\n<!--\nSchematic of levels of divisions\n*  \"preface\" has 4 peers, eg, \"dedication\"\n*  \"appendix\" has two peers, \"index\" and \"colophon\"\n*  specialized divisions, e.g \"references\" can go numerous places\n\nArticle, \"section\" at level 1\n||         0            ||    1     ||     2      ||      3        ||\n||          frontmatter ||          ||            ||               ||\n|| article              || section  || subsection || subsubsection ||\n||          backmatter  || appendix || subsection || subsubsection ||\n\n\nBook (no parts), \"section\" at level 2\n||        0         ||    1     ||    2     ||     3      ||      4        ||\n||      frontmatter || preface  ||          ||            ||               ||\n|| book             || chapter  || section  || subsection || subsubsection ||\n||      backmatter  || appendix || section  || subsection || subsubsection ||\n\n\nBook (with parts), \"section\" at level 3\n||  0   ||     1       ||    2     ||    3     ||     4      ||      5        ||\n||      || frontmatter || preface  ||          ||            ||               ||\n|| book || part        || chapter  || section  || subsection || subsubsection ||\n||      || backmatter  || appendix || section  || subsection || subsubsection ||\n-->\n\n\n<!-- For any element, work up the tree to a structural -->\n<!-- node and then compute level as above              -->\n<!-- NB: to meld with previous would require a better     -->\n<!-- definition of structural, and care with introduction -->\n<xsl:template match=\"*\" mode=\"enclosing-level\">\n    <xsl:variable name=\"structural\">\n        <xsl:apply-templates select=\".\" mode=\"is-structural\" />\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$structural = 'true'\">\n            <xsl:apply-templates select=\".\" mode=\"level\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\"parent::*\" mode=\"enclosing-level\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n<!-- Relative level offset -->\n<!-- This is the adjustment to move a relative       -->\n<!-- level onto the absolute scale                   -->\n<!--     part: 0                                     -->\n<!--     chapter, appendix: 1                        -->\n<!--     section: 2                                  -->\n<!--     subsection: 3                               -->\n<!--     subsubsection: 4                            -->\n<!-- It can be defined as the value on this absolute -->\n<!-- scale that the $document-root (book, article,   -->\n<!-- memo, etc.) would have, depending on options    -->\n<!-- for structure beneath it.  So for all divisions -->\n<!--                                                 -->\n<!-- absolute-level = (relative-)level + root-level  -->\n<!--                                                 -->\n<!-- NB: 2017-09-05, three places, keep as variable  -->\n<xsl:variable name=\"root-level\">\n    <xsl:choose>\n        <xsl:when test=\"$version-root/book/part\">-1</xsl:when>\n        <xsl:when test=\"$version-root/book/chapter\">0</xsl:when>\n        <!-- An article is rooted just above sections, -->\n        <!-- on par with chapters of a book            -->\n        <xsl:when test=\"$version-root/article\">1</xsl:when>\n        <xsl:when test=\"$version-root/slideshow\">1</xsl:when>\n        <xsl:when test=\"$version-root/letter\">1</xsl:when>\n        <xsl:when test=\"$version-root/memo\">1</xsl:when>\n        <xsl:otherwise>\n            <xsl:message>PTX:BUG: Level offset undefined for this document type</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- Names for Levels -->\n<!-- Levels (ie depths in the tree) translate to PTX element -->\n<!-- names and LaTeX divisions, which are generally the same -->\n<!-- This is useful for \"new\" sections (eg exercises) when   -->\n<!-- used with standard LaTeX sectioning and numbering       -->\n\n<!-- Input:  a relative level, ie counted from document root -->\n<!-- Output:  the LaTeX name (or close), HTML element        -->\n<!-- NB:  this is a named template, independent of context   -->\n<!-- NB: (2019-05-09) This could go to the -latex conversion -->\n<xsl:template name=\"level-to-name\">\n    <xsl:param name=\"level\" />\n    <xsl:variable name=\"normalized-level\" select=\"$level + $root-level\" />\n    <xsl:choose>\n        <xsl:when test=\"$normalized-level=0\">part</xsl:when>\n        <xsl:when test=\"$normalized-level=1\">chapter</xsl:when>\n        <xsl:when test=\"$normalized-level=2\">section</xsl:when>\n        <xsl:when test=\"$normalized-level=3\">subsection</xsl:when>\n        <xsl:when test=\"$normalized-level=4\">subsubsection</xsl:when>\n        <xsl:otherwise>\n            <xsl:message>PTX:BUG:   Level computation is out-of-bounds (input as <xsl:value-of select=\"$level\" />, normalized to <xsl:value-of select=\"$normalized-level\" />)</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- LaTex Native Levels -->\n<!-- LaTeX has its own internal absolute numbering scheme, -->\n<!-- where sections are always level 1, while PTX uses     -->\n<!-- level 2. So while a LaTeX-specific computation, we do -->\n<!-- the translation here, so as to isolate the use of the -->\n<!-- root-level variable in this -common file.             -->\n<xsl:template name=\"level-to-latex-level\">\n    <xsl:param name=\"level\" />\n    <xsl:value-of select=\"$level + $root-level -1\" />\n</xsl:template>\n\n<!-- Division element to its sectioning level name (part, chapter,   -->\n<!-- section, subsection, subsubsection, or \"paragraph\" for a deeply -->\n<!-- nested specialized division).  Structural divisions map by name; -->\n<!-- a specialized division (exercises, references, ...) maps by the  -->\n<!-- level of its parent, the same mapping the LaTeX sectioning uses. -->\n<xsl:template match=\"part|chapter|section|subsection|subsubsection\" mode=\"division-name\">\n    <xsl:value-of select=\"local-name(.)\"/>\n</xsl:template>\n\n<!-- Front matter divisions are only in book, and always at chapter level -->\n<xsl:template match=\"acknowledgement|foreword|preface\" mode=\"division-name\">\n    <xsl:text>chapter</xsl:text>\n</xsl:template>\n\n<!-- Some divisions can appear at multiple levels (eg, exercises) -->\n<!-- Divisions in the back matter vary between books and articles -->\n<!--     Book:    children of backmatter -> chapter               -->\n<!--     Article: children of backmatter -> section               -->\n<xsl:template match=\"exercises|solutions|worksheet|handout|reading-questions|references|glossary|appendix|index\" mode=\"division-name\">\n    <xsl:choose>\n        <xsl:when test=\"parent::article\">\n            <xsl:text>section</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"parent::chapter\">\n            <xsl:text>section</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"parent::section\">\n            <xsl:text>subsection</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"parent::subsection\">\n            <xsl:text>subsubsection</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"parent::subsubsection\">\n            <xsl:text>paragraph</xsl:text>\n        </xsl:when>\n        <!-- children of backmatter (appendix, solutions, reference, index) -->\n        <!-- in book/article are at chapter/section level                   -->\n        <xsl:when test=\"parent::backmatter\">\n            <xsl:choose>\n                <xsl:when test=\"ancestor::book\">\n                    <xsl:text>chapter</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"ancestor::article\">\n                    <xsl:text>section</xsl:text>\n                </xsl:when>\n            </xsl:choose>\n        </xsl:when>\n        <!-- appendix in book/article is at chapter/section level -->\n        <!-- so descendants (exercises, solutions) down one level -->\n        <xsl:when test=\"parent::appendix\">\n            <xsl:choose>\n                <xsl:when test=\"ancestor::book\">\n                    <xsl:text>section</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"ancestor::article\">\n                    <xsl:text>subsection</xsl:text>\n                </xsl:when>\n            </xsl:choose>\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"division-name\">\n    <xsl:message>PTX:BUG: Asking for the name of an element (<xsl:value-of select=\"local-name(.)\" />) that is not a division</xsl:message>\n</xsl:template>\n\n<!-- ########### -->\n<!-- Mathematics -->\n<!-- ########### -->\n\n<!-- Mathematics authored in LaTeX syntax should be       -->\n<!-- independent of output format.  Despite MathJax's     -->\n<!-- broad array of capabilities, there are still some    -->\n<!-- differences which we need to accomodate via abstract -->\n<!-- templates.  Those abstractions are documented here   -->\n<!-- and also where implemented.  Elsewhere are low-level -->\n<!-- manipulations of whitespace in processed versions    -->\n<!-- of LaTeX output                                      -->\n\n\n<!-- Inline Mathematics (\"m\") -->\n<!--                                                     -->\n<!-- This is fairly simple.  Differences are             -->\n<!--   (1) Some conversions require different delimiters -->\n<!--   (2) We adjust punctuation for HTML, but not Latex -->\n<!--                                                     -->\n<!-- Abstract Templates                                  -->\n<!--                                                     -->\n<!-- (1) named \"inline-math-wrapper\"                     -->\n<!--       Provides the delimiters for inline math       -->\n<!--       Stub warnings follow below                    -->\n<!-- (2) get-clause-punctuation                          -->\n<!--       Look at next node, and if a text node,        -->\n<!--       then look for leading punctuation, and        -->\n<!--       bring into math with \\text() wrapper          -->\n<!--       when  $math.punctuation.include  indicates    -->\n\n<!-- $debug.displaystyle defaults to yes for testing -->\n\n<!-- Warn about bare special characters inside \\text{} in math.      -->\n<!-- The textmacros extension treats # % &amp; as special, so they   -->\n<!-- must be escaped as \\# \\% \\&amp; to produce literal glyphs.      -->\n<!-- We walk through each \\text{...} segment via recursion and check -->\n<!-- the content up to the next } for bare special characters.       -->\n<!-- Imperfect with nested braces, but catches common cases.         -->\n<xsl:template name=\"warn-text-special-characters\">\n    <xsl:variable name=\"math-text\" select=\"string(.)\"/>\n    <xsl:if test=\"contains($math-text, '\\text{')\">\n        <xsl:call-template name=\"check-text-segments\">\n            <xsl:with-param name=\"remaining\" select=\"$math-text\"/>\n        </xsl:call-template>\n    </xsl:if>\n</xsl:template>\n\n<!-- Recursive walk through \\text{...} segments of a LaTeX string -->\n<xsl:template name=\"check-text-segments\">\n    <xsl:param name=\"remaining\"/>\n    <xsl:if test=\"contains($remaining, '\\text{')\">\n        <!-- content after \\text{ up to next } -->\n        <xsl:variable name=\"after-text\" select=\"substring-after($remaining, '\\text{')\"/>\n        <xsl:variable name=\"inside\" select=\"substring-before($after-text, '}')\"/>\n        <!-- check for bare # (present but \\# is not) -->\n        <xsl:if test=\"contains($inside, '#') and not(contains($inside, '\\#'))\">\n            <xsl:message>\n                <xsl:text>PTX:ERROR:     a bare \"#\" inside \\text{} in math must be escaped as \"\\#\"</xsl:text>\n                <xsl:text>&#xa;</xsl:text>\n                <xsl:text>               </xsl:text>\n                <xsl:apply-templates select=\".\" mode=\"location-report\"/>\n            </xsl:message>\n        </xsl:if>\n        <!-- check for bare % -->\n        <xsl:if test=\"contains($inside, '%') and not(contains($inside, '\\%'))\">\n            <xsl:message>\n                <xsl:text>PTX:ERROR:     a bare \"%\" inside \\text{} in math must be escaped as \"\\%\"</xsl:text>\n                <xsl:text>&#xa;</xsl:text>\n                <xsl:text>               </xsl:text>\n                <xsl:apply-templates select=\".\" mode=\"location-report\"/>\n            </xsl:message>\n        </xsl:if>\n        <!-- check for bare & -->\n        <xsl:if test=\"contains($inside, '&amp;') and not(contains($inside, '\\&amp;'))\">\n            <xsl:message>\n                <xsl:text>PTX:ERROR:     a bare \"&amp;\" inside \\text{} in math must be escaped as \"\\&amp;\"</xsl:text>\n                <xsl:text>&#xa;</xsl:text>\n                <xsl:text>               </xsl:text>\n                <xsl:apply-templates select=\".\" mode=\"location-report\"/>\n            </xsl:message>\n        </xsl:if>\n        <!-- recurse on remainder after this \\text{...} -->\n        <xsl:call-template name=\"check-text-segments\">\n            <xsl:with-param name=\"remaining\" select=\"$after-text\"/>\n        </xsl:call-template>\n    </xsl:if>\n</xsl:template>\n\n<xsl:template match=\"m\">\n    <xsl:call-template name=\"warn-text-special-characters\"/>\n    <!-- wrap in math delimiters -->\n    <xsl:call-template name=\"inline-math-wrapper\">\n        <xsl:with-param name=\"math\">\n            <!-- Build a textual version of the latex,  -->\n            <!-- applying the rare templates allowed,   -->\n            <!-- save for minor manipulation later.     -->\n            <!-- Note: generic text() template here in  -->\n            <!-- -common should always pass through the -->\n            <!-- text nodes within \"m\" with no changes  -->\n            <xsl:variable name=\"raw-latex\">\n                <xsl:choose>\n                    <xsl:when test=\"ancestor::static/parent::webwork-reps\">\n                        <xsl:apply-templates select=\"text()|var\" />\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:apply-templates select=\"text()|eval|fillin\" />\n                    </xsl:otherwise>\n                </xsl:choose>\n                <!-- look ahead to absorb immediate clause-ending punctuation   -->\n                <!-- this is useful for HTML/MathJax to prevent bad line breaks -->\n                <!-- The template here in -common is generally useful, but      -->\n                <!-- for LaTeX we override to be a no-op, since not necessary   -->\n                <xsl:apply-templates select=\".\" mode=\"get-clause-punctuation\" />\n            </xsl:variable>\n            <!-- Prefix will normally be empty and have no effect.  We also have  -->\n            <!-- an undocumented switch to totally kill the possibility entirely. -->\n            <!-- This was added to support testing of braille output.             -->\n            <xsl:if test=\"not($debug.displaystyle = 'no')\">\n                <xsl:apply-templates select=\".\"  mode=\"display-style-prefix\"/>\n            </xsl:if>\n            <!-- we clean whitespace that is irrelevant to LaTeX so that we -->\n            <!--   (1) avoid LaTeX compilation errors                       -->\n            <!--   (2) avoid spurious blank lines leading to new paragraphs -->\n            <!--   (3) provide human-readable source of high quality        -->\n            <!-- sanitize-latex template does not provide a final newline   -->\n            <!-- and we do not add one here either, since it is inline math -->\n            <!-- MathJax is more tolerant, but readability is still useful  -->\n            <xsl:call-template name=\"sanitize-latex\">\n                <xsl:with-param name=\"text\" select=\"$raw-latex\" />\n            </xsl:call-template>\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- This template needs an override in each output mode. -->\n<xsl:template name=\"inline-math-wrapper\">\n    <xsl:param name=\"math\"/>\n    <xsl:message>PTX:BUG:   the \"wrapper\" modal template for inline math needs an implementation in the current conversion</xsl:message>\n    <xsl:text>[[[</xsl:text>\n    <xsl:value-of select=\"$math\"/>\n    <xsl:text>]]]</xsl:text>\n</xsl:template>\n\n\n<!-- Display Style LaTeX markup for inline math -->\n<!--                                                     -->\n<!-- If the current context \"m\" is a child of an \"li\",   -->\n<!-- perhaps with an intervening \"p\", then we            -->\n<!-- contemplate injecting a \\displaystyle, if *the \"m\"  -->\n<!-- is the only content of the \"li\"*.-->\n<xsl:template match=\"m\" mode=\"display-style-prefix\">\n    <!-- We first obtain a parent \"li\" (or come away    -->\n    <!-- empty-handed). Booleans help readability later -->\n    <xsl:variable name=\"parent-li\" select=\"boolean(parent::li)\"/>\n    <xsl:variable name=\"grandparent-li\" select=\"boolean(parent::p/parent::li)\"/>\n    <xsl:variable name=\"the-list-item\" select=\"parent::li|parent::p/parent::li\"/>\n    <!-- If we have inline math inside a list item then we   -->\n    <!-- can collect all of non-whitespace text() nodes.     -->\n    <!-- We are only interested in the case of a single \"p\". -->\n    <xsl:variable name=\"actual-text\">\n        <xsl:if test=\"$the-list-item\">\n            <xsl:choose>\n                <xsl:when test=\"$parent-li\">\n                    <xsl:for-each select=\"$the-list-item/text()\">\n                        <xsl:value-of select=\"normalize-space(.)\"/>\n                    </xsl:for-each>\n                </xsl:when>\n                <xsl:when test=\"$grandparent-li\">\n                    <xsl:for-each select=\"$the-list-item/p[1]/text()\">\n                        <xsl:value-of select=\"normalize-space(.)\"/>\n                    </xsl:for-each>\n                </xsl:when>\n            </xsl:choose>\n        </xsl:if>\n    </xsl:variable>\n    <!-- Potential prefix with \\displaystyle                        -->\n    <!--                                                            -->\n    <!-- (1) If there is not a list item, the next two tests fail.  -->\n    <!-- (2) If there is any significant text() the tests will fail.-->\n    <!-- (3) If there is a parent li, or li/p, the tests will fail  -->\n    <!--     if there are more than two \"p\" or if the content       -->\n    <!--     contains other markup (elements) other elements        -->\n    <!--     besides just the lone \"m\".                             -->\n    <!--                                                            -->\n    <!-- So we improve the appearance of a lone \"m\" inside an \"li\". -->\n    <!-- Authors who do not like this can add innocuous content.    -->\n    <!--  -->\n    <!-- The two \"when\" are disjoint and both may be false.  They   -->\n    <!-- produce the same result.  This is meant to be more         -->\n    <!-- readable than a big \"or\".  Note: this could be wrapped in  -->\n    <!-- a big \"if\" based on the common $actual-text.               -->\n    <!-- The result of this template is \"\\displaystyle \" or \"\"      -->\n    <xsl:choose>\n        <xsl:when test=\"$parent-li and ($actual-text = '') and (count($the-list-item/*) = 1)\">\n            <xsl:text>\\displaystyle </xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$grandparent-li and ($actual-text = '') and (count($the-list-item/p) = 1) and (count($the-list-item/p[1]/*) = 1)\">\n            <xsl:text>\\displaystyle </xsl:text>\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- Displayed Multi-Line Math (\"md\", with \"mrow\" children)         -->\n<!-- \"md\" is a container for  \"mrow\" and intermediate \"intertext\".  -->\n<!-- Note that the pre-processor guarantees that every \"md\"         -->\n<!-- is structured with \"mrow\" and optionally \"intertext\".          -->\n<!--                                                                -->\n<!-- Abstract Templates                                             -->\n<!--                                                                -->\n<!-- (1) display-math-visual-blank-line, a named template           -->\n<!--       Just a line in source to help visually (% for LaTeX)     -->\n<!--                                                                -->\n<!-- (2) display-math-wrapper                                       -->\n<!--       An enclosing environment for any displayed mathematics   -->\n<!--       Necessary for HTML, no-op for LaTeX                      -->\n\n<!-- Default implementationis a no-op, can be overidden -->\n<xsl:template name=\"display-math-visual-blank-line\"/>\n\n<!-- All displayed mathematics gets wrapped by  -->\n<!-- an abstract template, a necessity for HTML -->\n<!-- output.  By default, just a copy machine.  -->\n<xsl:template match=\"md[mrow]\" mode=\"display-math-wrapper\">\n    <xsl:param name=\"content\" />\n    <xsl:value-of select=\"$content\" />\n</xsl:template>\n\n<!-- The HTML conversion accomodates duplicated content (i.e. knowls) -->\n<!-- with an elaborate scheme.  The mode=\"body\" template is central,  -->\n<!-- so we run with that here.                                        -->\n<xsl:template match=\"md[mrow]\" mode=\"body\">\n    <!-- block-type parameter is ignored, since the          -->\n    <!-- representation never varies, no heading, no wrapper -->\n    <xsl:param name=\"block-type\" />\n    <!-- If original content, or a duplication -->\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <!-- If the only content of a knowl then we do not -->\n    <!-- include adjacent (trailing) punctuation,      -->\n    <!-- since it is meaningless                       -->\n    <xsl:param name=\"b-top-level\" select=\"false()\" />\n    <!-- Optionally, the \\begin{} (the \"open\") or the \\end{}  -->\n    <!-- (the \"close\") can be suppressed.  This only happens  -->\n    <!-- when making LaTeX output, and only when un-exploding -->\n    <!-- an \"md\" that has \"intertext\" in it.  So the default  -->\n    <!-- values are true, and most conversions can safely     -->\n    <!-- ignore the use of these parameters.                  -->\n    <xsl:param name=\"b-needs-open\"  select=\"true()\"/>\n    <xsl:param name=\"b-needs-close\" select=\"true()\"/>\n    <!-- When applied by the LaTeX conversion to \"put back    -->\n    <!-- together\" an exploded \"md\" with \"intertext\", we need -->\n    <!-- to know if tags are necessary.                       -->\n    <xsl:param name=\"b-latex-intertext-needs-tags\" select=\"false()\"/>\n\n    <!-- Look across all mrow for the necessity of tags. We do not  -->\n    <!-- flag local tags as being numbered, but this affects        -->\n    <!-- LaTeX environment construction, so we need to consider it. -->\n    <!-- This just allows for slightly nicer human-readable source. -->\n    <xsl:variable name=\"b-needs-tags\" select=\"mrow[@pi:numbered = 'yes' or @tag] or $b-latex-intertext-needs-tags\" />\n    <xsl:variable name=\"complete-latex\">\n        <xsl:if test=\"$b-needs-open\">\n            <!-- we provide a newline for visual appeal -->\n            <xsl:call-template name=\"display-math-visual-blank-line\" />\n            <xsl:text>\\begin{</xsl:text>\n            <xsl:apply-templates select=\".\" mode=\"displaymath-alignment\">\n                <xsl:with-param name=\"b-needs-tags\" select=\"$b-needs-tags\" />\n            </xsl:apply-templates>\n            <xsl:text>}</xsl:text>\n            <xsl:apply-templates select=\".\" mode=\"alignat-columns\" />\n            <!-- leading whitespace not present, or stripped -->\n            <xsl:text>&#xa;</xsl:text>\n        </xsl:if>\n        <xsl:apply-templates select=\"mrow|intertext\">\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n            <xsl:with-param name=\"b-top-level\" select=\"$b-top-level\" />\n            <xsl:with-param name=\"b-needs-tags\" select=\"$b-needs-tags\" />\n        </xsl:apply-templates>\n        <!-- each mrow provides a newline, so unlike  -->\n        <!-- above, we do not need to add one here    -->\n        <xsl:if test=\"$b-needs-close\">\n            <xsl:text>\\end{</xsl:text>\n            <xsl:apply-templates select=\".\" mode=\"displaymath-alignment\">\n                <xsl:with-param name=\"b-needs-tags\" select=\"$b-needs-tags\" />\n            </xsl:apply-templates>\n            <xsl:text>}</xsl:text>\n            <!-- We must return to a paragraph, so                     -->\n            <!-- we can add an unprotected newline                     -->\n            <!-- Note: clause-ending punctuation has been absorbed,    -->\n            <!-- so is not left orphaned at the start of the next line -->\n            <xsl:text>&#xa;</xsl:text>\n        </xsl:if>\n    </xsl:variable>\n    <xsl:apply-templates select=\".\" mode=\"display-math-wrapper\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n        <xsl:with-param name=\"content\" select=\"$complete-latex\" />\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Rows of Displayed Multi-Line Math (\"mrow\") -->\n<!-- Each mrow finishes with a newline, for visual output      -->\n<!-- We perform LaTeX sanitization on each \"mrow\" here;        -->\n<!--                                                           -->\n<!-- Abstract Templates                                        -->\n<!--                                                           -->\n<!-- (1) display-page-break                                    -->\n<!--       LaTeX scheme, no-op here as base                    -->\n<!-- (2) tag                                                   -->\n<!--       on *rows* of multiline                              -->\n\n<!-- Default implementations of specialized templates -->\n<xsl:template match=\"mrow\" mode=\"display-page-break\"/>\n\n<xsl:template match=\"mrow\" mode=\"tag\">\n     <xsl:message>PTX:BUG:   the modal \"tag\" template needs an implementation for \"mrow\" in the current conversion</xsl:message>\n</xsl:template>\n\n<xsl:template match=\"mrow\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"b-top-level\" select=\"false()\" />\n    <xsl:param name=\"b-needs-tags\" />\n    <xsl:call-template name=\"warn-text-special-characters\"/>\n    <!-- Build a textual version of the latex,       -->\n    <!-- applying the rare templates allowed,        -->\n    <!-- save for minor manipulation later.          -->\n    <!-- Note: generic text() template here in       -->\n    <!-- -common should always pass through the text -->\n    <!-- nodes within \"mrow\" with no changes         -->\n    <xsl:variable name=\"raw-latex\">\n        <xsl:choose>\n            <xsl:when test=\"ancestor::webwork\">\n                <xsl:apply-templates select=\"text()|xref|var\" />\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:apply-templates select=\"text()|xref|eval|fillin\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- pull left for visual fidelity -->\n    <xsl:variable name=\"sanitized-latex\">\n        <xsl:call-template name=\"sanitize-latex\">\n            <xsl:with-param name=\"text\" select=\"$raw-latex\" />\n        </xsl:call-template>\n    </xsl:variable>\n    <!-- maybe there is clause-ending punctuation, and maybe we want it -->\n    <xsl:variable name=\"potential-punctuation\">\n        <xsl:if test=\"not(following-sibling::*[self::mrow or self::intertext])\">\n            <!-- look ahead to absorb immediate clause-ending punctuation         -->\n            <!-- for original versions, and as a child of a duplicated element    -->\n            <!-- but not in a duplicate that is entirely the display math         -->\n            <!-- pass the context as enclosing environment (parent::*, md or mdn) -->\n            <xsl:if test=\"$b-original or not($b-top-level)\">\n                <xsl:apply-templates select=\"parent::*\" mode=\"get-clause-punctuation\" />\n            </xsl:if>\n        </xsl:if>\n    </xsl:variable>\n    <!-- Identify if the sanitized LaTeX finishes a \"cases\" environment -->\n    <xsl:variable name=\"b-ends-with-cases\"\n                  select=\"substring($sanitized-latex, string-length($sanitized-latex) - 10) = '\\end{cases}'\"/>\n    <!-- output the latex and the punctuation -->\n    <xsl:choose>\n        <!-- effectively slide the punctuation inside the \"cases\" environment -->\n        <!-- NB: condition on non-empty punctuation could be dropped and the  -->\n        <!-- rearrangement would effective be idential to the \"otherwise\"     -->\n        <!-- clause, but it is clearer to include the condition and do the    -->\n        <!-- \"otherwise\" more of the time.                                    -->\n        <xsl:when test=\"not($potential-punctuation = '') and $b-ends-with-cases\">\n            <xsl:value-of select=\"substring($sanitized-latex, 1, string-length($sanitized-latex) - 11)\"/>\n            <xsl:value-of select=\"$potential-punctuation\"/>\n            <xsl:text>\\end{cases}</xsl:text>\n        </xsl:when>\n        <!-- The usual case, where punctuation has been stripped elsewhere -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$sanitized-latex\"/>\n            <xsl:value-of select=\"$potential-punctuation\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n    <!-- If we build a pure no-tag environment, then we add nothing      -->\n    <!-- Otherwise, we are in a non-starred environment and get a number -->\n    <!-- unless we \"\\notag\" it, which is the better choice under AMSmath -->\n    <!-- The modal \"tag\" template is more complicated than just forming  -->\n    <!-- a tag, it is everything associated with an equation, like a     -->\n    <!-- \\label{} for LaTeX, and also for HTML/MathJax.  It does depend  -->\n    <!-- on if the display is the original version or not                -->\n    <!-- http://tex.stackexchange.com/questions/48965                    -->\n    <!-- The @tag attribute trumps almost everything                     -->\n    <xsl:choose>\n        <xsl:when test=\"not($b-needs-tags)\" />\n        <!-- \"local\" tag is not numbered, but needs treatment -->\n        <xsl:when test=\"(@pi:numbered = 'yes') or @tag\">\n            <xsl:apply-templates select=\".\" mode=\"tag\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>\\notag</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n    <!-- we have a discretionary page break scheme for LaTeX -->\n    <xsl:if test=\"following-sibling::mrow\">\n       <xsl:text>\\\\</xsl:text>\n       <xsl:apply-templates select=\".\" mode=\"display-page-break\" />\n    </xsl:if>\n    <xsl:text>&#xa;</xsl:text>\n</xsl:template>\n\n<!-- We convert a token into the LaTeX for a symbol     -->\n<!-- for use as a local tag. Since we need this to work -->\n<!-- in MathJax, we need symbols that are available in  -->\n<!-- its limited set of supported commands.  Generally, -->\n<!-- AMSMath symbols are the best description.  See     -->\n<!-- http://docs.mathjax.org/en/latest/tex.html         -->\n<!--     #supported-latex-commands                      -->\n<!-- Note: \\tag{} expects text mode                     -->\n<!-- More? \\checkmark, \\bullet?                         -->\n<!-- TODO: if some text symbols are used, perhaps from  -->\n<!-- the textcomp package, then math delimiters will    -->\n<!-- move down into the \"when\" parts of the \"choose\"    -->\n<xsl:template match=\"@tag\" mode=\"tag-symbol\">\n    <xsl:choose>\n        <!-- Stars -->\n        <xsl:when test=\". = 'star'\">\n            <xsl:call-template name=\"tag-star\"/>\n        </xsl:when>\n        <xsl:when test=\". = 'dstar'\">\n            <xsl:call-template name=\"tag-star\"/>\n            <xsl:call-template name=\"tag-star\"/>\n        </xsl:when>\n        <xsl:when test=\". = 'tstar'\">\n            <xsl:call-template name=\"tag-star\"/>\n            <xsl:call-template name=\"tag-star\"/>\n            <xsl:call-template name=\"tag-star\"/>\n        </xsl:when>\n        <!-- Dagger -->\n        <xsl:when test=\". = 'dagger'\">\n            <xsl:call-template name=\"tag-dagger\"/>\n        </xsl:when>\n        <xsl:when test=\". = 'ddagger'\">\n            <xsl:call-template name=\"tag-dagger\"/>\n            <xsl:call-template name=\"tag-dagger\"/>\n        </xsl:when>\n        <xsl:when test=\". = 'tdagger'\">\n            <xsl:call-template name=\"tag-dagger\"/>\n            <xsl:call-template name=\"tag-dagger\"/>\n            <xsl:call-template name=\"tag-dagger\"/>\n        </xsl:when>\n        <!-- Double Dagger -->\n        <xsl:when test=\". = 'daggerdbl'\">\n            <xsl:call-template name=\"tag-daggerdbl\"/>\n        </xsl:when>\n        <xsl:when test=\". = 'ddaggerdbl'\">\n            <xsl:call-template name=\"tag-daggerdbl\"/>\n            <xsl:call-template name=\"tag-daggerdbl\"/>\n        </xsl:when>\n        <xsl:when test=\". = 'tdaggerdbl'\">\n            <xsl:call-template name=\"tag-daggerdbl\"/>\n            <xsl:call-template name=\"tag-daggerdbl\"/>\n            <xsl:call-template name=\"tag-daggerdbl\"/>\n        </xsl:when>\n        <!-- Hash -->\n        <xsl:when test=\". = 'hash'\">\n            <xsl:call-template name=\"tag-hash\"/>\n        </xsl:when>\n        <xsl:when test=\". = 'dhash'\">\n            <xsl:call-template name=\"tag-hash\"/>\n            <xsl:call-template name=\"tag-hash\"/>\n        </xsl:when>\n        <xsl:when test=\". = 'thash'\">\n            <xsl:call-template name=\"tag-hash\"/>\n            <xsl:call-template name=\"tag-hash\"/>\n            <xsl:call-template name=\"tag-hash\"/>\n        </xsl:when>\n        <!-- Maltese -->\n        <xsl:when test=\". = 'maltese'\">\n            <xsl:call-template name=\"tag-maltese\"/>\n        </xsl:when>\n        <xsl:when test=\". = 'dmaltese'\">\n            <xsl:call-template name=\"tag-maltese\"/>\n            <xsl:call-template name=\"tag-maltese\"/>\n        </xsl:when>\n        <xsl:when test=\". = 'tmaltese'\">\n            <xsl:call-template name=\"tag-maltese\"/>\n            <xsl:call-template name=\"tag-maltese\"/>\n            <xsl:call-template name=\"tag-maltese\"/>\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n<!-- ####################### -->\n<!-- Display Math Alignments -->\n<!-- ####################### -->\n\n<!-- We sniff around for ampersands, to decide between \"align\"    -->\n<!-- and \"gather\", plus an asterisk for the no-tag version        -->\n<!-- AMSMath has no easy way to make a one-off number within      -->\n<!-- the *-form, so we lean toward always using the un-starred    -->\n<!-- versions, except when we flag tags as needed inside an \"md\"  -->\n<!-- Template is applied twice (begin/end) and its use ensures    -->\n<!-- consistency.                                                 -->\n<xsl:template match=\"md[mrow]\" mode=\"displaymath-alignment\">\n    <xsl:param name=\"b-needs-tags\" select=\"true()\" />\n    <xsl:choose>\n        <!-- Honor the @alignment override.  The schema restricts the   -->\n        <!-- value to one of these three.  The trailing \"@alignment\"    -->\n        <!-- catch-all is reached only by schema-bypassed input; it     -->\n        <!-- emits a literal token so LaTeX (or MathJax) errors out on  -->\n        <!-- an unknown environment rather than silently falling        -->\n        <!-- through to the ampersand-sniff branch.                     -->\n        <xsl:when test=\"@alignment='gather'\">\n            <xsl:text>gather</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"@alignment='alignat'\">\n            <xsl:text>alignat</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"@alignment='align'\">\n            <xsl:text>align</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"@alignment\">\n            <xsl:text>bad-alignment-choice</xsl:text>\n        </xsl:when>\n        <!-- perhaps authored as obviously one-line (no alignment) -->\n        <!-- and manipulated into an  md/@mrow  form               -->\n        <xsl:when test=\"@pi:authored-one-line\">\n            <xsl:text>equation</xsl:text>\n        </xsl:when>\n        <!-- sniff for alignment specifications    -->\n        <!-- this can be easily fooled, eg matrices-->\n        <xsl:when test=\"contains(., '&amp;') or contains(., '\\amp')\">\n            <xsl:text>align</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>gather</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n    <!-- if absolutely no numbers and no local tags,   -->\n    <!-- we'll economize in favor of human-readability -->\n    <xsl:if test=\"not($b-needs-tags)\">\n        <xsl:text>*</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<!-- With alignment=\"alignat\" we need the number of columns     -->\n<!-- as an argument, complete with the LaTeX group (braces)     -->\n<!-- Mostly we call this regularly, and it usually does nothing -->\n<xsl:template match=\"md[mrow]\" mode=\"alignat-columns\" />\n\n<xsl:template match=\"md[mrow and (@alignment='alignat')]\" mode=\"alignat-columns\">\n    <xsl:variable name=\"number-equation-columns\">\n        <xsl:choose>\n            <!-- override first -->\n            <xsl:when test=\"@alignat-columns\">\n                <!-- MathJax chokes on spaces here -->\n                <xsl:value-of select=\"normalize-space(@alignat-columns)\" />\n            </xsl:when>\n            <!-- count ampersands, compute columns -->\n            <xsl:otherwise>\n                <xsl:variable name=\"number-ampersands\">\n                    <xsl:apply-templates select=\"mrow[1]\" mode=\"max-ampersands\" />\n                </xsl:variable>\n                <!-- amps + 1, divide by 2, round up; 0.5 becomes 0.25, round behaves -->\n                <xsl:value-of select=\"round(($number-ampersands + 1.5) div 2)\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:text>{</xsl:text>\n    <xsl:value-of select=\"$number-equation-columns\" />\n    <xsl:text>}</xsl:text>\n</xsl:template>\n\n<!-- count ampersands in a string              -->\n<!-- both as LaTeX macro and as bare character -->\n<xsl:template name=\"count-ampersands\">\n    <xsl:param name=\"text\" />\n    <xsl:variable name=\"amp-char\">\n        <xsl:call-template name=\"count-substring\">\n            <xsl:with-param name=\"text\" select=\"$text\" />\n            <xsl:with-param name=\"word\" select=\"'&amp;'\" />\n        </xsl:call-template>\n    </xsl:variable>\n    <xsl:variable name=\"amp-macro\">\n        <xsl:call-template name=\"count-substring\">\n            <xsl:with-param name=\"text\" select=\"$text\" />\n            <xsl:with-param name=\"word\" select=\"'\\amp'\" />\n        </xsl:call-template>\n    </xsl:variable>\n    <xsl:value-of select=\"$amp-char + $amp-macro\" />\n</xsl:template>\n\n<!-- Recurse through \"mrow\"s of a presumed \"md\"   -->\n<!-- counting ampersands and tracking the maximum -->\n<xsl:template match=\"mrow\" mode=\"max-ampersands\">\n    <xsl:param name=\"max\" select=\"0\"/>\n    <!-- build string/text content -->\n    <xsl:variable name=\"row-content\">\n        <xsl:for-each select=\"text()\">\n            <xsl:value-of select=\".\" />\n        </xsl:for-each>\n    </xsl:variable>\n    <!-- count row's ampersands -->\n    <xsl:variable name=\"ampersands\">\n        <xsl:call-template name=\"count-ampersands\">\n            <xsl:with-param name=\"text\" select=\"$row-content\" />\n        </xsl:call-template>\n    </xsl:variable>\n    <!-- recalculate maximum -->\n    <xsl:variable name=\"new-max\">\n        <xsl:choose>\n            <xsl:when test=\"$ampersands > $max\">\n                <xsl:value-of select=\"$ampersands\" />\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$max\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- recurse or report -->\n    <xsl:variable name=\"following-mrows\" select=\"following-sibling::mrow\" />\n    <xsl:choose>\n        <xsl:when test=\"$following-mrows\">\n            <xsl:apply-templates select=\"$following-mrows[1]\" mode=\"max-ampersands\">\n                <xsl:with-param name=\"max\" select=\"$new-max\" />\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"$new-max\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- ######### -->\n<!-- Intertext -->\n<!-- ######### -->\n\n<!-- Unless overridden somehow, an internal \"pi:intertext\" element -->\n<!-- (coming from the \"intertext-exploder\" mode in -assembly) just -->\n<!-- needs a full-on \"xsl:apply-templates\"                         -->\n<xsl:template match=\"pi:intertext\">\n    <xsl:apply-templates/>\n</xsl:template>\n\n<!-- #################### -->\n<!-- LaTeX Image Preamble -->\n<!-- #################### -->\n\n<!-- A docinfo may have latex-image-preamble without a  -->\n<!-- @syntax. There should only be one, but schema does -->\n<!-- not enforce that. It is stored here as a variable  -->\n<!-- (possibly empty) to facilitate having other        -->\n<!-- latex-image-preamble that do have special @syntax. -->\n<xsl:variable name=\"latex-image-preamble\">\n    <xsl:choose>\n        <xsl:when test=\"$docinfo/latex-image-preamble[not(@syntax)]\">\n            <xsl:call-template name=\"sanitize-text\">\n                <xsl:with-param name=\"text\" select=\"$docinfo/latex-image-preamble[not(@syntax)][1]\" />\n            </xsl:call-template>\n        </xsl:when>\n        <xsl:otherwise/>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- ############## -->\n<!-- LaTeX Preamble -->\n<!-- ############## -->\n\n<!-- We pick up user-supplied macros, and         -->\n<!-- add three of our own that are useful         -->\n<!-- for avoiding conflicts with XML reserved     -->\n<!-- characters.  Even though MathJax defines     -->\n<!-- \\lt  and  \\gt  we go ahead and do it         -->\n<!-- anyway for completeness.  We add these       -->\n<!-- last with a \\newcommand to minimize the      -->\n<!-- possibility author defines them earlier      -->\n<!-- This should be the primary and only          -->\n<!-- interface to the macros list, though         -->\n<!-- it might need some extra                     -->\n<!-- conversion-specific wrapping in use          -->\n<!-- and it may be necessary/desirable to replace -->\n<!-- newline line-endings with something like {}  -->\n<!-- First, we move left-margin as far left as    -->\n<!-- possible, then strip all comments,  without  -->\n<!-- stripping too much, such as useful \\%        -->\n<!-- We save in a variable, so only here once     -->\n<!-- NB: the \\lt definition is removed in the     -->\n<!-- Jupyter conversion, since the Jupyter        -->\n<!-- \"print to LaTeX\" converter will also define  -->\n<!-- it in order to cover for MathJax's decision  -->\n<!-- to make the definition. So if *any* edit is  -->\n<!-- made here, then the \"replace()\" there will   -->\n<!-- need to be edited to match.                  -->\n<xsl:variable name=\"latex-macros\">\n    <xsl:variable name=\"latex-left-justified\">\n        <xsl:call-template name=\"sanitize-text\">\n            <xsl:with-param name=\"text\">\n                <xsl:value-of select=\"$docinfo/macros\" />\n            </xsl:with-param>\n        </xsl:call-template>\n    </xsl:variable>\n    <xsl:call-template name=\"latex-macro-first-percent\">\n        <xsl:with-param name=\"latex-code\">\n            <xsl:value-of select=\"$latex-left-justified\" />\n        </xsl:with-param>\n    </xsl:call-template>\n    <xsl:text>\\newcommand{\\lt}{&lt;}&#xa;</xsl:text>\n    <xsl:text>\\newcommand{\\gt}{&gt;}&#xa;</xsl:text>\n    <xsl:text>\\newcommand{\\amp}{&amp;}&#xa;</xsl:text>\n</xsl:variable>\n\n<!-- Recursively, line-by-line, find first %                             -->\n<!-- If preceded by \\, then output and reform with rest of line          -->\n<!-- If a naked %, then drop rest of line, tidy up and move to next line -->\n<!-- Every output line ends with a newline                               -->\n<xsl:template name=\"latex-macro-first-percent\">\n    <xsl:param name=\"latex-code\" />\n    <xsl:variable name=\"first-line\" select=\"concat(substring-before($latex-code, '&#xA;'), '&#xA;')\" />\n    <xsl:variable name=\"remainder\" select=\"substring-after($latex-code, '&#xA;')\" />\n    <xsl:choose>\n        <!-- done, quit recursing -->\n        <xsl:when test=\"not($latex-code)\" />\n        <!-- first potential comment character-->\n        <xsl:when test=\"contains($first-line, '%')\">\n            <xsl:variable name=\"initial\" select=\"substring-before($first-line, '%')\" />\n            <xsl:choose>\n                <xsl:when test=\"substring($initial, string-length($initial))='\\'\">\n                    <!-- false positive, output symptom and reorganize -->\n                    <xsl:value-of select=\"concat($initial, '%')\" />\n                    <xsl:call-template name=\"latex-macro-first-percent\">\n                        <xsl:with-param name=\"latex-code\" select=\"concat(substring-after($first-line, '%'), $remainder)\" />\n                    </xsl:call-template>\n                </xsl:when>\n                <xsl:otherwise>\n                    <!-- comment character in first column is no line        -->\n                    <!-- else, content prior, with stripped newline restored -->\n                    <xsl:if test=\"$initial\">\n                        <xsl:value-of select=\"concat($initial, '&#xA;')\" />\n                    </xsl:if>\n                    <!-- move on to remaining lines -->\n                    <xsl:call-template name=\"latex-macro-first-percent\">\n                        <xsl:with-param name=\"latex-code\" select=\"$remainder\" />\n                    </xsl:call-template>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- no action, just echo and work the rest -->\n            <xsl:value-of select=\"$first-line\" />\n            <xsl:call-template name=\"latex-macro-first-percent\">\n                <xsl:with-param name=\"latex-code\" select=\"substring-after($latex-code, '&#xA;')\" />\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- For a \"fillin\" within math.                                       -->\n<!-- First, define math fillin macro that is common to LaTeX, MathJax. -->\n<!-- Then below, template for matching on each \"fillin\".               -->\n<xsl:template name=\"fillin-math\">\n    <xsl:choose>\n        <xsl:when test=\"$fillin-math-style = 'underline'\">\n            <xsl:text>\\newcommand{\\fillinmath}[1]{\\mathchoice</xsl:text>\n            <xsl:text>{\\underline{\\displaystyle     \\phantom{\\ \\,#1\\ \\,}}}</xsl:text>\n            <xsl:text>{\\underline{\\textstyle        \\phantom{\\ \\,#1\\ \\,}}}</xsl:text>\n            <xsl:text>{\\underline{\\scriptstyle      \\phantom{\\ \\,#1\\ \\,}}}</xsl:text>\n            <xsl:text>{\\underline{\\scriptscriptstyle\\phantom{\\ \\,#1\\ \\,}}}}&#xa;</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$fillin-math-style = 'box'\">\n            <xsl:text>\\newcommand{\\fillinmath}[1]{\\mathchoice</xsl:text>\n            <xsl:text>{\\boxed{\\displaystyle     \\phantom{\\,#1\\,}}}</xsl:text>\n            <xsl:text>{\\boxed{\\textstyle        \\phantom{\\,#1\\,}}}</xsl:text>\n            <xsl:text>{\\boxed{\\scriptstyle      \\phantom{\\,#1\\,}}}</xsl:text>\n            <xsl:text>{\\boxed{\\scriptscriptstyle\\phantom{\\,#1\\,}}}}&#xa;</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$fillin-math-style = 'shade'\">\n            <xsl:text>\\definecolor{fillinmathshade}{gray}{0.9}&#xa;</xsl:text>\n            <xsl:text>\\newcommand{\\fillinmath}[1]{\\mathchoice</xsl:text>\n            <xsl:text>{\\colorbox{fillinmathshade}{$\\displaystyle     \\phantom{\\,#1\\,}$}}</xsl:text>\n            <xsl:text>{\\colorbox{fillinmathshade}{$\\textstyle        \\phantom{\\,#1\\,}$}}</xsl:text>\n            <xsl:text>{\\colorbox{fillinmathshade}{$\\scriptstyle      \\phantom{\\,#1\\,}$}}</xsl:text>\n            <xsl:text>{\\colorbox{fillinmathshade}{$\\scriptscriptstyle\\phantom{\\,#1\\,}$}}}&#xa;</xsl:text>\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"m/fillin|mrow/fillin\">\n    <xsl:choose>\n        <xsl:when test=\"@fill\">\n            <xsl:text>\\fillinmath{</xsl:text>\n            <xsl:value-of select=\"@fill\"/>\n            <xsl:text>}</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"@characters\">\n            <xsl:text>\\fillinmath{</xsl:text>\n                <xsl:call-template name=\"duplicate-string\">\n                    <xsl:with-param name=\"count\" select=\"@characters\" />\n                    <xsl:with-param name=\"text\"  select=\"'X'\" />\n                </xsl:call-template>\n            <xsl:text>}</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>\\fillinmath{XXX}</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- For a fillin (not in math) that describes itself as an array -->\n<xsl:template match=\"fillin\" mode=\"fillin-array\">\n    <xsl:variable name=\"rows\">\n        <xsl:choose>\n            <xsl:when test=\"@rows\">\n                <xsl:value-of select=\"@rows\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"1\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"cols\">\n        <xsl:choose>\n            <xsl:when test=\"@cols\">\n                <xsl:value-of select=\"@cols\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"1\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:if test=\"$rows &gt; 1 or $cols &gt; 1\">\n        <xsl:text> (</xsl:text>\n        <xsl:value-of select=\"$rows\"/>\n        <xsl:call-template name=\"character\">\n            <xsl:with-param name=\"name\" select=\"'nbsp'\"/>\n        </xsl:call-template>\n        <xsl:call-template name=\"character\">\n            <xsl:with-param name=\"name\" select=\"'times'\"/>\n        </xsl:call-template>\n        <xsl:call-template name=\"character\">\n            <xsl:with-param name=\"name\" select=\"'nbsp'\"/>\n        </xsl:call-template>\n        <xsl:value-of select=\"$cols\"/>\n        <xsl:text> </xsl:text>\n        <xsl:apply-templates select=\".\" mode=\"type-name\">\n            <xsl:with-param name=\"string-id\" select=\"'array'\"/>\n        </xsl:apply-templates>\n        <xsl:text>)</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- Sage Cells -->\n<!-- Contents are text manipulations (below)     -->\n<!-- Two abstract named templates in other files -->\n<!-- provide the necessary wrapping, per format  -->\n\n<!-- Utility: Class Names -->\n<!-- This is the class we place on \"pre\" elements to have them configure    -->\n<!-- as Sage cells.  This is given in the Javascript call in the head, and  -->\n<!-- on the actual instances of Sage cells.  So this provides consistency.  -->\n<!-- Passing an empty string for the language is historical, and could      -->\n<!-- perhaps be unwound to be the default language in the parameter.        -->\n<xsl:template name=\"sagecell-class-name\">\n    <xsl:param name=\"language-attribute\"/>\n    <xsl:param name=\"b-autoeval\"/>\n\n    <xsl:text>sagecell</xsl:text>\n    <xsl:text>-</xsl:text>\n    <xsl:choose>\n        <xsl:when test=\"$language-attribute=''\">\n            <xsl:text>sage</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"$language-attribute\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n    <xsl:if test=\"$b-autoeval\">\n        <xsl:text>-</xsl:text>\n        <xsl:text>autoeval</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<!-- Type; empty element                      -->\n<!-- Provide an empty cell to scribble in     -->\n<!-- Or break text cells in the Sage notebook -->\n<!-- This cell does respect @language         -->\n<xsl:template match=\"sage[not(input) and not(output) and not(@type)]\">\n    <xsl:apply-templates select=\".\" mode=\"sage-active-markup\">\n        <!-- OK to send empty string, implementation reacts -->\n        <xsl:with-param name=\"language-attribute\">\n            <xsl:value-of select=\"@language\" />\n        </xsl:with-param>\n        <xsl:with-param name=\"b-autoeval\" select=\"@auto-evaluate = 'yes'\"/>\n        <xsl:with-param name=\"in\" select=\"''\"/>\n        <xsl:with-param name=\"out\" select=\"''\" />\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Type: \"invisible\"; to doctest, but never show to a reader -->\n<xsl:template match=\"sage[@type='invisible']\" />\n\n<!-- Type: \"practice\"; empty, but with practice announcement -->\n<!-- We override this in LaTeX, since it is useless          -->\n<!-- (and we can't tell in the abstract wrapping template)   -->\n<xsl:template match=\"sage[@type='practice']\">\n    <xsl:apply-templates select=\".\" mode=\"sage-active-markup\">\n        <xsl:with-param name=\"language-attribute\">\n            <xsl:value-of select=\"'practice'\" />\n        </xsl:with-param>\n        <xsl:with-param name=\"in\" select=\"'# Practice area (not linked for Sage Cell use)&#xa;'\"/>\n        <xsl:with-param name=\"out\" select=\"''\" />\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Type: \"display\"; input portion as uneditable, unevaluatable -->\n<!-- This calls a slightly different abstract template           -->\n<!-- We do not pass along any output, since this is silly        -->\n<!-- These cells are meant to be be incorrect or incomplete      -->\n<xsl:template match=\"sage[@type='display']\">\n    <xsl:call-template name=\"sage-display-markup\">\n        <xsl:with-param name=\"language-attribute\">\n            <xsl:value-of select=\"'display'\" />\n        </xsl:with-param>\n        <xsl:with-param name=\"in\">\n            <xsl:call-template name=\"sanitize-text\">\n                <xsl:with-param name=\"text\" select=\"input\" />\n            </xsl:call-template>\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- Type: \"full\" (the default)         -->\n<!-- Absent meeting any other condition -->\n<xsl:template match=\"sage|sage[@type='full']\">\n    <xsl:apply-templates select=\".\" mode=\"sage-active-markup\">\n        <!-- OK to send empty string, implementation reacts -->\n        <xsl:with-param name=\"language-attribute\">\n            <xsl:value-of select=\"@language\" />\n        </xsl:with-param>\n        <xsl:with-param name=\"b-autoeval\" select=\"@auto-evaluate = 'yes'\"/>\n        <xsl:with-param name=\"in\">\n            <xsl:call-template name=\"sanitize-text\">\n                <xsl:with-param name=\"text\" select=\"input\" />\n            </xsl:call-template>\n        </xsl:with-param>\n        <xsl:with-param name=\"out\">\n            <xsl:if test=\"output\">\n                <xsl:call-template name=\"sanitize-text\" >\n                    <xsl:with-param name=\"text\" select=\"output\" />\n                </xsl:call-template>\n            </xsl:if>\n        </xsl:with-param>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Console Session, prompt on input line-->\n<!-- An interactive command-line session with pairs of input and output -->\n<!-- Determining the prompt is a bit complicated, but always the same   -->\n<!-- and always a pure textual result.  It becomes a part of the input  -->\n<!-- line, so this modal template has an \"input\" as its context.        -->\n<!--                                                                    -->\n<!-- Priority:                                                          -->\n<!--   1.  a specific @prompt on the \"input\" element                    -->\n<!--   2.  an overall session-wide @prompt on the \"console\" element     -->\n<!--   3.  a default, which can be superseded by a session-wide version -->\n<!-- NB: could add a \"docinfo\" element for use just before the default? -->\n<xsl:template match=\"console/input\" mode=\"determine-console-prompt\">\n    <xsl:choose>\n        <xsl:when test=\"@prompt\">\n            <xsl:value-of select=\"@prompt\"/>\n        </xsl:when>\n        <!-- parent is guaranteed to be a \"console\", which can -->\n        <!-- carry a default prompt for the entire session     -->\n        <xsl:when test=\"parent::console/@prompt\">\n            <xsl:value-of select=\"parent::console/@prompt\"/>\n        </xsl:when>\n        <!-- Default is a $-space, could just as well have been >-space -->\n        <xsl:otherwise>\n            <xsl:text>$&#x20;</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Determine what string, if any, should be used for input \"continuation\" -->\n<!-- Each line after the first would be prepended by this string -->\n<!-- Looks for @continuation in the input, fall back to @continuation in console -->\n<!-- Else default to empty. (Or should it be a number of spaces equaling the prompt?) -->\n<xsl:template match=\"console/input\" mode=\"determine-console-continuation\">\n    <xsl:choose>\n        <xsl:when test=\"@continuation\">\n            <xsl:value-of select=\"@continuation\"/>\n        </xsl:when>\n        <!-- parent is guaranteed to be a \"console\", which can    -->\n        <!-- carry a default continuation for the entire session  -->\n        <xsl:when test=\"parent::console/@continuation\">\n            <xsl:value-of select=\"parent::console/@continuation\"/>\n        </xsl:when>\n        <!-- Default is empty -->\n        <xsl:otherwise>\n            <xsl:text/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- ################# -->\n<!-- Preformatted Text -->\n<!-- ################# -->\n\n<!-- Inline \"code\" uses a \"c\" element and we want to be careful, so    -->\n<!-- we use a universal template here, while leaving peculiarities     -->\n<!-- of output formats to their respective stylesheets.  The \"c\"       -->\n<!-- element never has any elements as children, so we grab the        -->\n<!-- author's characters as their intent.  Output markup languages     -->\n<!-- Important: we use a \"value-of\" instruction so that the            -->\n<!-- text-manipulation routines do not get their hands on any          -->\n<!-- whitespace or anything else.  So the parameter $content is pure   -->\n<!-- character data.  A named template means no context, which is only -->\n<!-- a problem when WeBWorK PG formulation wants to provide a location -->\n<!-- report on a failure due to banned markup.                         -->\n<!-- NB: newlines are assumed to be an editing convenience (hard       -->\n<!-- line-breaks as part of word-wrapping, and not intended by the     -->\n<!-- author to be literal.  We have other devices for multi-line       -->\n<!-- verbatim text. -->\n<xsl:template match=\"c\">\n    <!-- With no newlines, we use \"value-of\" to get the characters -->\n    <!-- precisely.  Otherwise, we have newlines and likely each   -->\n    <!-- will be followed by a run of spaces (indentation on the   -->\n    <!-- subsequent line of the source), so we use a recursive     -->\n    <!-- template to scrub the spaces.                             -->\n    <xsl:variable name=\"raw-content\">\n        <xsl:choose>\n            <xsl:when test=\"not(contains(., '&#xa;'))\">\n                <xsl:value-of select=\".\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:call-template name=\"reduce-line-break\">\n                    <xsl:with-param name=\"text\">\n                        <xsl:value-of select=\".\"/>\n                    </xsl:with-param>\n                </xsl:call-template>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- The newlines remain, but all trailing spaces have been -->\n    <!-- scrubbed, so we replace newlines with spaces as part   -->\n    <!-- of the application of the wrapper.                     -->\n    <xsl:call-template name=\"code-wrapper\">\n        <xsl:with-param name=\"content\" select=\"translate($raw-content, '&#xa;', '&#x20;')\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<xsl:template name=\"code-wrapper\">\n    <xsl:message>PTX:BUG:  current conversion needs an implementation of the \"code-wrapper\" template</xsl:message>\n</xsl:template>\n\n\n<!-- The content of a \"pre\" element is wrapped many ways, -->\n<!-- but the content itself is always strictly text       -->\n\n<!-- With no \"cline\", we adjust left margin -->\n<xsl:template match=\"pre\" mode=\"interior\">\n    <xsl:call-template name=\"sanitize-text\">\n        <xsl:with-param name=\"text\" select=\".\" />\n    </xsl:call-template>\n</xsl:template>\n\n<!-- With a \"cline\", we process the lines -->\n<xsl:template match=\"pre[cline]\" mode=\"interior\">\n    <xsl:apply-templates select=\"cline\" />\n</xsl:template>\n\n<!-- Code Lines -->\n<!-- A \"cline\" is used to (optionally) structure hunks     -->\n<!-- of verbatim text.  Due to its simplicity, it should   -->\n<!-- be universal and the only efffect is to add a newline -->\n<!-- character, which the output format should recognize   -->\n<!-- via its own devices.                                  -->\n<!-- NB: the newline provide by the last \"cline\" of a      -->\n<!-- structure is used by some recursive text utilities as -->\n<!-- a signal, such as the \"braille-source-code\" template. -->\n<xsl:template match=\"cline\">\n    <xsl:value-of select=\".\" />\n    <xsl:text>&#xa;</xsl:text>\n</xsl:template>\n\n<!-- ############## -->\n<!-- Lists of Names -->\n<!-- ############## -->\n\n<!-- Authors and editors are people credited in the front matter and in   -->\n<!-- mastheads, etc.  Authors can appear on major divisions, such as      -->\n<!-- chapters and sections.  There can be multiple, and we want to string -->\n<!-- them together with commas, and give editors a parenthetical          -->\n<!-- distinction.                                                         -->\n\n<!-- First, we kill these elements as metadata, so we do not process them  -->\n<!-- in document order, but instead need to always process them with modal -->\n<!-- templates.                                                            -->\n<xsl:template match=\"author|editor\" />\n\n<!-- Names can appear structured in the front matter, unstructured on -->\n<!-- divisions, or as cross-references to contributors.               -->\n<xsl:template match=\"author|editor\" mode=\"name-only\">\n    <xsl:choose>\n        <!-- structured version -->\n        <xsl:when test=\"personname\">\n            <xsl:apply-templates select=\"personname\"/>\n        </xsl:when>\n        <!-- PreTeXt's validation requires the target -->\n        <!-- of the xref to be a contributor element  -->\n        <xsl:when test=\"xref\">\n            <xsl:apply-templates select=\"xref\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\"node()\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Authors, editors in serial lists for headers -->\n<xsl:template match=\"author|editor\" mode=\"name-list\" >\n    <!-- separator, if following -->\n    <xsl:if test=\"preceding-sibling::author|preceding-sibling::editor\">\n        <xsl:text>, </xsl:text>\n    </xsl:if>\n    <!-- name itself, from \"personname\" or the content -->\n    <xsl:apply-templates select=\".\" mode=\"name-only\"/>\n    <xsl:if test=\"self::editor\">\n        <xsl:text> (</xsl:text>\n        <xsl:apply-templates select=\".\" mode=\"type-name\" />\n        <xsl:text>)</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<!-- Text Utilities -->\n<!-- (2022-03-27) A number of basic named templates were split out from this -->\n<!-- location.  Likely wise to move this to the top of this stylesheet.      -->\n<xsl:include href = \"./pretext-text-utilities.xsl\"/>\n\n<!-- Number consumers: serial-number, structure-number, \"number\",     -->\n<!-- xref-number, and division levels.  The native counting           -->\n<!-- primitives they build on live in the assembly pass, which every  -->\n<!-- conversion also imports.                                         -->\n<xsl:include href = \"./pretext-numbers.xsl\"/>\n\n\n<!-- When trying to represent XML source as it would have been authored, -->\n<!-- we \"break\" the escape characters to result in their authored form.  -->\n<!-- TODO: add &apos; and &quot; (which we *never* author,               -->\n<!-- since just necessary for attributes).                               -->\n<xsl:template match=\"node()\" mode=\"serialize-content\">\n    <xsl:param name=\"as-authored-source\"/>\n\n    <xsl:choose>\n        <xsl:when test=\"$as-authored-source = 'no'\">\n            <xsl:value-of select=\".\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- fix raw ampersands before introducing more -->\n            <xsl:variable name=\"fix-ampersand\"    select=\"str:replace(.,              '&amp;', '&amp;amp;')\"/>\n            <xsl:variable name=\"fix-lessthan\"     select=\"str:replace($fix-ampersand, '&lt;',  '&amp;lt;' )\"/>\n            <xsl:variable name=\"fix-greaterthan\"  select=\"str:replace($fix-lessthan,  '&gt;',  '&amp;gt;' )\"/>\n            <xsl:value-of select=\"$fix-greaterthan\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- ################## -->\n<!-- LaTeX Shortcomings -->\n<!-- ################## -->\n\n<!-- Math bits are authored in LaTeX syntax, -->\n<!-- but sometimes LaTeX needs a little help -->\n<!-- to do the right thing.  This help is    -->\n<!-- often common to several output formats, -->\n<!-- so we put these modal templates here.   -->\n\n<!-- Clauses ending with math -->\n<!-- We look for an immediately adjacent/subsequent text -->\n<!-- node and if we get any punctuation, we wrap it for  -->\n<!-- inclusion in the final throes of the math part      -->\n<!-- A corresponding event happens with the following    -->\n<!-- text() node: the punctuation will get scrubbed      -->\n<!-- from there iff the punctuation migrates in this     -->\n\n<!-- Sometimes we just need the mark itself (e.g. braille).  Note -->\n<!-- that the \"mark\" could well be plural, but usuually is not.   -->\n<xsl:template match=\"m|md\" mode=\"get-clause-punctuation-mark\">\n    <xsl:if test=\"(self::m and $b-include-inline) or (self::md and $b-include-display)\">\n        <xsl:variable name=\"trailing-text\" select=\"following-sibling::node()[1]/self::text()\" />\n        <xsl:call-template name=\"leading-clause-punctuation\">\n            <xsl:with-param name=\"text\" select=\"$trailing-text\" />\n        </xsl:call-template>\n    </xsl:if>\n</xsl:template>\n\n<!-- Usually we wrap the punctuation with \\text{} for use   -->\n<!-- inside LaTeX rendering.                                -->\n<!-- NB: this mode name is not great, but we leave it as-is -->\n<!-- from a refactor. A cosmetic refactor could improve it. -->\n<xsl:template match=\"m|md\" mode=\"get-clause-punctuation\">\n    <xsl:if test=\"(self::m and $b-include-inline) or (self::md and $b-include-display)\">\n        <xsl:variable name=\"punctuation\">\n            <xsl:apply-templates select=\".\" mode=\"get-clause-punctuation-mark\"/>\n        </xsl:variable>\n        <xsl:if test=\"not($punctuation = '')\">\n            <xsl:text>\\text{</xsl:text>\n            <xsl:value-of select=\"$punctuation\" />\n            <xsl:text>}</xsl:text>\n        </xsl:if>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- ################################## -->\n<!-- General Text Handling and Clean-Up -->\n<!-- ################################## -->\n\n<!-- Text adjustments -->\n<!-- This is a general template for every text node.  -->\n<!-- Note that most verbatim-ish elements should not  -->\n<!-- be applying templates, but instead will use      -->\n<!-- \"xsl:value-of\".  Math is an exception, since     -->\n<!-- we allow some elements in amongst the            -->\n<!-- \"pure text\" LaTeX syntax.  We are first using    -->\n<!-- it to adjust for clause-ending punctuation       -->\n<!-- being absorbed elsewhere into math, so we place  -->\n<!-- this near math handling.                         -->\n<!--                                                  -->\n<!-- Later Strategy                                   -->\n<!--                                                  -->\n<!-- 1.  \"Display\" objects, such as lists, display    -->\n<!-- math, and displayed verbatim text, can have text -->\n<!-- nodes (before and after), stripped of whitespace -->\n<!-- (trailing and leading, respectively).            -->\n<!--                                                  -->\n<!-- 2.  Any newlines left after this can be removed, -->\n<!-- with some whitespace consolidated                -->\n\n<!-- Punctuation ending a clause of a sentence   -->\n<!-- Asymmetric: no space, mark, space           -->\n<xsl:variable name=\"clause-ending-marks\">\n    <xsl:text>.?!:;,</xsl:text>\n</xsl:variable>\n\n<xsl:template match=\"text()\">\n    <!-- Scrub clause-ending punctuation immediately after math  -->\n    <!-- It migrates and is absorbed in math templates elsewhere -->\n    <!-- Side-effect: resulting leading whitespace is scrubbed   -->\n    <!-- for displayed mathematics (only) as it is irrelevant    -->\n    <xsl:variable name=\"first-char\" select=\"substring(., 1, 1)\" />\n    <xsl:variable name=\"math-punctuation\">\n        <xsl:choose>\n            <!-- drop punctuation after display math, if moving to math -->\n            <xsl:when test=\"$b-include-display and contains($clause-ending-marks, $first-char) and preceding-sibling::node()[1][self::md]\">\n                <xsl:call-template name=\"strip-leading-whitespace\">\n                    <xsl:with-param name=\"text\">\n                        <xsl:call-template name=\"drop-clause-punctuation\">\n                            <xsl:with-param name=\"text\" select=\".\" />\n                        </xsl:call-template>\n                    </xsl:with-param>\n                </xsl:call-template>\n            </xsl:when>\n            <!-- drop punctuation after inline math, if moving to math -->\n            <xsl:when test=\"$b-include-inline and contains($clause-ending-marks, $first-char) and preceding-sibling::node()[1][self::m]\">\n                <xsl:call-template name=\"drop-clause-punctuation\">\n                    <xsl:with-param name=\"text\" select=\".\" />\n                </xsl:call-template>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\".\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- After math clause-ending rearrangements, we provide some    -->\n    <!-- low-level text manipulations.  We do this via a conversion- -->\n    <!-- specific hook, so we do not do more processing than is      -->\n    <!-- necessary, presuming this template is executed frequently.  -->\n    <!-- A math element that allows XML elements within will         -->\n    <!-- be hit with \"xsl:apply-templates\" and arrive here,          -->\n    <!-- so we need to guard against \"text()\" with parents:          -->\n    <!-- \"fillin\", \"xref\", \"var\"   inside   \"m\",  \"mrow\"             -->\n    <!-- The default behavior is a straight copy, with no changes.   -->\n    <!-- NB: We defer WW-specific work for now.                      -->\n    <xsl:variable name=\"text-processed\">\n        <xsl:choose>\n            <xsl:when test=\"not(parent::m|parent::mrow)\">\n                <xsl:call-template name=\"text-processing\">\n                    <xsl:with-param name=\"text\" select=\"$math-punctuation\"/>\n                </xsl:call-template>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$math-punctuation\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- TODO: strip leading whitespace above only under  -->\n    <!-- 'strict' policy, and combine two when clauses.   -->\n    <!-- Below, strip leading and trailing whitespace on  -->\n    <!-- either side of displayed objects, math and lists -->\n    <!-- (only?), in addition to first and last nodes     -->\n    <xsl:choose>\n        <!-- pass through if assuming strict adherence to whitespace policy -->\n        <xsl:when test=\"$whitespace-style = 'strict'\">\n            <xsl:value-of select=\"$text-processed\" />\n        </xsl:when>\n        <!-- We must \"apply-templates\" to math bits in order    -->\n        <!-- to process \"var\", \"fillin\" and \"xref\", so we pass  -->\n        <!-- through neighboring text nodes under any policy    -->\n        <!-- and we handle whitespace specially afterward       -->\n        <xsl:when test=\"parent::*[self::m|self::mrow]\">\n            <xsl:value-of select=\"$text-processed\" />\n        </xsl:when>\n        <!-- If a pure-whitespace text node is bracketed on both sides by -->\n        <!-- index or notation elements, then almost certainly the space  -->\n        <!-- is for source-formatting clarity and not significant for the -->\n        <!-- content.  In particular, in LaTeX output the macros left     -->\n        <!-- behind prevent consolidation of this whitespace and can lead -->\n        <!-- to significant runs of abnormal whitespace in the output.    -->\n        <xsl:when test=\"normalize-space($text-processed) = '' and preceding-sibling::node()[1][self::idx|self::notation] and following-sibling::node()[1][self::idx|self::notation]\"/>\n        <!-- manipulate leading, trailing, intermediate whitespace under flexible policy -->\n        <!-- if only text node inside parent, all three transformations may apply        -->\n        <!-- Note: space after clause-punctuation will not be deleted here               -->\n        <xsl:when test=\"$whitespace-style = 'flexible'\">\n            <xsl:variable name=\"original\" select=\"$text-processed\" />\n            <xsl:variable name=\"front-cleaned\">\n                <xsl:choose>\n                    <xsl:when test=\"not(preceding-sibling::node()[self::*|self::text()]) or preceding-sibling::node()[self::*|self::text()][1][self::md|self::cd|self::pre|self::ol/parent::p|self::ul/parent::p|self::dl/parent::p]\">\n                        <xsl:call-template name=\"strip-leading-whitespace\">\n                            <xsl:with-param name=\"text\" select=\"$original\" />\n                        </xsl:call-template>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:value-of select=\"$original\" />\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:variable>\n            <xsl:variable name=\"back-cleaned\">\n                <xsl:choose>\n                    <xsl:when test=\"not(following-sibling::node()[self::*|self::text()])  or following-sibling::node()[self::*|self::text()][1][self::md|self::cd|self::pre|self::ol/parent::p|self::ul/parent::p|self::dl/parent::p]\">\n                        <xsl:call-template name=\"strip-trailing-whitespace\">\n                            <xsl:with-param name=\"text\" select=\"$front-cleaned\" />\n                        </xsl:call-template>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:value-of select=\"$front-cleaned\" />\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:variable>\n            <xsl:variable name=\"middle-cleaned\">\n                <xsl:call-template name=\"strip-newlines\">\n                    <xsl:with-param name=\"text\" select=\"$back-cleaned\" />\n                </xsl:call-template>\n            </xsl:variable>\n            <!-- ACTUAL output -->\n            <xsl:value-of select=\"$middle-cleaned\" />\n            <!-- comes from ws.debug string parameter -->\n            <xsl:if test=\"$wsdebug and not($text-processed = $middle-cleaned)\">\n                <!-- DEBUGGING follows, maybe move outward later -->\n                <xsl:message>\n                    <xsl:text>PTX:DEBUG: whitespace diagnostic&#xa;</xsl:text>\n                    <xsl:text>O:</xsl:text>\n                    <xsl:value-of select=\".\" />\n                    <xsl:text>:O&#xa;</xsl:text>\n                    <xsl:text>M:</xsl:text>\n                    <xsl:value-of select=\"$text-processed\" />\n                    <xsl:text>:M&#xa;</xsl:text>\n                    <xsl:text>F:</xsl:text>\n                    <xsl:value-of select=\"$front-cleaned\" />\n                    <xsl:text>:F&#xa;</xsl:text>\n                    <xsl:text>B:</xsl:text>\n                    <xsl:value-of select=\"$back-cleaned\" />\n                    <xsl:text>:B&#xa;</xsl:text>\n                    <xsl:text>M:</xsl:text>\n                    <xsl:value-of select=\"$middle-cleaned\" />\n                    <xsl:text>:M&#xa;</xsl:text>\n                    <xsl:text>****&#xa;</xsl:text>\n                </xsl:message>\n            </xsl:if>\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Text-processing should be done carefully in a per-conversion -->\n<!-- manner.  Absent anything special, we just duplicate.         -->\n<xsl:template name=\"text-processing\">\n    <xsl:param name=\"text\"/>\n    <xsl:value-of select=\"$text\"/>\n</xsl:template>\n\n<!-- Date and Time Functions -->\n<!-- http://stackoverflow.com/questions/1437995/how-to-convert-2009-09-18-to-18th-sept-in-xslt -->\n<!-- http://remysharp.com/2008/08/15/how-to-default-a-variable-in-xslt/ -->\n<xsl:template match=\"today\">\n    <xsl:variable name=\"format\">\n        <xsl:choose>\n            <xsl:when test=\"@format\"><xsl:value-of select=\"@format\" /></xsl:when>\n            <xsl:otherwise>month-day-year</xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"datetime\" select=\"substring(date:date-time(),1,10)\" />\n    <xsl:choose>\n        <xsl:when test=\"$format='month-day-year'\">\n            <xsl:value-of select=\"date:month-name($datetime)\" />\n            <xsl:text> </xsl:text>\n            <xsl:value-of select=\"date:day-in-month($datetime)\" />\n            <xsl:text>, </xsl:text>\n            <xsl:value-of select=\"date:year($datetime)\" />\n        </xsl:when>\n        <xsl:when test=\"$format='yyyy/mm/dd'\">\n            <xsl:value-of select=\"substring($datetime, 1, 4)\" />\n            <xsl:text>/</xsl:text>\n            <xsl:value-of select=\"substring($datetime, 6, 2)\" />\n            <xsl:text>/</xsl:text>\n            <xsl:value-of select=\"substring($datetime, 9, 2)\" />\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Could use a format to suppress/manipulate time zone -->\n<xsl:template match=\"timeofday\">\n    <xsl:value-of select=\"substring(date:date-time(),12,8)\" />\n    <xsl:text> (</xsl:text>\n    <xsl:value-of select=\"substring(date:date-time(),20)\" />\n    <xsl:text>)</xsl:text>\n</xsl:template>\n\n<!-- ################## -->\n<!-- Document Structure -->\n<!-- ################## -->\n\n<!-- Structural Nodes -->\n<!-- Some elements of the XML tree are structural elements of the document tree  -->\n<!-- This is our logical overlay on the (finer, larger, more expansive) XML tree -->\n<!-- Example: <section> is structural, and ancestors are all structural          -->\n<!-- Example: <title> is not structural, but does have a structural ancestor     -->\n<!-- NB: These elements need only be specified here, and in leaf template (next) -->\n<xsl:template match=\"&STRUCTURAL;\" mode=\"is-structural\">\n    <xsl:value-of select=\"true()\" />\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"is-structural\">\n    <xsl:value-of select=\"false()\" />\n</xsl:template>\n\n<!-- Structural Leaves -->\n<!-- Some structural elements of the document tree     -->\n<!-- are the leaves of that tree, meaning they do      -->\n<!-- not contain any structural nodes themselves       -->\n<!-- backmatter is always structured, else no purpose  -->\n<!-- frontmatter is anomalous:  \"titlepage\" (and       -->\n<!-- for an \"article\", \"abstract\") are not treated     -->\n<!-- as divisions, they just get mined as part of the  -->\n<!-- frontmatter itself.  So an article/frontmatter    -->\n<!-- is always a leaf, and a book/frontmatter is not   -->\n<!-- a leaf if it has a child other than a \"titlepage\" -->\n<!-- Generally, we look for definitive markers         -->\n<!-- NB: references, exercises, solutions not relevant -->\n<xsl:template match=\"&STRUCTURAL;\" mode=\"is-leaf\">\n    <xsl:choose>\n        <xsl:when test=\"self::frontmatter\">\n            <xsl:choose>\n                <xsl:when test=\"parent::article\">\n                    <xsl:value-of select=\"true()\" />\n                </xsl:when>\n                <xsl:when test=\"parent::book\">\n                    <xsl:value-of select=\"not(*[not(self::titlepage)])\" />\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:BUG:     asking if a \"frontmatter\" is a leaf, for a document that is not a \"book\" nor an \"article\"</xsl:message>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <xsl:when test=\"self::backmatter\">\n            <xsl:value-of select=\"false()\" />\n        </xsl:when>\n        <!-- The presence of a traditional division is emblematic of a structured -->\n        <!-- division, so not a leaf of the structural/document tree              -->\n        <xsl:when test=\"part or chapter or section or subsection or subsubsection\">\n            <xsl:value-of select=\"false()\" />\n        </xsl:when>\n        <!-- One exception, a division full of only \"worksheet\" or \"handout\"     -->\n        <!-- (as a subdivision, there could be metadata, \"introduction\", etc.)   -->\n        <!-- We know there are no traditional divisions as subdiivisions at this -->\n        <!-- point.  So we test for at least one worksheet or handout and no     -->\n        <!-- other specialized divisions.                                        -->\n        <xsl:when test=\"(worksheet or handout) and not(exercises|references|glossary|reading-questions|solutions)\">\n            <xsl:value-of select=\"false()\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"true()\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- This once just returned false,      -->\n<!-- but should maybe not even be called -->\n<xsl:template match=\"*\" mode=\"is-leaf\">\n    <xsl:value-of select=\"false()\" />\n    <!-- <xsl:message>PTX:BUG:     asking if a non-structural division is a leaf</xsl:message> -->\n</xsl:template>\n\n<!-- Test if element is a specialized division or not. -->\n<!-- If element is not even a division, give error.    -->\n<xsl:template match=\"*\" mode=\"is-specialized-division\">\n    <xsl:choose>\n        <xsl:when test=\"&TRADITIONAL-DIVISION-FILTER;\">\n            <xsl:value-of select=\"false()\"/>\n        </xsl:when>\n        <xsl:when test=\"&SPECIALIZED-DIVISION-FILTER;\">\n            <xsl:value-of select=\"true()\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message>PTX:BUG: asking if a non-division (<xsl:value-of select=\"local-name(.)\"/>) is a specialized division</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- We also want to identify smaller pieces of a document,          -->\n<!-- such as when they contain an index element or defined term,     -->\n<!-- so we can reference back to them.  We call these \"blocks\" here, -->\n<!-- which mostly corresponds to the use of the term in the DTD.     -->\n<!-- The difference is that a paragraph is a \"block\" if and only if  -->\n<!-- it is a direct descendant of a structural node or a directly    -->\n<!-- descended introduction or conclusion .                          -->\n<!-- Also, list items are considered blocks.                         -->\n<!-- NB: we don't point to a sidebyside, so not included here        -->\n<xsl:template match=\"md[mrow]|ul|ol|dl|blockquote|pre|sage|&FIGURE-LIKE;|poem|program|image|tabular|paragraphs|&DEFINITION-LIKE;|&THEOREM-LIKE;|&AXIOM-LIKE;|&REMARK-LIKE;|&COMPUTATION-LIKE;|&EXAMPLE-LIKE;|&PROJECT-LIKE;|assemblage|exercise|li\" mode=\"is-block\">\n    <xsl:value-of select=\"true()\" />\n</xsl:template>\n\n<xsl:template match=\"p\" mode=\"is-block\">\n    <xsl:choose>\n        <xsl:when test=\"parent::introduction or parent::conclusion\">\n            <xsl:variable name=\"interloper\" select=\"parent::*\" />\n            <xsl:apply-templates select=\"$interloper/parent::*\" mode=\"is-structural\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\"parent::*\" mode=\"is-structural\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"is-block\">\n    <xsl:value-of select=\"false()\" />\n</xsl:template>\n\n<!-- FIGURE-LIKE as panels of sidebyside -->\n<!-- A \"figure\", \"table\", \"list\", or \"listing\" has slightly different    -->\n<!-- behavior (potentially) when appearing as a panel of a \"sidebyside\". -->\n<!-- It can be \"subnumbered\" (e.g. (a), (b), (c),...) or it may normally -->\n<!-- be titled above, and we want to place the title below (more like a  -->\n<!-- caption) so the faux-titles and captions seem to (almost) align     -->\n<!-- vertically with each other.  Generally this means authoring the     -->\n<!-- panel with bottom alignment.                                        -->\n<!--                                                                     -->\n<!--   \"block\" - child of a division, captions below, titles above,      -->\n<!--     as according to CMoS.                                           -->\n<!--                                                                     -->\n<!--   \"panel\" - a panel of a side-by-side, but with a block number      -->\n<!--     of its own, since there is no enclosing \"figure\"                -->\n<!--                                                                     -->\n<!--   \"subnumber\" - a panel of a side-by-side, which in turn is a       -->\n<!--     child/descendant of a \"figure\" (a \"sbsgroup\" may intervene).    -->\n<!--     This triggers a block number foor the exterior \"figure\" and     -->\n<!--     a subnumber for the interior FIGURE-LIKE.                       -->\n<!--                                                                     -->\n<!-- (These code comments are referenced in the LaTeX conversion.)       -->\n<!--                                                                     -->\n<xsl:template match=\"&FIGURE-LIKE;\" mode=\"figure-placement\">\n    <!-- more specific first, reverse of description above -->\n    <xsl:choose>\n        <xsl:when test=\"parent::sidebyside and ancestor::figure\">\n            <xsl:text>subnumber</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"parent::sidebyside\">\n            <xsl:text>panel</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>block</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- ####################### -->\n<!-- Chunking Document Nodes -->\n<!-- ####################### -->\n\n\n<!-- When we break a document into pieces, known as \"chunks,\"       -->\n<!-- there is a configurable level (the \"chunk-level\") where        -->\n<!-- the document nodes at that level are always a chunk.           -->\n<!-- At a lesser level, document nodes are \"intermediate\" nodes     -->\n<!-- and so are output as summaries of their children.              -->\n<!-- However, an intermediate node may have no children             -->\n<!-- (is a \"leaf\") and hence is output as a chunk.                  -->\n<!--                                                                -->\n<!-- Said differently, chunks are natural leaves of the document    -->\n<!-- tree, or leaves (dead-ends) manufactured by an arbitrary       -->\n<!-- cutoff given by the chunk-level variable                       -->\n<!--                                                                -->\n<!-- So we have three types of document nodes:                      -->\n<!-- Intermediate: structural node, not a document leaf, smaller    -->\n<!--               level than chunk-level                           -->\n<!--   Realization: some content (title, introduction, conclusion), -->\n<!--                links/includes to children                      -->\n<!-- Leaf: structural node, at chunk-level or a leaf at smaller     -->\n<!--       level than chunk-level                                   -->\n<!--   Realization: a chunk will all content                        -->\n<!-- Neither: A structural node that is simply a (visual)           -->\n<!--          division of a chunk                                   -->\n<!--   Realization: usual presentation, within the enclosing chunk  -->\n\n\n<!-- A conversion opts in to \"division companion\" chunks: the four   -->\n<!-- elements of &DIVISION-COMPANION; earn their own page (chunk)    -->\n<!-- exactly when their parent division is realized as a summary    -->\n<!-- (intermediate) page.  The HTML conversion opts in; conversions -->\n<!-- with their own chunking (WeBWorK sets, Sage doctest) do not.   -->\n<xsl:variable name=\"b-division-companion-chunks\" select=\"false()\"/>\n\n<!-- An intermediate node is at lesser level -->\n<!-- than chunk-level and is not a leaf      -->\n <xsl:template match=\"*\" mode=\"is-intermediate\">\n    <xsl:variable name=\"structural\">\n        <xsl:apply-templates select=\".\" mode=\"is-structural\" />\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$structural='true'\">\n            <xsl:variable name=\"current-level\">\n                <xsl:apply-templates select=\".\" mode=\"level\" />\n            </xsl:variable>\n            <xsl:variable name=\"leaf\">\n                <xsl:apply-templates select=\".\" mode=\"is-leaf\" />\n            </xsl:variable>\n            <xsl:value-of select=\"($leaf='false') and ($chunk-level > $current-level)\" />\n        </xsl:when>\n        <xsl:when test=\"$structural='false'\">\n            <xsl:value-of select=\"$structural\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message>PTX:BUG: Structural determination (<xsl:value-of select=\"$structural\" />) failed for is-intermediate at <xsl:apply-templates select=\".\" mode=\"long-name\"/></xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- A chunk node is at the chunk-level, -->\n<!-- or a leaf at a lesser level         -->\n<xsl:template match=\"*\" mode=\"is-chunk\">\n    <xsl:variable name=\"structural\">\n        <xsl:apply-templates select=\".\" mode=\"is-structural\" />\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$structural='true'\">\n            <xsl:variable name=\"current-level\">\n                <xsl:apply-templates select=\".\" mode=\"level\" />\n            </xsl:variable>\n            <xsl:variable name=\"leaf\">\n                <xsl:apply-templates select=\".\" mode=\"is-leaf\" />\n            </xsl:variable>\n            <xsl:value-of select=\"($chunk-level = $current-level) or ( ($leaf='true') and ($chunk-level > $current-level) )\" />\n        </xsl:when>\n        <xsl:when test=\"$structural='false'\">\n            <xsl:value-of select=\"$structural\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message>PTX:BUG: Structural determination (<xsl:value-of select=\"$structural\" />) failed for is-chunk at <xsl:apply-templates select=\".\" mode=\"long-name\"/></xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- A division companion is a chunk exactly when its parent -->\n<!-- is a summary (intermediate) page, and the conversion    -->\n<!-- has opted in.  It is never an intermediate node itself  -->\n<!-- (the generic template answers correctly), and it is     -->\n<!-- inline content of its parent's page in every other case -->\n<xsl:template match=\"&DIVISION-COMPANION;\" mode=\"is-chunk\">\n    <xsl:choose>\n        <xsl:when test=\"$b-division-companion-chunks\">\n            <xsl:apply-templates select=\"parent::*\" mode=\"is-intermediate\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"false()\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- #################################### -->\n<!-- Abstract Chunking of Structural Nodes-->\n<!-- #################################### -->\n\n<!-- Implementations get structural nodes of two types          -->\n<!--                                                            -->\n<!--   1) \"chunk\"                                               -->\n<!--       usually realizable as a single file by               -->\n<!--       applying default templates                           -->\n<!--                                                            -->\n<!--   2) \"intermediate\":                                       -->\n<!--       usually realizable as a single file with a title,    -->\n<!--       introduction and conclusion surrounding a summary    -->\n<!--       of the subdivisions it contains                      -->\n<!--                                                            -->\n<!-- So an implementation must implement two modal templates    -->\n<!--                                                            -->\n<!--   1) match=\"&STRUCTURAL;\" mode=\"chunk\"                     -->\n<!--   2) match=\"&STRUCTURAL;\" mode=\"intermediate\"              -->\n<!--                                                            -->\n<!-- Similarities can be consolidated within the implementation -->\n<!-- See  xsl/pretext-html.xsl  for a canonical example         -->\n<!--                                                            -->\n<!-- See the discussion just above to understand leaves of the  -->\n<!-- document tree (always chunks), manufactured leaves (due to -->\n<!-- an arbitrary, but configured, chunk level depth), and      -->\n<!-- intermediate nodes (structured divisions above the chunk   -->\n<!-- level line).                                               -->\n<!--                                                            -->\n<!-- NB: as of 2020-12-30 these implementations are used        -->\n<!-- directly as-is or are overridden (in part) by the          -->\n<!-- conversions to WeBWorK problem sets and logical files for  -->\n<!-- Sage doctesting.  They are also extended in the HTML       -->\n<!-- conversion, which is again extended by the EPUB and        -->\n<!-- Jupyter conversions.  This is an exhaustive list of uses.  -->\n\n<xsl:template match=\"&STRUCTURAL;\" mode=\"chunking\">\n    <xsl:variable name=\"chunk\">\n        <xsl:apply-templates select=\".\" mode=\"is-chunk\" />\n    </xsl:variable>\n     <xsl:choose>\n        <xsl:when test=\"$chunk='true'\">\n            <xsl:apply-templates select=\".\" mode=\"chunk\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\".\" mode=\"intermediate\" />\n            <xsl:apply-templates select=\"&STRUCTURAL;|&DIVISION-COMPANION;\" mode=\"chunking\" />\n        </xsl:otherwise>\n    </xsl:choose>\n </xsl:template>\n\n<!-- A division companion produces a page (chunk) or nothing: -->\n<!-- it is only visited via the recursion above, so a parent  -->\n<!-- summary page is guaranteed, but the opt-in may be off    -->\n<xsl:template match=\"&DIVISION-COMPANION;\" mode=\"chunking\">\n    <xsl:variable name=\"chunk\">\n        <xsl:apply-templates select=\".\" mode=\"is-chunk\" />\n    </xsl:variable>\n    <xsl:if test=\"$chunk = 'true'\">\n        <xsl:apply-templates select=\".\" mode=\"chunk\" />\n    </xsl:if>\n</xsl:template>\n\n<!-- docinfo, and anything else, is immune and dead-ends -->\n<xsl:template match=\"*\" mode=\"chunking\" />\n\n<!-- With an implementation of a file-wrapping routine,     -->\n<!-- a typical use is to                                    -->\n<!--                                                        -->\n<!--   (a) apply a default template to the structural       -->\n<!--       node for a complete (chunk'ed) node              -->\n<!--                                                        -->\n<!--   (b) apply a modal template to the structural         -->\n<!--       node for a summary (intermediate) node           -->\n<!--                                                        -->\n<!-- The \"file-wrap\" routine should accept a $content       -->\n<!-- parameter holding the contents of the body of the page -->\n\n<!-- A complete file/page for a structural division         -->\n<xsl:template match=\"&STRUCTURAL;|&DIVISION-COMPANION;\" mode=\"chunk\">\n    <xsl:apply-templates select=\".\" mode=\"file-wrap\">\n        <xsl:with-param name=\"content\">\n            <xsl:apply-templates select=\".\" />\n        </xsl:with-param>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- An intermediate file/page for a structural division    -->\n<!-- It is very possible this implementation is not correct -->\n<!-- or desirable, since the notion of an \"intermediate\"    -->\n<!-- (or \"summary\") page/file is a bit unusual.             -->\n<!--                                                        -->\n<!-- See  xsl/pretext-ww-problem-sets.xsl  for an example   -->\n<!-- use, in addition to a non-trivial application for the  -->\n<!-- (primary) HTML conversion. -->\n<!--                                                        -->\n<!-- See  xsl/pretext-sage-doctest.xsl  for a conversion    -->\n<!-- which only implements the \"file-wrap\" template.        -->\n<xsl:template match=\"&STRUCTURAL;\" mode=\"intermediate\">\n    <xsl:apply-templates select=\".\" mode=\"file-wrap\">\n        <xsl:with-param name=\"content\">\n            <xsl:apply-templates select=\"*[not(&STRUCTURAL-FILTER;)]\" />\n        </xsl:with-param>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Containing Filenames, URLs -->\n<!-- Relative to the chunking in effect, every -->\n<!-- XML element is born within some file.     -->\n<!-- That filename will have a different       -->\n<!-- suffix in different conversions.          -->\n<!-- Parameter: $file-extension, set globally  -->\n<xsl:template match=\"*\" mode=\"containing-filename\">\n    <!-- this is a frequent programming error -->\n    <xsl:if test=\"$chunk-level = ''\">\n        <xsl:message>PTX:BUG:   the $chunk-level variable is empty, so must have been set improperly, perhaps when overridden in a conversion.  The \"containing-filename\" template is likely to act incorrectly.  Please report me</xsl:message>\n    </xsl:if>\n    <xsl:variable name=\"intermediate\">\n        <xsl:apply-templates select=\".\" mode=\"is-intermediate\" />\n    </xsl:variable>\n    <xsl:variable name=\"chunk\">\n        <xsl:apply-templates select=\".\" mode=\"is-chunk\" />\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$intermediate='true' or $chunk='true'\">\n            <xsl:apply-templates select=\".\" mode=\"unique-id\" />\n            <xsl:value-of select=\"$file-extension\" />\n        </xsl:when>\n        <!-- Halts since \"mathbook\" element will be chunk (or earlier) -->\n        <xsl:otherwise>\n            <xsl:apply-templates select=\"..\" mode=\"containing-filename\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Context URL                                                   -->\n<!-- URL for an element on its containing HTML page.               -->\n<!-- Produces: baseurl + containing-filename + \"#\" + unique-id     -->\n<!-- Empty when no baseurl is configured.                          -->\n<!-- NB: requires $chunk-level and $file-extension to be set       -->\n<!-- correctly for HTML output (as in extract-qrcode.xsl).         -->\n<xsl:template match=\"audio|video|interactive\" mode=\"context-url\">\n    <xsl:if test=\"$b-has-baseurl\">\n        <xsl:value-of select=\"$baseurl\"/>\n        <xsl:apply-templates select=\".\" mode=\"containing-filename\"/>\n        <xsl:text>#</xsl:text>\n        <xsl:apply-templates select=\".\" mode=\"unique-id\"/>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- ###### -->\n<!-- Titles -->\n<!-- ###### -->\n\n<!-- Titles are like metadata, they are a useful property    -->\n<!-- of many things and they migrate many different places.  -->\n<!-- So principally, we kill them on sight.  But we provide  -->\n<!-- modal templates as interfaces to titles and derivatives -->\n<!-- of them for purposes where only a restricted subset of  -->\n<!-- their content is allowed.                               -->\n<!--                                                         -->\n<!-- Also, many stock divisions have natural default titles, -->\n<!-- so we want to accomodate that option, and do so via     -->\n<!-- the localization routines.                              -->\n\n\n<!-- With modal templates below, the default template does nothing   -->\n<!-- We include the \"creator\" element of a theorem/axiom as metadata -->\n<!-- NB: since these elements get killed on-sight, when we actually  -->\n<!-- want to process them we need to use a \"select\" attribute        -->\n<!-- similar to  title/*|title/text() or title/node().               -->\n<xsl:template match=\"title\" />\n<xsl:template match=\"subtitle\" />\n<xsl:template match=\"shorttitle\"/>\n<xsl:template match=\"plaintitle\"/>\n<xsl:template match=\"creator\" />\n\n<!-- Some items have default titles that make sense         -->\n<!-- Typically these are one-off subdivisions (eg preface), -->\n<!-- or repeated generic divisions (eg exercises)           -->\n<xsl:template match=\"frontmatter|colophon|preface|foreword|acknowledgement|dedication|biography|abstract|references|glossary|exercises|worksheet|handout|reading-questions|exercisegroup|solutions|backmatter|index|case|interactive/instructions|keywords\" mode=\"has-default-title\">\n    <xsl:text>true</xsl:text>\n</xsl:template>\n<xsl:template match=\"*\" mode=\"has-default-title\">\n    <xsl:text>false</xsl:text>\n</xsl:template>\n\n<!-- NB: these templates return a property of the title's parent -->\n\n<xsl:template match=\"keywords\" mode=\"default-title\">\n    <xsl:choose>\n        <xsl:when test=\"@authority='msc'\">\n            <xsl:if test=\"@variant\">\n                <xsl:value-of select=\"@variant\"/>\n                <xsl:text>&#160;</xsl:text>\n            </xsl:if>\n            <xsl:text>Math Subject Classification</xsl:text>\n        </xsl:when>\n        <!-- Default is @authority='author' or no recognized authority given -->\n        <xsl:otherwise>\n            <xsl:apply-templates select=\".\" mode=\"type-name\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Normally a default title is the \"type-name\" of the object. -->\n<!-- But to indicate that a \"worksheet\" or \"exercises\" division -->\n<!-- is groupwork, we preface the title.                        -->\n<xsl:template match=\"*\" mode=\"default-title\">\n    <xsl:if test=\"(@groupwork= 'yes') and (self::worksheet or self::exercises)\">\n        <xsl:apply-templates select=\".\" mode=\"type-name\">\n            <xsl:with-param name=\"string-id\" select=\"'group'\"/>\n        </xsl:apply-templates>\n        <xsl:text> </xsl:text>\n    </xsl:if>\n    <xsl:apply-templates select=\".\" mode=\"type-name\"/>\n</xsl:template>\n\n\n<!-- This has much of the logic of producing a title, but lacks any  -->\n<!-- additional punctuation, so is useful for titles employed places  -->\n<!-- other than immediately adjacent to the content they describe. -->\n<xsl:template match=\"*\" mode=\"title-xref\">\n    <xsl:variable name=\"default-exists\">\n        <xsl:apply-templates select=\".\" mode=\"has-default-title\" />\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"title/line\">\n            <xsl:apply-templates select=\"title/line\">\n                <xsl:with-param name=\"separator\" select=\"$title-separator\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- select=\"title\" would just get it killed -->\n        <xsl:when test=\"title\">\n            <xsl:apply-templates select=\"title/node()\" />\n        </xsl:when>\n        <xsl:when test=\"$default-exists='true'\">\n            <xsl:apply-templates select=\".\" mode=\"default-title\"/>\n        </xsl:when>\n        <!-- otherwise empty -->\n        <xsl:otherwise />\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"title-full\">\n    <!-- first, the punctuation-less version -->\n    <xsl:apply-templates select=\".\" mode=\"title-xref\"/>\n    <!-- Should we add punctuation?                       -->\n    <!--   1. Should not have any already,                -->\n    <!--   2. Or should be a default version,             -->\n    <!--   3. Plus should be a situation where we want it -->\n\n    <!-- with no title present, first variable is an empty string -->\n    <xsl:variable name=\"has-punctuation\">\n        <xsl:apply-templates select=\"title\" mode=\"has-punctuation\"/>\n    </xsl:variable>\n    <xsl:variable name=\"default-exists\">\n        <xsl:apply-templates select=\".\" mode=\"has-default-title\" />\n    </xsl:variable>\n    <xsl:variable name=\"default-in-use\">\n        <xsl:value-of select=\"not(title) and $default-exists = 'true'\"/>\n    </xsl:variable>\n    <xsl:variable name=\"wants-period\">\n        <xsl:apply-templates select=\".\" mode=\"title-wants-punctuation\"/>\n    </xsl:variable>\n    <xsl:if test=\"(($has-punctuation = 'false') or ($default-in-use = 'true')) and ($wants-period = 'true')\">\n        <xsl:text>.</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<!-- This template does elective sanitization of a title, which  -->\n<!-- is distinct for universal adjustments (such as protecting   -->\n<!-- LaTeX macros, or making any \"xref\" static.  So removing a   -->\n<!-- footnote is such a sanitization (we allow it on a \"real\"    -->\n<!-- title, but not when migrating other places).  This template -->\n<!-- is not called often, usually the \"title-short\" template is  -->\n<!-- the right template to call when a title is duplicated.      -->\n<!-- We pass a space for the version structured with \"line\".     -->\n<!-- TODO: ban fn in titles, then maybe this is obsolete -->\n<!-- or maybe we should be careful about math            -->\n<xsl:template match=\"*\" mode=\"title-simple\">\n    <xsl:variable name=\"default-exists\">\n        <xsl:apply-templates select=\".\" mode=\"has-default-title\" />\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"title/line\">\n            <xsl:apply-templates select=\"title/line\">\n                <xsl:with-param name=\"separator\" select=\"' '\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- select=\"title\" would just get it killed -->\n        <!-- avoid footnotes in simple version       -->\n        <xsl:when test=\"title\">\n            <xsl:apply-templates select=\"title/*[not(self::fn)]|title/text()\" />\n        </xsl:when>\n        <xsl:when test=\"$default-exists='true'\">\n            <xsl:apply-templates select=\".\" mode=\"default-title\"/>\n        </xsl:when>\n        <!-- otherwise empty -->\n        <xsl:otherwise />\n    </xsl:choose>\n</xsl:template>\n\n<!-- Short titles are meant for places such as the Table of  -->\n<!-- Contents and for LaTeX, the page headers and/or footers -->\n<!-- It'd be silly to structure this with \"line\"             -->\n<xsl:template match=\"*\" mode=\"title-short\">\n    <xsl:choose>\n        <!-- schema should control content, eg no footnotes -->\n        <!-- optional, so check for author's suggestion     -->\n        <xsl:when test=\"shorttitle\">\n            <xsl:apply-templates select=\"shorttitle/node()[not(self::fn)]\"/>\n        </xsl:when>\n        <!-- else, existing title, cleaned up -->\n        <xsl:otherwise>\n            <xsl:apply-templates select=\".\" mode=\"title-simple\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- A version of the title with all abnormal characters stripped -->\n<!-- and using underscores in place of spaces                     -->\n<!-- http://stackoverflow.com/questions/1267934/                  -->\n<!-- removing-non-alphanumeric-characters-from-string-in-xsl      -->\n<xsl:template match=\"*\" mode=\"title-filesafe\">\n    <!-- first, the simple title -->\n    <xsl:variable name=\"raw-title\">\n        <xsl:apply-templates select=\".\" mode=\"title-simple\"/>\n    </xsl:variable>\n    <xsl:variable name=\"letter-only-title\">\n        <xsl:value-of select=\"translate($raw-title, translate($raw-title, concat(&SIMPLECHAR;,' '), ''), '')\" />\n    </xsl:variable>\n    <xsl:value-of select=\"translate($letter-only-title, ' ', '_')\" />\n</xsl:template>\n\n<!-- This comes from writing out WW problems to filenames    -->\n<!-- in some sort of reasonable numbering scheme             -->\n<!-- It is not integrated into the above complexity-scheme   -->\n<!-- (though does call the \"title-filesafe\" modal template)  -->\n<!-- Consider integration if there is a refactoring of above -->\n<xsl:template match=\"*\" mode=\"numbered-title-filesafe\">\n    <!-- traditional \"dotted\" number -->\n    <xsl:variable name=\"dotted-number\">\n        <xsl:apply-templates select=\".\" mode=\"number\" />\n    </xsl:variable>\n    <xsl:variable name=\"title-string\">\n        <xsl:apply-templates select=\".\" mode=\"title-filesafe\" />\n    </xsl:variable>\n    <!-- number output, with dot to dash conversion -->\n    <xsl:value-of select=\"translate($dotted-number, '.', '_')\" />\n    <!-- separator, if needed -->\n    <xsl:if test=\"not($dotted-number = '' or $title-string = '')\">\n        <xsl:text>-</xsl:text>\n    </xsl:if>\n    <xsl:value-of select=\"$title-string\" />\n</xsl:template>\n\n<!-- We get subtitles the same way, but with no variations -->\n<!-- Structured with \"line\" is a possibility               -->\n<xsl:template match=\"*\" mode=\"subtitle\">\n    <xsl:choose>\n        <xsl:when test=\"subtitle/line\">\n            <xsl:apply-templates select=\"subtitle/line\">\n                <xsl:with-param name=\"separator\" select=\"$title-separator\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- select=\"subtitle\" would just get it killed -->\n        <xsl:when test=\"subtitle\">\n            <xsl:apply-templates select=\"subtitle/*|subtitle/text()\" />\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Plain title: motivation is browser tabs without extensive -->\n<!-- MathJax markup around (little bits) of mathematics        -->\n<!-- Also used for <meta> in HTML carrying identification      -->\n<xsl:template match=\"*\" mode=\"title-plain\">\n    <xsl:variable name=\"default-exists\">\n        <xsl:apply-templates select=\".\" mode=\"has-default-title\" />\n    </xsl:variable>\n    <xsl:choose>\n        <!-- \"plaintitle\" has *no* markup, but we do strip extra   -->\n        <!-- whitespace by sending to generic text node processing -->\n        <xsl:when test=\"plaintitle\">\n            <xsl:apply-templates select=\"plaintitle/text()\"/>\n        </xsl:when>\n        <xsl:when test=\"title\">\n            <xsl:apply-templates select=\"title/node()[not(self::fn)]\" mode=\"plain-title-edit\"/>\n        </xsl:when>\n        <!-- We assume the automatic titles are plain -->\n        <xsl:when test=\"$default-exists='true'\">\n            <xsl:apply-templates select=\".\" mode=\"default-title\"/>\n        </xsl:when>\n        <!-- just empty if there is no titles, no default -->\n        <xsl:otherwise/>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Plain subtitle: used for HTML <meta> tags -->\n<xsl:template match=\"*\" mode=\"subtitle-plain\">\n    <xsl:if test=\"subtitle\">\n        <xsl:apply-templates select=\"subtitle/node()[not(self::fn)]\" mode=\"plain-title-edit\"/>\n    </xsl:if>\n</xsl:template>\n\n<!-- We do not wrap an \"m\" element as part of a plain title -->\n<!-- This will misbehave for m/xref and m/fillin, etc, but  -->\n<!-- these devices should not be in a title anyway          -->\n<!-- N.B. this would be a place to do some crude            -->\n<!-- substitutions, such as \"\\delta\" -> \"δ\" (U+03B4)        -->\n<xsl:template match=\"m\" mode=\"plain-title-edit\">\n    <xsl:value-of select=\".\"/>\n</xsl:template>\n\n<!-- We do not wrap an \"c\" element as part of a plain title -->\n<xsl:template match=\"c\" mode=\"plain-title-edit\">\n    <xsl:value-of select=\".\"/>\n</xsl:template>\n\n<!-- We dumb-down quotation marks to \"straight\" ASCII. -->\n<!-- These behave well in output as attribute values,  -->\n<!-- the HTML serialization seems \"smart\" enough to    -->\n<!-- escape properly, even when both typesare present. -->\n\n<xsl:template match=\"q\" mode=\"plain-title-edit\">\n    <xsl:text>\"</xsl:text>\n    <xsl:apply-templates/>\n    <xsl:text>\"</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"sq\" mode=\"plain-title-edit\">\n    <xsl:text>'</xsl:text>\n    <xsl:apply-templates/>\n    <xsl:text>'</xsl:text>\n</xsl:template>\n\n<!-- Return processing to defaults for most elements of titles -->\n<xsl:template match=\"node()\" mode=\"plain-title-edit\">\n    <xsl:apply-templates select=\".\"/>\n</xsl:template>\n\n<!-- We let styling provide punctuation for titles, principally       -->\n<!-- a period at the end.  But this is awkward if there is already    -->\n<!-- punctuation there.  This template returns the string 'true' if,  -->\n<!-- and only if, such punctuation exists.  Else, it returns 'false'. -->\n<!-- Consolidating interior whitespace should have no effect.         -->\n<!-- Text generators (eg <today />) may fool this, but applying       -->\n<!-- templates first will introduce LaTeX macros that will fool this  -->\n<!-- To debug: add messages here, then call via this default template -->\n<!-- TODO: maybe warn about \"bad\" ending-punctuation, like a colon? -->\n<xsl:template match=\"title|subtitle\" mode=\"has-punctuation\">\n    <xsl:variable name=\"title-ending-punctuation\" select=\"'?!'\" />\n    <xsl:variable name=\"all-text\" select=\"normalize-space(string(.))\" />\n    <xsl:variable name=\"last-char\" select=\"substring($all-text, string-length($all-text))\" />\n    <!-- title should not be empty, but if so, the contains() alone is true -->\n    <xsl:value-of select=\"$last-char and contains($title-ending-punctuation, $last-char)\" />\n</xsl:template>\n\n<!-- Some titles should have periods supplied by PTX, mostly   -->\n<!-- \"smaller\" objects like \"example\" and not \"larger\" objects -->\n<!-- like \"chapter\".  We create a template to signal this, for -->\n<!-- consistency across conversions, and so that it can be     -->\n<!-- consciously overridden as part of styling work.  In       -->\n<!-- pieces simply so it is more readable.                     -->\n<!--                                                           -->\n<!-- Blocks -->\n<xsl:template match=\"&THEOREM-LIKE;|&PROOF-LIKE;|&AXIOM-LIKE;|&DEFINITION-LIKE;|&REMARK-LIKE;|&COMPUTATION-LIKE;|&EXAMPLE-LIKE;|&PROJECT-LIKE;|&ASIDE-LIKE;|exercise|assemblage\" mode=\"title-wants-punctuation\">\n    <xsl:value-of select=\"true()\"/>\n</xsl:template>\n<!-- Miscellaneous -->\n<xsl:template match=\"paragraphs|case|exercisegroup\" mode=\"title-wants-punctuation\">\n    <xsl:value-of select=\"true()\"/>\n</xsl:template>\n<!-- Titled: list items; tasks of exercise, PROJECT-LIKE, EXAMPLE-LIKE; glossary items -->\n<xsl:template match=\"ol/li|ul/li|task|gi\" mode=\"title-wants-punctuation\">\n    <xsl:value-of select=\"true()\"/>\n</xsl:template>\n<!-- Introductions and Conclusions -->\n<xsl:template match=\"article/introduction|chapter/introduction|section/introduction|subsection/introduction|appendix/introduction|exercises/introduction|solutions/introduction|worksheet/introduction|handout/introduction|reading-questions/introduction|article/conclusion|chapter/conclusion|section/conclusion|subsection/conclusion|appendix/conclusion|exercises/conclusion|solutions/conclusion|worksheet/conclusion|handout/conclusion|reading-questions/conclusion\" mode=\"title-wants-punctuation\">\n    <xsl:value-of select=\"true()\"/>\n</xsl:template>\n<xsl:template match=\"*\" mode=\"title-wants-punctuation\">\n    <xsl:value-of select=\"false()\"/>\n</xsl:template>\n\n<xsl:template match=\"&THEOREM-LIKE;|&AXIOM-LIKE;\" mode=\"creator-full\">\n    <!-- select=\"creator\" would just get it killed -->\n    <xsl:apply-templates select=\"creator/*|creator/text()\" />\n</xsl:template>\n\n<!-- Structured titles -->\n\n<!-- Each \"line\", except the last, gets a separator     -->\n<!-- Almost always a space, but for LaTeX, at birth,    -->\n<!-- a newline.  We make it obvious that this character -->\n<!-- has not been overridden in a conversion            -->\n\n<xsl:variable name=\"title-separator\" select=\"'[TITLESEP]'\"/>\n\n<!-- Books:    overall title and subtitle, titles of parts, chapters and sections -->\n<!-- Articles: overall title and subtitle, titles of sections                     -->\n<xsl:template match=\"book/title/line|book/subtitle/line|book/part/title/line|book/part/chapter/title/line|book/chapter/title/line|book/part/chapter/section/title/line|book/chapter/section/title/line|article/title/line|article/subtitle/line|article/section/title/line\">\n    <xsl:param name=\"separator\"/>\n\n    <xsl:apply-templates/>\n    <xsl:if test=\"following-sibling::line\">\n        <xsl:value-of select=\"$separator\"/>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- ######## -->\n<!-- Captions -->\n<!-- ######## -->\n\n<!-- Captions are similar to titles.  They should be -->\n<!-- killed as metadata and requested when needed.   -->\n\n<xsl:template match=\"caption\"/>\n\n<!-- A caption can have a footnote, thus HTML will create    -->\n<!-- a knowl, and we need to distinguish between original    -->\n<!-- and duplicate scenarios.  For other conversions, the    -->\n<!-- \"b-original\" parameter should just be silently ignored. -->\n<xsl:template match=\"figure|listing\" mode=\"caption-full\">\n    <xsl:param name=\"b-original\" select=\"true()\"/>\n\n    <xsl:if test=\"caption\">\n        <xsl:apply-templates select=\"caption/node()\">\n            <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n        </xsl:apply-templates>\n    </xsl:if>\n</xsl:template>\n\n<!-- #################################### -->\n<!-- Widths of Images, Audio, Videos, Etc -->\n<!-- #################################### -->\n\n<!-- Because we allow width settings as consequences of sidebyside     -->\n<!-- layout parameters, we need to \"reach up\" and get these widths     -->\n<!-- on occassion.  So we consider the PreTeXt markup/situation and    -->\n<!-- produce a percentage as a string.  Consumers need to convert to   -->\n<!-- a percentage, pixels, fractional linewidths - whatever is needed. -->\n\n<!-- An image appears -->\n<!--                                                                      -->\n<!--   1.  in a figure (itself not in a sidebyside) where it              -->\n<!--       can have a width specification on itself                       -->\n<!--   2.  in a sidebyside directly, or a figure in a sidebyside.         -->\n<!--       These widths come from the layout, and are converter dependent -->\n<!--                                                                      -->\n<!-- Entirely similar for jsxgraph, audio and video but we do             -->\n<!-- not consult default *image* width in docinfo                         -->\n\n<xsl:template match=\"image[not(ancestor::sidebyside)]|audio[not(ancestor::sidebyside)]|video[not(ancestor::sidebyside)]|jsxgraph[not(ancestor::sidebyside)]|interactive[not(ancestor::sidebyside)]|slate[not(ancestor::sidebyside)]\" mode=\"get-width-percentage\">\n    <!-- find it first -->\n    <xsl:variable name=\"raw-width\">\n        <xsl:choose>\n            <!-- right on the element! -->\n            <xsl:when test=\"@width\">\n                <xsl:value-of select=\"@width\" />\n            </xsl:when>\n            <!-- not on an image, but doc-wide default exists -->\n            <xsl:when test=\"self::image and $docinfo/defaults/images/@width\">\n                <xsl:value-of select=\"$docinfo/defaults/images/@width\" />\n            </xsl:when>\n            <!-- naked slate, look to enclosing interactive -->\n            <xsl:when test=\"self::slate\">\n                <xsl:apply-templates select=\"parent::interactive\" mode=\"get-width-percentage\" />\n            </xsl:when>\n            <!-- what to do? Author will figure it out if too extreme -->\n            <xsl:otherwise>\n                <xsl:text>100%</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- now sanitize it -->\n    <xsl:variable name=\"normalized-width\" select=\"normalize-space($raw-width)\" />\n    <xsl:choose>\n        <xsl:when test=\"not(substring($normalized-width, string-length($normalized-width)) = '%')\">\n            <xsl:message>PTX:FALLBACK:   a \"width\" attribute should be given as a percentage (such as \"40%\", not as \"<xsl:value-of select=\"$normalized-width\" />, using 100% instead\"</xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\" />\n            <!-- replace by 100% -->\n            <xsl:text>100%</xsl:text>\n        </xsl:when>\n        <!-- test for stray interior spaces here? -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$normalized-width\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Any way that an image gets placed in a sidebyside -->\n<!-- panel it should have a relative size filling that -->\n<!-- panel, so this is easy, just 100% all the time    -->\n<!-- Exception: asymptote WebGL needs actual pixels    -->\n<xsl:template match=\"image[ancestor::sidebyside]\" mode=\"get-width-percentage\">\n    <xsl:text>100%</xsl:text>\n</xsl:template>\n\n<!-- The exception is an image inside a sidebyside in a webwork  -->\n<!-- where the parent sidebyside should only have a single percentage in its @widths -->\n<!-- N.B. This should be reworked/removed when there is a one-item sbs equivalent -->\n<xsl:template match=\"webwork//image[parent::sidebyside/@widths]\" mode=\"get-width-percentage\">\n    <xsl:value-of select=\"parent::sidebyside/@widths\" />\n</xsl:template>\n\n<!-- We need to get the right entry from the sidebyside layout.         -->\n<!-- This is complicated slightly by two possibilities for the element  -->\n<!-- of the sidebyside, a naked object, or a figure holding the object  -->\n<!-- Widths from sidebyside layouts have been error-checked as input    -->\n\n<!-- occurs in a figure, not contained in a sidebyside -->\n<xsl:template match=\"audio[ancestor::sidebyside]|video[ancestor::sidebyside]|jsxgraph[ancestor::sidebyside]|interactive[ancestor::sidebyside]|slate[ancestor::sidebyside]|image[asymptote and ancestor::sidebyside]|image[sageplot and ancestor::sidebyside]\" mode=\"get-width-percentage\">\n    <!-- in a side-by-side, get layout, locate in layout -->\n    <!-- and get width.  The layout-parameters template  -->\n    <!-- will analyze an enclosing sbsgroup              -->\n    <xsl:variable name=\"enclosing-sbs\" select=\"ancestor::sidebyside\" />\n    <xsl:variable name=\"rtf-layout\">\n        <xsl:apply-templates select=\"$enclosing-sbs\" mode=\"layout-parameters\" />\n    </xsl:variable>\n    <xsl:variable name=\"layout\" select=\"exsl:node-set($rtf-layout)\" />\n    <xsl:choose>\n        <xsl:when test=\"parent::figure or parent::stack\">\n            <xsl:variable name=\"panel-number\" select=\"count(parent::*/preceding-sibling::*) + 1\" />\n            <xsl:value-of select=\"$layout/width[$panel-number]\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:variable name=\"panel-number\" select=\"count(preceding-sibling::*) + 1\" />\n            <xsl:value-of select=\"$layout/width[$panel-number]\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Assumes element may have an @aspect attribute   -->\n<!-- Caller can provide a default for its context    -->\n<!-- Input:  \"width:height\", or decimal width/height -->\n<!-- Return: real number as fraction width/height    -->\n<!-- Totally blank means nothing could be determined -->\n<xsl:template match=\"slate|interactive|jsxgraph|audio|video|image[asymptote]|image[sageplot]\" mode=\"get-aspect-ratio\">\n    <xsl:param name=\"default-aspect\" select=\"''\" />\n\n    <!-- look to element first, then to supplied default          -->\n    <!-- this could be empty (default default), then return empty -->\n    <xsl:variable name=\"the-aspect\">\n        <xsl:choose>\n            <!-- The aspect ratio is a property of an       -->\n            <!-- interactive Asymptote WebGL version, only. -->\n            <xsl:when test=\"self::image and asymptote/@aspect\">\n                <xsl:value-of select=\"asymptote/@aspect\" />\n            </xsl:when>\n            <xsl:when test=\"self::image and sageplot/@aspect\">\n                <xsl:value-of select=\"sageplot/@aspect\" />\n            </xsl:when>\n            <xsl:when test=\"not(self::image) and @aspect\">\n                <xsl:value-of select=\"@aspect\" />\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$default-aspect\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:choose>\n        <!-- nothing provided by element or caller -->\n        <xsl:when test=\"$the-aspect = ''\" />\n        <!-- test if a ratio is given, and assume parts are good -->\n        <xsl:when test=\"contains($the-aspect, ':')\">\n            <xsl:variable name=\"width\" select=\"substring-before($the-aspect, ':')\" />\n            <xsl:variable name=\"height\" select=\"substring-after($the-aspect, ':')\" />\n            <xsl:value-of select=\"$width div $height\" />\n        </xsl:when>\n        <!-- assume a number and see if it is bad, return nothing -->\n        <!-- NaN does not equal *anything*, so tests if a number  -->\n        <!-- http://stackoverflow.com/questions/6895870           -->\n        <xsl:when test=\"not(number($the-aspect) = number($the-aspect)) or ($the-aspect &lt; 0)\">\n            <xsl:message>PTX:ERROR:   the @aspect attribute should be a ratio, like 4:3, or a positive number, not \"<xsl:value-of select=\"$the-aspect\" />\"</xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\" />\n        </xsl:when>\n        <!-- survives as a number -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$the-aspect\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Various components need to be built with pixel widths from % based widths -->\n<!-- design-width is the 100% value.                                           -->\n<!-- Individual stylesheets (e.g. html, reveal) may change this                -->\n<xsl:variable name=\"design-width\" select=\"'600'\" />\n\n<!-- Some elements may allow for a custom design-width.                        -->\n<!-- They will override this template and either provide a different value or  -->\n<!-- fall back on the local variable                                           -->\n<xsl:template match=\"*\" mode=\"get-design-width\">\n    <xsl:value-of select=\"$design-width\" />\n</xsl:template>\n\n<!-- Pixels are an HTML thing, but we may need these numbers -->\n<!-- elsewhere, and these are are pure text templates        -->\n<!-- NB 3D \"sageplot\" needs an \"iframe\" with pixels for size -->\n<xsl:template match=\"slate|audio|video|interactive|image[asymptote]|image[sageplot]\" mode=\"get-width-pixels\">\n    <xsl:variable name=\"local-design-width\">\n        <xsl:apply-templates select=\".\" mode=\"get-design-width\" />\n    </xsl:variable>\n    <xsl:variable name=\"width-percent\">\n        <xsl:apply-templates select=\".\" mode=\"get-width-percentage\" />\n    </xsl:variable>\n    <xsl:variable name=\"width-fraction\">\n        <xsl:value-of select=\"substring-before($width-percent,'%') div 100\" />\n    </xsl:variable>\n    <xsl:value-of select=\"round($local-design-width * $width-fraction)\" />\n</xsl:template>\n\n<!-- Square by default, when asked.  Can override -->\n<xsl:template match=\"slate|audio|video|interactive|image[asymptote]|image[sageplot]\" mode=\"get-height-pixels\">\n    <xsl:param name=\"default-aspect\" select=\"'1:1'\" />\n    <xsl:variable name=\"local-design-width\">\n        <xsl:apply-templates select=\".\" mode=\"get-design-width\" />\n    </xsl:variable>\n    <xsl:variable name=\"width-percent\">\n        <xsl:apply-templates select=\".\" mode=\"get-width-percentage\" />\n    </xsl:variable>\n    <xsl:variable name=\"width-fraction\">\n        <xsl:value-of select=\"substring-before($width-percent,'%') div 100\" />\n    </xsl:variable>\n    <xsl:variable name=\"aspect-ratio\">\n        <xsl:apply-templates select=\".\" mode=\"get-aspect-ratio\">\n            <xsl:with-param name=\"default-aspect\" select=\"$default-aspect\" />\n        </xsl:apply-templates>\n    </xsl:variable>\n    <xsl:value-of select=\"round($local-design-width * $width-fraction div $aspect-ratio)\" />\n</xsl:template>\n\n\n<!-- ################ -->\n<!-- Names of Objects -->\n<!-- ################ -->\n\n<!-- The  xsl/localizations/localizations.xml  file contains the base -->\n<!-- filenames for the individual (per-language) files.  We form a    -->\n<!-- node-set of these filenames in the  $locale-files  variable.     -->\n<!-- Then the  document()  function will read multiple files and      -->\n<!-- form one grand node-set with all of the translations for         -->\n<!-- all languages.  The  xi:include  device is possible within the   -->\n<!-- localizations  directory, but would require activating that      -->\n<!-- feature (e.g.  xsltproc -xinclude) for even the simplest         -->\n<!-- (non-modular) documents.  Better to accomplish the consolidation -->\n<!-- with standard XSLT.                                              -->\n<!-- NB: the $localizations variable has multiple root nodes, so when -->\n<!-- used in a context-switch before looking up a key, the \"for-each\" -->\n<!-- is actually looping over multiple root nodes.  So when we switch -->\n<!-- context with a \"for-each\" we restrict to the root node for the   -->\n<!-- specific language in play.                                       -->\n<xsl:variable name=\"locale-files\" select=\"document('localizations/localizations.xml')/localizations/filename\" />\n<xsl:variable name=\"localizations\" select=\"document($locale-files)\" />\n<!-- Key to lookup a particular localization -->\n<xsl:key name=\"localization-key\" match=\"localization\" use=\"@string-id\"/>\n\n<!-- Ultimately translations are all contained in the files of  -->\n<!-- the xsl/localizations directory, which provides            -->\n<!-- upper-case, singular versions.  In this way, we only ever  -->\n<!-- hardcode a string (like \"Chapter\") once                    -->\n<!-- Template is intentionally modal.                           -->\n<xsl:template match=\"*\" mode=\"type-name\">\n    <xsl:param name=\"string-id\" select=\"''\"/>\n    <!-- The $string-id parameter allows for an override on        -->\n    <!-- semi-automatic determination of the object being named    -->\n    <!-- (see the modal \"string-id\" templates).  This is necessary -->\n    <!-- for items like the names of interface buttons that are    -->\n    <!-- not associated closely with a certain PreTeXt element.    -->\n    <xsl:variable name=\"str-id\">\n        <xsl:choose>\n            <xsl:when test=\"not($string-id = '')\">\n                <xsl:value-of select=\"$string-id\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:apply-templates select=\".\" mode=\"string-id\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n\n    <!-- The language \"in force\", or \"ambient language\" is found      -->\n    <!-- by looking up the document tree for the closest containing   -->\n    <!-- specification of the language.                               -->\n    <!--                                                              -->\n    <!-- Tip: To get the \"document-language\" as the in-force          -->\n    <!-- language, *only* for the case of setting a string-id         -->\n    <!-- override, set the context to $root in the employing @select, -->\n    <!-- then $lang-element *will* be $root and $lang *will* be the   -->\n    <!-- overall, document-wide, language (set by -assembly).         -->\n    <xsl:variable name=\"lang\">\n        <xsl:apply-templates select=\".\" mode=\"ambient-language\"/>\n    </xsl:variable>\n\n    <!-- Now, build the actual translation via a lookup -->\n    <xsl:variable name=\"lookup\">\n        <xsl:choose>\n            <!-- First, look in docinfo for document-specific rename with correct language -->\n            <xsl:when test=\"$docinfo/rename[@element=$str-id and @xml:lang=$lang]\">\n                <xsl:apply-templates select=\"$docinfo/rename[@element=$str-id and @xml:lang=$lang]\"/>\n            </xsl:when>\n            <!-- Second, look in docinfo for document-specific rename, but       -->\n            <!-- now explicitly language-agnostic; \"@lang\" became \"@xml:lang\".   -->\n            <xsl:when test=\"$docinfo/rename[@element=$str-id and not(@xml:lang)]\">\n                <xsl:apply-templates select=\"$docinfo/rename[@element=$str-id and not(@xml:lang)]\"/>\n            </xsl:when>\n            <!-- Finally, default to a lookup from the localization file's nodes -->\n            <!-- Use a \"for-each\" to effect a context switch for the look-up and -->\n            <!-- restrict the context to the language in play.                   -->\n            <xsl:otherwise>\n                <xsl:for-each select=\"$localizations/locale[@language = $lang]\">\n                    <xsl:value-of select=\"key('localization-key', $str-id)\"/>\n                </xsl:for-each>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- Exceptions to failed lookups                     -->\n    <!-- Some un-implemented translations are ubiquitous, -->\n    <!-- so we recognize failure and fallback to English  -->\n    <xsl:variable name=\"translation\">\n        <xsl:choose>\n            <!-- $lookup is good, echo it -->\n            <xsl:when test=\"not($lookup = '')\">\n                <xsl:value-of select=\"$lookup\"/>\n            </xsl:when>\n            <!-- substitute English since $lookup is empty     -->\n            <!-- NB: could test with an \"or\" for multiple      -->\n            <!-- exceptions and then get en-US version with a  -->\n            <!-- proper lookup as a single statement, but not  -->\n            <!-- bothering yet.                                -->\n            <!-- \"Close\" is on every knowl, too many warnings  -->\n            <xsl:when test=\"$str-id = 'close'\">\n                <xsl:text>Close</xsl:text>\n            </xsl:when>\n            <!-- \"Reveal\" is on every knowl, too many warnings -->\n            <xsl:when test=\"$str-id = 'reveal'\">\n                <xsl:text>Reveal</xsl:text>\n            </xsl:when>\n            <!-- $lookup empty and not exceptional    -->\n            <!-- echo the empty lookup as translation -->\n            <xsl:otherwise/>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$translation != ''\">\n            <xsl:value-of select=\"$translation\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>[</xsl:text>\n            <xsl:value-of select=\"$str-id\" />\n            <xsl:text>]</xsl:text>\n            <xsl:message>PTX:WARNING: could not translate string with id \"<xsl:value-of select=\"$str-id\"/>\" into language for code \"<xsl:value-of select=\"$lang\"/>\"</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- In the assembly pass, we sometimes need to postpone localization, -->\n<!-- since we have not analyzed languages and we maybe don't have the  -->\n<!-- $docinfo element needed for renaming.  So we emit a placeholder,  -->\n<!-- in a \"pi:localize\" element with the \"string-id\" as an attribute.  -->\n<!-- Now, as part of a conversion, the substitution can be made.       -->\n<xsl:template match=\"pi:localize\">\n    <xsl:apply-templates select=\".\" mode=\"type-name\">\n        <xsl:with-param name=\"string-id\" select=\"@string-id\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- A bare appendix letter beside a title is ambiguous (\"A Trip    -->\n<!-- Abroad\"), so wherever the letter and title compose on one line -->\n<!-- a period follows the letter: \"A. Trip Abroad\".  A \"solutions\"  -->\n<!-- division in the back matter shares the letter sequence (see    -->\n<!-- \"division-serial-number\" in the assembly), so it is treated    -->\n<!-- identically.  Only the top-level letter: subdivision numbers   -->\n<!-- (\"A.2\") are already unambiguous.  Styling refinements are      -->\n<!-- anticipated.                                                   -->\n<xsl:template match=\"*\" mode=\"division-number-separator\"/>\n<xsl:template match=\"appendix|backmatter/solutions\" mode=\"division-number-separator\">\n    <xsl:text>.</xsl:text>\n</xsl:template>\n\n<!-- Most PreTeXt elements have names, and their localizations, indexed   -->\n<!-- by a \"string-id\" that is simply their local name.  However, others   -->\n<!-- (\"exercise\" is archetypical) have names that vary according to their -->\n<!-- context.  The following templates just report these \"string-id\",     -->\n<!-- defaulting to the \"local name\".  See the \"en-US\" localization file   -->\n<!-- for the best documentation of these non-standard string-id.          -->\n\n<!-- A single objective or outcome is authored as a list item -->\n<xsl:template match=\"objectives/ol/li|objectives/ul/li|objectives/dl/li\" mode=\"string-id\">\n    <xsl:text>objective</xsl:text>\n</xsl:template>\n<xsl:template match=\"outcomes/ol/li|outcomes/ul/li|outcomes/dl/li\" mode=\"string-id\">\n    <xsl:text>outcome</xsl:text>\n</xsl:template>\n\n<!-- There are lots of exercises, but differentiated by their parents,  -->\n<!-- so we use identifiers that remind us of their location in the tree -->\n\n<!-- First, a \"divisional\" \"exercise\" in an \"exercises\",      -->\n<!-- with perhaps intervening groups, like an \"exercisegroup\" -->\n<xsl:template match=\"exercises//exercise\" mode=\"string-id\">\n    <xsl:text>divisionalexercise</xsl:text>\n</xsl:template>\n\n<!-- Second, an \"exercise\" placed within a \"worksheet\"-->\n<xsl:template match=\"worksheet//exercise\" mode=\"string-id\">\n    <xsl:text>worksheetexercise</xsl:text>\n</xsl:template>\n\n<!-- Third, an \"exercise\" placed within a \"reading-questions\"-->\n<xsl:template match=\"reading-questions//exercise\" mode=\"string-id\">\n    <xsl:text>readingquestion</xsl:text>\n</xsl:template>\n\n<!-- Finally, an inline exercise has a division (several possible)        -->\n<!-- as a parent. We just drop in here last if other matches do not       -->\n<!-- succeed, but could improve with a filter or list of specific matches -->\n<!-- This matches the LaTeX environment of the same name, so              -->\n<!-- template to create an \"inlineexercise\" environment runs smoothly     -->\n<xsl:template match=\"exercise\" mode=\"string-id\">\n    <xsl:text>inlineexercise</xsl:text>\n</xsl:template>\n\n<!-- \"solutions\" divisions are \"Solutions 5.6\" in the  -->\n<!-- main matter, but \"Appendix D\" in the back matter -->\n<xsl:template match=\"solutions\" mode=\"string-id\">\n    <xsl:choose>\n        <xsl:when test=\"parent::backmatter\">\n            <xsl:text>appendix</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>solutions</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Display Mathematics can be a single line or multiple      -->\n<!-- lines and the two do not always align with element names, -->\n<!-- so we use two strings to signal the two situations.       -->\n\n<xsl:template match=\"mrow|md[@pi:authored-one-line]\" mode=\"string-id\">\n    <xsl:text>equation</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"md[not(@pi:authored-one-line)]\" mode=\"string-id\">\n    <xsl:text>displaymath</xsl:text>\n</xsl:template>\n\n<!-- And with no better match, the default is  -->\n<!-- the PreTeXt name for the element itself. -->\n<xsl:template match=\"*\" mode=\"string-id\">\n    <xsl:value-of select=\"local-name(.)\"/>\n</xsl:template>\n\n<!-- ################### -->\n<!-- Language Properties -->\n<!-- ################### -->\n\n<!-- At any given point in processing, we may want   -->\n<!-- to know which language is in effect. We look    -->\n<!-- up the tree for the \"closest\" indication of a   -->\n<!-- language for localization. The  @pi:locale-lang -->\n<!-- attribute is set by the -assembly  stylesheet,  -->\n<!-- and guarantees the language is supported by an  -->\n<!-- extant localization file. Result is a           -->\n<!-- language code we can use.  At worst, we get the -->\n<!-- $document-language from the \"pretext\" element.  -->\n<!-- Typical use would save the result in a          -->\n<!-- variable, say $lang, and then locate a \"locale\" -->\n<!-- via XPath that leads with an expression like    -->\n<!--                                                 -->\n<!--    $localizations/locale[@language = $lang]     -->\n\n<xsl:template match=\"*\" mode=\"ambient-language\">\n    <xsl:value-of select=\"ancestor-or-self::*[@pi:locale-lang][1]/@pi:locale-lang\"/>\n</xsl:template>\n\n<!-- Language direction -->\n\n<!-- Every localiztion should specify the direction of the  -->\n<!-- language, which we record as a variable and as a flag. -->\n<xsl:variable name=\"document-language-direction\">\n    <xsl:value-of select=\"$localizations/locale[@language = $document-language]/@direction\"/>\n</xsl:variable>\n\n<!-- We consider right-to-left as exceptional, so we set a flag   -->\n<!-- for this case.  This should be the primary determinant in    -->\n<!-- code such as the LaTeX coionversion, though the actual value -->\n<!-- of \"$language-direction\" is meant to be used in attributes   -->\n<!-- for HTML pages.                                              -->\n<xsl:variable name=\"b-rtl\" select=\"$document-language-direction = 'rtl'\"/>\n\n<!-- Quotation Marks -->\n\n<!-- Utility templates to query localization specification -->\n\n<xsl:template match=\"*\" mode=\"get-quote-primary\">\n    <xsl:variable name=\"lang\">\n        <xsl:apply-templates select=\".\" mode=\"ambient-language\"/>\n    </xsl:variable>\n    <xsl:value-of select=\"$localizations/locale[@language = $lang]/@quote-primary\"/>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"get-quote-secondary\">\n    <xsl:variable name=\"lang\">\n        <xsl:apply-templates select=\".\" mode=\"ambient-language\"/>\n    </xsl:variable>\n    <xsl:value-of select=\"$localizations/locale[@language = $lang]/@quote-secondary\"/>\n</xsl:template>\n\n<!-- Lookup table: one row per (style, side) with Unicode and LaTeX -->\n<!-- representations.  Output-format templates look up a row by     -->\n<!-- combining @style and @side with a \"|\" separator, then read     -->\n<!-- @unicode-character attribute or the latex-character child.     -->\n<!-- Add a new child element to support additional output formats.  -->\n\n<xsl:variable name=\"quote-character-rtf\">\n    <!-- U+201C: LEFT DOUBLE QUOTATION MARK  -->\n    <!-- U+201D: RIGHT DOUBLE QUOTATION MARK -->\n    <quote-character style=\"english-double\" side=\"left\"  unicode-character=\"&#x201c;\">\n        <latex-character>\\textquotedblleft{}</latex-character>\n    </quote-character>\n    <quote-character style=\"english-double\" side=\"right\" unicode-character=\"&#x201d;\">\n        <latex-character>\\textquotedblright{}</latex-character>\n    </quote-character>\n    <!-- U+2018: LEFT SINGLE QUOTATION MARK  -->\n    <!-- U+2019: RIGHT SINGLE QUOTATION MARK -->\n    <quote-character style=\"english-single\" side=\"left\"  unicode-character=\"&#x2018;\">\n        <latex-character>\\textquoteleft{}</latex-character>\n    </quote-character>\n    <quote-character style=\"english-single\" side=\"right\" unicode-character=\"&#x2019;\">\n        <latex-character>\\textquoteright{}</latex-character>\n    </quote-character>\n    <!-- U+00AB: LEFT-POINTING DOUBLE ANGLE QUOTATION MARK  -->\n    <!-- U+00BB: RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK -->\n    <quote-character style=\"angle-double\" side=\"left\"  unicode-character=\"&#x00ab;\">\n        <latex-character>\\guillemotleft{}</latex-character>\n    </quote-character>\n    <quote-character style=\"angle-double\" side=\"right\" unicode-character=\"&#x00bb;\">\n        <latex-character>\\guillemotright{}</latex-character>\n    </quote-character>\n    <!-- U+2039: SINGLE LEFT-POINTING ANGLE QUOTATION MARK  -->\n    <!-- U+203A: SINGLE RIGHT-POINTING ANGLE QUOTATION MARK -->\n    <quote-character style=\"angle-single\" side=\"left\"  unicode-character=\"&#x2039;\">\n        <latex-character>\\guilsinglleft{}</latex-character>\n    </quote-character>\n    <quote-character style=\"angle-single\" side=\"right\" unicode-character=\"&#x203a;\">\n        <latex-character>\\guilsinglright{}</latex-character>\n    </quote-character>\n    <!-- U+202F: NARROW NO-BREAK SPACE -->\n    <quote-character style=\"angle-double-space\" side=\"left\"  unicode-character=\"&#x00ab;&#x202f;\">\n        <latex-character>\\guillemotleft\\thinspace{}</latex-character>\n    </quote-character>\n    <quote-character style=\"angle-double-space\" side=\"right\" unicode-character=\"&#x202f;&#x00bb;\">\n        <latex-character>\\thinspace\\guillemotright{}</latex-character>\n    </quote-character>\n    <quote-character style=\"angle-single-space\" side=\"left\"  unicode-character=\"&#x2039;&#x202f;\">\n        <latex-character>\\guilsinglleft\\thinspace{}</latex-character>\n    </quote-character>\n    <quote-character style=\"angle-single-space\" side=\"right\" unicode-character=\"&#x202f;&#x203a;\">\n        <latex-character>\\thinspace\\guilsinglright{}</latex-character>\n    </quote-character>\n    <!-- U+201E: DOUBLE LOW-9 QUOTATION MARK -->\n    <quote-character style=\"down-up-double\" side=\"left\"  unicode-character=\"&#x201e;\">\n        <latex-character>\\quotedblbase{}</latex-character>\n    </quote-character>\n    <quote-character style=\"down-up-double\" side=\"right\" unicode-character=\"&#x201d;\">\n        <latex-character>\\textquotedblright{}</latex-character>\n    </quote-character>\n    <!-- U+201A: SINGLE LOW-9 QUOTATION MARK -->\n    <quote-character style=\"down-up-single\" side=\"left\"  unicode-character=\"&#x201a;\">\n        <latex-character>\\quotesinglbase{}</latex-character>\n    </quote-character>\n    <quote-character style=\"down-up-single\" side=\"right\" unicode-character=\"&#x2019;\">\n        <latex-character>\\textquoteright{}</latex-character>\n    </quote-character>\n</xsl:variable>\n\n<xsl:variable name=\"quote-character-table\"\n    select=\"exsl:node-set($quote-character-rtf)\"/>\n\n<xsl:key name=\"quote-character-key\" match=\"quote-character\"\n    use=\"concat(@style, '|', @side)\"/>\n\n<!-- Given a quotation \"style\" and a \"side\", return the Unicode -->\n<!-- character from the table above.  Output formats that quote  -->\n<!-- with literal characters (HTML, XSL-FO) route their          -->\n<!-- \"*-character\" templates through here.                       -->\n<xsl:template match=\"*\" mode=\"quote-character-unicode\">\n    <xsl:param name=\"style\"/>\n    <xsl:param name=\"side\"/>\n    <xsl:variable name=\"unicode-character\">\n        <xsl:for-each select=\"$quote-character-table\">\n            <xsl:value-of select=\"key('quote-character-key',\n                concat($style, '|', $side))/@unicode-character\"/>\n        </xsl:for-each>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$unicode-character != ''\">\n            <xsl:value-of select=\"$unicode-character\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message>\n                <xsl:text>PTX:BUG:  the quotation style \"</xsl:text>\n                <xsl:value-of select=\"$style\"/>\n                <xsl:text>\" (</xsl:text>\n                <xsl:value-of select=\"$side\"/>\n                <xsl:text>) was not recognized</xsl:text>\n            </xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- ##### -->\n<!-- Icons -->\n<!-- ##### -->\n\n<!-- Information about icons -->\n<!--     @name: PreTeXt name, what authors know/use              -->\n<!--     @font-awesome-family: Font Awesome family,              -->\n<!--                           \"classic\" or \"brands\"             -->\n<!--     @font-awesome: the font-awesome name, which becomes     -->\n<!--                    CamelCase for use with the LaTeX package -->\n<!--     @unicode: for use in less-capable formats               -->\n<!--                                                             -->\n<xsl:variable name=\"icon-rtf\">\n    <!-- see Unicode Character 'LEFTWARDS HEAVY ARROW' (U+1F844) -->\n    <!-- for bulkier arrows (in \"Supplemental Arrows-C Block\")   -->\n    <iconinfo name=\"arrow-left\"\n              font-awesome-family=\"classic\"\n              font-awesome=\"arrow-left\"\n              fa-codepoint=\"&#xF060;\"\n              unicode=\"&#x2190;\"/> <!-- LEFTWARDS ARROW -->\n    <iconinfo name=\"arrow-up\"\n              font-awesome-family=\"classic\"\n              font-awesome=\"arrow-up\"\n              fa-codepoint=\"&#xF062;\"\n              unicode=\"&#x2191;\"/> <!-- UPWARDS ARROW -->\n    <iconinfo name=\"arrow-right\"\n              font-awesome-family=\"classic\"\n              font-awesome=\"arrow-right\"\n              fa-codepoint=\"&#xF061;\"\n              unicode=\"&#x2192;\"/> <!-- RIGHTWARDS ARROW -->\n    <iconinfo name=\"arrow-down\"\n              font-awesome-family=\"classic\"\n              font-awesome=\"arrow-down\"\n              fa-codepoint=\"&#xF063;\"\n              unicode=\"&#x2193;\"/> <!-- DOWNWARDS ARROW -->\n    <iconinfo name=\"file-save\"\n              font-awesome-family=\"classic\"\n              font-awesome=\"save\"\n              fa-codepoint=\"&#xF0C7;\"\n              unicode=\"&#x1f4be;\"/> <!-- FLOPPY DISK -->\n    <iconinfo name=\"gear\"\n              font-awesome-family=\"classic\"\n              font-awesome=\"cog\"\n              fa-codepoint=\"&#xF013;\"\n              unicode=\"&#x2699;\" /> <!-- GEAR -->\n    <iconinfo name=\"menu\"\n              font-awesome-family=\"classic\"\n              font-awesome=\"bars\"\n              fa-codepoint=\"&#xF0C9;\"\n              unicode=\"&#x2630;\" /> <!-- TRIGRAM FOR HEAVEN -->\n    <iconinfo name=\"wrench\"\n              font-awesome-family=\"classic\"\n              font-awesome=\"wrench\"\n              fa-codepoint=\"&#xF0AD;\"\n              unicode=\"&#x1f527;\"/> <!-- WRENCH -->\n    <iconinfo name=\"power\"\n              font-awesome-family=\"classic\"\n              font-awesome=\"power-off\"\n              fa-codepoint=\"&#xF011;\"\n              unicode=\"&#x23FB;\"/> <!-- POWER SYMBOL -->\n    <iconinfo name=\"media-play\"\n              font-awesome-family=\"classic\"\n              font-awesome=\"play\"\n              fa-codepoint=\"&#xF04B;\"\n              unicode=\"&#x25B6;\"/> <!--BLACK RIGHT-POINTING TRIANGLE-->\n    <iconinfo name=\"media-pause\"\n              font-awesome-family=\"classic\"\n              font-awesome=\"pause\"\n              fa-codepoint=\"&#xF04C;\"\n              unicode=\"&#x23F8;\"/> <!-- DOUBLE VERTICAL BAR -->\n    <iconinfo name=\"media-stop\"\n              font-awesome-family=\"classic\"\n              font-awesome=\"stop\"\n              fa-codepoint=\"&#xF04D;\"\n              unicode=\"&#x23F9;\"/> <!-- BLACK SQUARE FOR STOP-->\n    <iconinfo name=\"media-fast-forward\"\n              font-awesome-family=\"classic\"\n              font-awesome=\"forward\"\n              fa-codepoint=\"&#xF04E;\"\n              unicode=\"&#x23E9;\"/> <!-- BLACK RIGHT-POINTING DOUBLE TRIANGLE -->\n    <iconinfo name=\"media-rewind\"\n              font-awesome-family=\"classic\"\n              font-awesome=\"backward\"\n              fa-codepoint=\"&#xF04A;\"\n              unicode=\"&#x23EA;\"/> <!-- BLACK LEFT-POINTING DOUBLE TRIANGLE -->\n    <iconinfo name=\"media-skip-to-end\"\n              font-awesome-family=\"classic\"\n              font-awesome=\"fast-forward\"\n              fa-codepoint=\"&#xF050;\"\n              unicode=\"&#x23ED;\"/> <!-- BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR -->\n    <iconinfo name=\"media-skip-to-start\"\n              font-awesome-family=\"classic\"\n              font-awesome=\"fast-backward\"\n              fa-codepoint=\"&#xF049;\"\n              unicode=\"&#x23EE;\"/> <!-- BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR -->\n    <!-- Creative Commons, Font Awesome Brands family -->\n    <!-- https://creativecommons.org/2020/03/18/the-unicode-standard-now-includes-cc-license-symbols/ -->\n    <iconinfo name=\"cc\"\n              font-awesome-family=\"brands\"\n              font-awesome=\"creative-commons\"\n              fa-codepoint=\"&#xF25E;\"\n              unicode=\"&#x1F16D;\"/> <!-- CIRCLED CC -->\n    <iconinfo name=\"cc-by\"\n              font-awesome-family=\"brands\"\n              font-awesome=\"creative-commons-by\"\n              fa-codepoint=\"&#xF4E7;\"\n              unicode=\"&#x1F16F;\"/> <!-- CIRCLED HUMAN FIGURE -->\n    <iconinfo name=\"cc-sa\"\n              font-awesome-family=\"brands\"\n              font-awesome=\"creative-commons-sa\"\n              fa-codepoint=\"&#xF4EF;\"\n              unicode=\"&#x1F10E;\"/> <!-- CIRCLED ANTICLOCKWISE ARROW -->\n    <iconinfo name=\"cc-nc\"\n              font-awesome-family=\"brands\"\n              font-awesome=\"creative-commons-nc\"\n              fa-codepoint=\"&#xF4E8;\"\n              unicode=\"&#x1F10F;\"/> <!-- CIRCLED DOLLAR SIGN WITH OVERLAID BACKSLASH -->\n    <iconinfo name=\"cc-pd\"\n              font-awesome-family=\"brands\"\n              font-awesome=\"creative-commons-pd\"\n              fa-codepoint=\"&#xF4EC;\"\n              unicode=\"&#x1F16E;\"/> <!-- CIRCLED C WITH OVERLAID BACKSLASH -->\n    <iconinfo name=\"cc-zero\"\n              font-awesome-family=\"brands\"\n              font-awesome=\"creative-commons-zero\"\n              fa-codepoint=\"&#xF4F3;\"\n              unicode=\"&#x1F16D;\"/> <!-- CIRCLED ZERO WITH BACKSLASH -->\n</xsl:variable>\n\n<!-- If read from a file via \"document()\" then   -->\n<!-- the exsl:node-set() call would seem to be   -->\n<!-- unnecessary.  When list above gets too big, -->\n<!-- migrate to a new file after consulting      -->\n<!-- localization scheme                         -->\n<xsl:variable name=\"icon-table\" select=\"exsl:node-set($icon-rtf)\"/>\n\n<xsl:key name=\"icon-key\" match=\"iconinfo\" use=\"@name\"/>\n\n<!-- ##### -->\n<!-- Icons -->\n<!-- ##### -->\n\n<xsl:template match=\"icon\">\n    <!-- the name attribute of the \"icon\" in text as a string -->\n    <xsl:variable name=\"icon-name\">\n        <xsl:value-of select=\"@name\"/>\n    </xsl:variable>\n\n    <!-- for-each is just one node, but sets context for key() -->\n    <xsl:for-each select=\"$icon-table\">\n        <xsl:value-of select=\"key('icon-key', $icon-name)/@unicode\" />\n    </xsl:for-each>\n</xsl:template>\n\n<!-- ############# -->\n<!-- Keyboard Keys -->\n<!-- ############# -->\n\n<!-- Comments are Unicode names, from fileformat.info             -->\n<!-- @latex values are macros in the menukeys package specifying  -->\n<!-- keyboard keys that are typically labeled with graphics,      -->\n<!-- or \"textcomp Text-mode Math Symbols\" from \"The Comprehensive -->\n<!-- LaTeX Symbol List\", or constructions combining them          -->\n<xsl:variable name=\"kbdkey-rtf\">\n    <kbdkeyinfo name=\"left\"\n                latex=\"\\arrowkeyleft\"\n                unicode=\"&#x2190;\"/> <!-- LEFTWARDS ARROW -->\n    <kbdkeyinfo name=\"up\"\n                latex=\"\\arrowkeyup\"\n                unicode=\"&#x2191;\"/> <!-- UPWARDS ARROW -->\n    <kbdkeyinfo name=\"right\"\n                latex=\"\\arrowkeyright\"\n                unicode=\"&#x2192;\"/> <!-- RIGHTWARDS ARROW -->\n    <kbdkeyinfo name=\"down\"\n                latex=\"\\arrowkeydown\"\n                unicode=\"&#x2193;\"/> <!-- DOWNWARDS ARROW -->\n    <kbdkeyinfo name=\"enter\"\n                latex=\"\\return\"\n                unicode=\"&#x2BA0;\"/> <!-- DOWNWARDS TRIANGLE-HEADED ARROW WITH LONG TIP LEFTWARDS -->\n    <kbdkeyinfo name=\"shift\"\n                latex=\"\\shift\"\n                unicode=\"&#x21E7;\"/> <!-- UPWARDS WHITE ARROW -->\n    <kbdkeyinfo name=\"ampersand\"\n                latex=\"\\&amp;\"\n                unicode=\"&#x0026;\"/> <!-- AMPERSAND -->\n    <kbdkeyinfo name=\"less\"\n                latex='\\textless'\n                unicode=\"&#x003C;\"/> <!-- LESS-THAN SIGN-->\n    <kbdkeyinfo name=\"greater\"\n                latex='\\textgreater'\n                unicode=\"&#x003E;\"/> <!-- GREATER-THAN SIGN-->\n    <kbdkeyinfo name=\"dollar\"\n                latex='\\$'\n                unicode=\"&#x0024;\"/> <!-- DOLLAR SIGN -->\n    <kbdkeyinfo name=\"percent\"\n                latex='\\%'\n                unicode=\"&#x0025;\"/> <!-- PERCENT SIGN -->\n    <!-- pair of braces is not confused as AVT notation -->\n    <kbdkeyinfo name=\"openbrace\"\n                latex='\\textbraceleft'\n                unicode=\"{{\"/> <!-- LEFT CURLY BRACKET -->\n    <kbdkeyinfo name=\"closebrace\"\n                latex='\\textbraceright'\n                unicode=\"}}\"/> <!-- RIGHT CURLY BRACKET -->\n    <kbdkeyinfo name=\"hash\"\n                latex='\\#'\n                unicode=\"&#x0023;\"/> <!-- OCTOTHORPE -->\n    <kbdkeyinfo name=\"backslash\"\n                latex='\\textbackslash'\n                unicode=\"&#x005C;\"/> <!-- BACKSLASH -->\n    <kbdkeyinfo name=\"tilde\"\n                latex='\\textasciitilde'\n                unicode=\"&#x007E;\"/> <!-- TILDE -->\n    <kbdkeyinfo name=\"circumflex\"\n                latex='\\textasciicircum'\n                unicode=\"&#x005E;\"/> <!-- CIRCUMFLEX ACCENT -->\n    <kbdkeyinfo name=\"underscore\"\n                latex='\\textunderscore'\n                unicode=\"&#x005F;\"/> <!-- LOW LINE -->\n    <kbdkeyinfo name=\"plus\"\n                latex='+'\n                unicode=\"&#x002B;\"/> <!-- PLUS SIGN -->\n    <!-- MINUS SIGN is U+2212, but not in all fonts? -->\n    <kbdkeyinfo name=\"minus\"\n                latex='\\textminus'\n                unicode=\"&#x002D;\"/> <!-- HYPHEN-MINUS -->\n    <kbdkeyinfo name=\"times\"\n                latex='\\texttimes'\n                unicode=\"&#x00D7;\"/> <!-- MULTIPLICATION SIGN -->\n    <kbdkeyinfo name=\"solidus\"\n                latex='\\textfractionsolidus'\n                unicode=\"&#x002F;\"/> <!-- SOLIDUS -->\n    <kbdkeyinfo name=\"obelus\"\n                latex='\\textdiv'\n                unicode=\"&#x00F7;\"/> <!-- DIVISION SIGN -->\n    <kbdkeyinfo name=\"squared\"\n                latex='x\\textasciicircum{}2'\n                unicode=\"x&#x005E;2\"/> <!--  -->\n    <kbdkeyinfo name=\"inverse\"\n                latex='x\\textasciicircum{-1}'\n                unicode=\"x&#x005E;-1\"/> <!--  -->\n    <kbdkeyinfo name=\"left-paren\"\n                latex='('\n                unicode=\"&#x0028;\"/> <!-- LEFT PARENTHESIS -->\n    <kbdkeyinfo name=\"right-paren\"\n                latex=')'\n                unicode=\"&#x0029;\"/> <!-- RIGHT PARENTHESIS -->\n</xsl:variable>\n\n<!-- If read from a file via \"document()\" then   -->\n<!-- the exsl:node-set() call would seem to be   -->\n<!-- unnecessary.  When list above gets too big, -->\n<!-- migrate to a new file after consulting      -->\n<!-- localization scheme                         -->\n<xsl:variable name=\"kbdkey-table\" select=\"exsl:node-set($kbdkey-rtf)\"/>\n\n<xsl:key name=\"kbdkey-key\" match=\"kbdkeyinfo\" use=\"@name\"/>\n\n<!-- ###################### -->\n<!-- Identifiers and Labels -->\n<!-- ###################### -->\n\n<!-- The \"unique-id\" is an attribute built during the descent of the -->\n<!-- tree in the assembly phase, so it is fast to construct and fast -->\n<!-- to read back.  It appears in filenames and URLs when an author  -->\n<!-- has not provided a stable name (an authored \"@label\" is always  -->\n<!-- preferred for anything a reader manages or shares), and it is   -->\n<!-- not permanent: editing a document can renumber it.  A former    -->\n<!-- \"visible-id\" getter, once a slow reader-facing construction,    -->\n<!-- became an alias of this one and was then retired.               -->\n<xsl:template match=\"*\" mode=\"unique-id\">\n    <xsl:value-of select=\"@pi:unique-id\"/>\n</xsl:template>\n\n<!-- An image described by source code, using languages Asymptote,     -->\n<!-- Sage, or LaTeX, should have its filename determined by properties -->\n<!-- of the associated language-specific element, specifically this is -->\n<!-- the province of the @label attribute.  So this is the preference  -->\n<!-- from approximately 2023-08-12.  Looking to the enclosing (parent) -->\n<!-- \"image\" is historical, preserving backward-compatibility.         -->\n<xsl:template match=\"asymptote|sageplot|mermaid|latex-image\" mode=\"image-source-basename\">\n    <xsl:choose>\n        <!-- 2023-08-12: new behavior, prefer a @label (not @xml:id) -->\n        <!-- on the source code element to provide the filename      -->\n        <xsl:when test=\"@label\">\n           <xsl:value-of select=\"@label\"/>\n        </xsl:when>\n        <!-- Next stanza preserves backward-compatibility: previously an       -->\n        <!-- @xml:id value was used to form the filename of an image described -->\n        <!-- by source code (or a default was provided, like image-37).        -->\n        <xsl:when test=\"parent::image\">\n            <xsl:apply-templates select=\"parent::image\" mode=\"unique-id\"/>\n        </xsl:when>\n        <!-- Well-formed PTX source means we never reach the \"otherwise\" -->\n        <xsl:otherwise>\n            <xsl:message>PTX:BUG:  parent of a \"<xsl:value-of select=\"local-name()\"/>\" element in your PreTeXt source is not an \"image\".  If you think this is a programming error (not an error in your source), please report me.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- PreFigure images debuted after the switch to preferring a @label on -->\n<!-- the \"prefigure\" element, and not on the enclosing image, so we can  -->\n<!-- employ an improved version of the \"image-source-basename\" template. -->\n<xsl:template match=\"pf:prefigure\" mode=\"image-source-basename\">\n    <xsl:choose>\n        <!-- Determine if @label is authored or generated for backwrd compatibility -->\n        <xsl:when test=\"not(@pi:authored-label)\">\n            <xsl:apply-templates select=\".\" mode=\"unique-id\"/>\n            <xsl:message>PTX:WARNING:  you are encouraged to place a @label attribute on every \"prefigure\" element.  Otherwise, associated image files will have unreliable filenames.</xsl:message>\n        </xsl:when>\n        <!-- this @label is now guaranteed to be authored -->\n        <xsl:when test=\"@label\">\n           <xsl:value-of select=\"@label\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message>PTX:BUG:  a \"prefigure\" element is confused about where its @label came from</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- When hosted on Runestone, an interactive exercise is tracked in a    -->\n<!-- database across courses (\"base course\") and semesters (\"time\").      -->\n<!-- And the HTML representation of an interactive exercise, when powered -->\n<!-- by Runestone services, needs an HTML id.  But the PreTeXt \"exercise\" -->\n<!-- that wraps it has its own HTML id necessary for targets of           -->\n<!-- cross-reference (in-context) URLs.  We will prefer @label for the    -->\n<!-- PreTeXt \"exercise\" HTML id.  And we will require a *stable* @label   -->\n<!-- from an author, which we will dress up here.  Notice that this can   -->\n<!-- change when an author declares a new edition.                        -->\n<xsl:template match=\"exercise|program|datafile|query|&PROJECT-LIKE;|task|video[@youtube]|exercises|worksheet|interactive[@platform = 'doenetml']|interactive[@iframe]\" mode=\"runestone-id\">\n    <!-- With no @xml:id and no @label we realize the author has not given       -->\n    <!-- any thought to a (semi-)peersistent identifire for the Runestone        -->\n    <!-- database.  So we call that out as an error.  And we do not even         -->\n    <!-- attempt to fallback to an automatically generated string, which         -->\n    <!-- would be malleable over time and editing.                               -->\n    <!-- As part of backwards-compatibility, we copy old @xml:id values into     -->\n    <!-- fresh @label.  But have an internal  @pi:authored-label attribute whose -->\n    <!-- absence alerts us to the copying, which is now not best practice.       -->\n    <!-- These messages were disabled 2024-02-20 as unreliable.  The cause       -->\n    <!-- was a pointer to another component resolving against the authored       -->\n    <!-- source, where the @pi:authored-label stamp does not exist; that is      -->\n    <!-- repaired, so the messages return.  A plain static code listing is       -->\n    <!-- the one element reaching here that legitimately has no database         -->\n    <!-- identity and needs none, so it is exempt.                               -->\n    <xsl:choose>\n        <xsl:when test=\"self::program and not(@interactive = 'activecode' or @interactive = 'codelens')\"/>\n        <xsl:when test=\"$b-host-runestone and not(@xml:id) and not(@pi:authored-label)\">\n            <xsl:message>\n                <xsl:text>PTX:ERROR:  While building for a Runestone server, a PreTeXt \"</xsl:text>\n                <xsl:value-of select=\"local-name(.)\"/>\n                <xsl:text>\" element&#xa;</xsl:text>\n                <xsl:text>has been encountered without a @label attribute and without a @xml:id attribute.&#xa;</xsl:text>\n                <xsl:text>This will cause this Runestone component to fail to perform and there will be no&#xa;</xsl:text>\n                <xsl:text>identification of this component in the Runestone database.  You must add a&#xa;</xsl:text>\n                <xsl:text>@label attribute with a unique value.  (It is not necessary to add a @xml:id, &#xa;</xsl:text>\n                <xsl:text>it is consulted as part of a backward-compatibility arrangement you do not need).&#xa;</xsl:text>\n                <xsl:text>[You may get more than one message about this instance.]&#xa;</xsl:text>\n            </xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\"/>\n        </xsl:when>\n        <xsl:when test=\"$b-host-runestone and not(@pi:authored-label)\">\n            <xsl:message>\n                <xsl:text>PTX:FALLBACK:  While building for a Runestone server, a PreTeXt \"</xsl:text>\n                <xsl:value-of select=\"local-name(.)\"/>\n                <xsl:text>\" element&#xa;</xsl:text>\n                <xsl:text>has been encountered without a @label attribute.  For reasons of backward-compatibility &#xa;</xsl:text>\n                <xsl:text>we have used the value of an @xml:id.  This may not be what you want, and as of 2024-02-15 &#xa;</xsl:text>\n                <xsl:text>is no longer best practice.  You can copy the @xml:id value exactly into a new @label &#xa;</xsl:text>\n                <xsl:text>attribute and this message will stop AND your project's entries in any Runestone database &#xa;</xsl:text>\n                <xsl:text>will be preserved and function exactly as before.&#xa;</xsl:text>\n                <xsl:text>[You may get more than one message about this instance.]&#xa;</xsl:text>\n            </xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\"/>\n        </xsl:when>\n    </xsl:choose>\n    <!-- We require a @label attribute, but allow it to be -->\n    <!-- the result of an automatic copy from an @xml:id.  -->\n    <xsl:variable name=\"label\">\n        <xsl:value-of select=\"@label\"/>\n    </xsl:variable>\n    <xsl:if test=\"$label != ''\">\n        <xsl:call-template name=\"runestone-label-prefix\"/>\n        <xsl:value-of select=\"$label\"/>\n    </xsl:if>\n</xsl:template>\n\n<!-- Special handling for programs in exercise-like elements.              -->\n<!-- We want to associate those programs with the label on their container -->\n<!-- and NOT with an auto-generated label on the program itself that might -->\n<!-- come from an @xml:id.                                                 -->\n<!-- This is an implicit use of &PROJECT-LIKE; and should be kept in sync  -->\n<xsl:template match=\"exercise/program|task/program|project/program|activity/program|exploration/program|investigation/program\" mode=\"runestone-id\">\n    <xsl:variable name=\"label\">\n        <xsl:value-of select=\"../@label\"/>\n    </xsl:variable>\n    <xsl:if test=\"$label != ''\">\n        <xsl:call-template name=\"runestone-label-prefix\"/>\n        <xsl:value-of select=\"$label\"/>\n    </xsl:if>\n</xsl:template>\n\n<!-- Prefix just for RS-server builds, in order that the database -->\n<!-- of exercises gets a globally unique identifier.              -->\n<!-- And for a non-RS-server build, we add a prefix in order to   -->\n<!-- differentiate from nearby (wrappers) uses of @label for      -->\n<!-- PreTeXt functions.                                           -->\n<xsl:template name=\"runestone-label-prefix\">\n    <xsl:choose>\n        <xsl:when test=\"$b-host-runestone\">\n            <!-- global variables defined in this stylesheet -->\n            <xsl:value-of select=\"$document-id\"/>\n            <xsl:text>_</xsl:text>\n            <xsl:value-of select=\"$edition\"/>\n            <xsl:text>_</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>rs-</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Need a unique filename for codelens traces                                -->\n<!-- unique-id can change if an xml:id is added to program for other reasons   -->\n<!-- Can't vary with build target (so no runestone-id)                         -->\n<!-- Should generally mirror rs-id but without prefix                          -->\n<xsl:template match=\"program[@interactive = 'codelens']\" mode=\"runestone-codelens-trace-filename\">\n    <xsl:choose>\n        <!-- If part of exercise-like, use that label, otherwise own                -->\n        <!-- This is an implicit use of &PROJECT-LIKE; and should be kept in sync   -->\n        <xsl:when test=\"parent::exercise|parent::task|parent::project|parent::activity|parent::exploration|parent::investigation\">\n            <xsl:value-of select=\"../@pi:unique-id\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"@pi:unique-id\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n    <xsl:text>.js</xsl:text>\n</xsl:template>\n\n<!--            -->\n<!-- Long Names -->\n<!--            -->\n\n<!-- Simple text representations of structural elements        -->\n<!-- Type, number (empty?), optional title typically           -->\n<!-- Ignore footnotes in these constructions                   -->\n<!-- Used for author's report, LaTeX typeout during processing -->\n<xsl:template match=\"*\" mode=\"long-name\">\n    <xsl:apply-templates select=\".\" mode=\"type-name\" />\n    <xsl:text> </xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"number\" />\n    <xsl:text> </xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"title-simple\"/>\n</xsl:template>\n\n\n<!-- ######### -->\n<!-- Numbering -->\n<!-- ######### -->\n\n<!-- We mimic default LaTeX behavior as much as possible    -->\n<!--                                                        -->\n<!-- There are six numbering schemes in place:              -->\n<!-- 1) divisions: sections, subsections, etc.              -->\n<!-- 2) environments: theorems, examples, exercises, figures -->\n<!-- 3) equations: display mathematics                      -->\n<!-- 4) exercises: as part of a section of exercises        -->\n<!-- 5) bibliographic items: in multiple sections           -->\n<!-- 6) footnotes:                                          -->\n\n<!-- Every such item has two numbers                   -->\n<!--                                                   -->\n<!-- a) \"structural\": for example, X.Y.Z for an item   -->\n<!--     in Chapter X, Section Y, Subsection Z         -->\n<!-- b) \"serial\": for example N, where the item is     -->\n<!--     number N of its scheme, within some division  -->\n<!--                                                   -->\n<!-- We form a \"full number\" by concatenating these,   -->\n<!-- so \"Claim X.Y.Z.N\" would be the N-th instance of  -->\n<!-- a scheme 2 item with division X.Y.Z. An empty     -->\n<!-- serial number is indicative of not being numbered -->\n<!--                                                   -->\n<!-- Parameters of the form \"numbering.<scheme>.level\" -->\n<!-- control the number of components in these numbers -->\n\n\n<!--                       -->\n<!-- Circular Case Numbers -->\n<!--                       -->\n\n<!-- These two templates are to facilitate outputting ⇒\tand ⇐ in different target formats. -->\n<!-- They are (or should be) overridden with appropriate templates of same name in the     -->\n<!-- -latex, -html, etc conversions.                                                       -->\n<xsl:template name=\"double-right-arrow-symbol\">\n    <xsl:message>PTX:BUG: A \"case\" has \"direction\" equal to either \"forward\" or \"cycle\", but the conversion for this output target does not have a double right arrow symbol defined.</xsl:message>\n    <xsl:apply-templates select=\".\" mode=\"location-report\"/>\n</xsl:template>\n<xsl:template name=\"double-left-arrow-symbol\">\n    <xsl:message>PTX:BUG: A \"case\" has \"direction\" equal to \"backward\", but the conversion for this output target does not have a double left arrow symbol defined.</xsl:message>\n    <xsl:apply-templates select=\".\" mode=\"location-report\"/>\n</xsl:template>\n<!-- This template is to add an extra small horizontal space between the outer delimiters -->\n<!-- and the inner content of the \"cycle\" title for a \"case\", in case the \"marker\" on the -->\n<!-- corresponding \"ol\" also involves delimiters. Not an error if this is left undefined  -->\n<!-- or is defined to be a null string in a particular conversion stylesheet, in which    -->\n <!-- case no extra space is added. -->\n<xsl:template name=\"case-cycle-delimiter-space\">\n    <xsl:message>PTX:BUG: A \"case\" has \"direction\" equal to \"cycle\", but the conversion for this output target does not have a \"delimiter space\" symbol defined. The maintainer for this output target may wish to know about this (or may wish to set the \"delimiter space\" symbol to be a null string to suppress this warning message).</xsl:message>\n    <xsl:apply-templates select=\".\" mode=\"location-report\"/>\n</xsl:template>\n\n<xsl:template match=\"ol\" mode=\"marker-formatted-case-cycle\">\n    <xsl:param name=\"from\" />\n    <xsl:param name=\"to\" />\n    <xsl:variable name=\"format-code\">\n        <xsl:choose>\n            <xsl:when test=\"self::node()[@pi:format-code]\">\n                <xsl:value-of select=\"./@pi:format-code\" />\n            </xsl:when>\n            <xsl:otherwise>1</xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"adjusted-from\">\n        <xsl:choose>\n            <xsl:when test=\"$format-code = '0'\"><xsl:value-of select=\"$from - 1\" /></xsl:when>\n            <xsl:otherwise><xsl:value-of select=\"$from\" /></xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"adjusted-to\">\n        <xsl:choose>\n            <xsl:when test=\"$format-code = '0'\"><xsl:value-of select=\"$to - 1\" /></xsl:when>\n            <xsl:otherwise><xsl:value-of select=\"$to\" /></xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"original-marker-suffix\" select=\"./@pi:marker-suffix\" />\n    <xsl:variable name=\"marker-suffix\">\n        <xsl:choose>\n            <!-- Strip out any trailing dot from the marker format. -->\n            <xsl:when test=\"substring($original-marker-suffix, string-length($original-marker-suffix)) = '.'\">\n                <xsl:value-of select=\"substring($original-marker-suffix,1,string-length($original-marker-suffix) - 1)\" />\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$original-marker-suffix\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:call-template name=\"formatted-case-cycle\">\n        <xsl:with-param name=\"from\">\n            <xsl:value-of select=\"./@pi:marker-prefix\" />\n            <xsl:number value=\"$adjusted-from\" format=\"{$format-code}\" />\n            <xsl:value-of select=\"$marker-suffix\" />\n        </xsl:with-param>\n        <xsl:with-param name=\"to\">\n            <xsl:value-of select=\"./@pi:marker-prefix\" />\n            <xsl:number value=\"$adjusted-to\" format=\"{$format-code}\" />\n            <xsl:value-of select=\"$marker-suffix\" />\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n<xsl:template name=\"formatted-case-cycle\">\n    <xsl:param name=\"from\" />\n    <xsl:param name=\"to\" />\n    <xsl:text>(</xsl:text>\n    <xsl:call-template name=\"case-cycle-delimiter-space\" />\n    <xsl:value-of select=\"$from\" />\n    <xsl:text>&#xa0;</xsl:text>\n    <xsl:call-template name=\"double-right-arrow-symbol\" />\n    <xsl:text>&#xa0;</xsl:text>\n    <xsl:value-of select=\"$to\" />\n    <xsl:call-template name=\"case-cycle-delimiter-space\" />\n    <xsl:text>)&#xa0;</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"case\" mode=\"case-cycle-numbers\">\n    <xsl:variable name=\"cycle-position\">\n        <xsl:number count=\"case[@direction='cycle']\" />\n    </xsl:variable>\n    <xsl:number value=\"$cycle-position\" />\n    <xsl:text>|</xsl:text>\n    <xsl:choose>\n        <xsl:when test=\"$cycle-position = count(../case[@direction='cycle'])\">\n            <xsl:if test=\"$cycle-position = 1\">\n                <xsl:message>PTX:WARNING: a \"case\" with @direction \"cycle\" should be one of several</xsl:message>\n                <xsl:apply-templates select=\"../..\" mode=\"location-report\"/>\n            </xsl:if>\n            <xsl:number value=\"1\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:number value=\"$cycle-position + 1\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"proof[@ref]/case\" mode=\"case-cycle\">\n    <!-- NB existence/validity of \"@ref\" is already error checked   -->\n    <!-- by code that augments the proof title based on the \"@ref\". -->\n    <xsl:variable name=\"cycle-numbers\">\n        <xsl:apply-templates select=\".\" mode=\"case-cycle-numbers\" />\n    </xsl:variable>\n    <xsl:variable name=\"cycle-position\" select=\"substring-before($cycle-numbers,'|')\" />\n    <xsl:variable name=\"cycle-position-plus-one\" select=\"substring-after($cycle-numbers,'|')\" />\n    <xsl:variable name=\"target\" select=\"id(../@ref)\"/>\n    <!-- \"@ref\" should point to something containing an \"ol\". -->\n    <!-- NB In future this might be a \"statement\" child of a  -->\n    <!-- THEOREM-LIKE instead of specifically a THEOREM-LIKE. -->\n    <xsl:choose>\n        <xsl:when test=\"$target//ol[1]\">\n            <xsl:apply-templates select=\"$target//ol[1]\" mode=\"marker-formatted-case-cycle\">\n                <xsl:with-param name=\"from\" select=\"$cycle-position\" />\n                <xsl:with-param name=\"to\" select=\"$cycle-position-plus-one\" />\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message>PTX:WARNING:   a cross-reference (\"ref\") from a \"<xsl:value-of select=\"local-name(..)\"/>\" containing at least one \"case\" with \"direction\" set to \"cycle\" uses a reference [<xsl:value-of select=\"../@ref\"/>] that does not point to an element that contains an \"ol\".</xsl:message>\n            <xsl:apply-templates select=\"../..\" mode=\"location-report\"/>\n            <xsl:call-template name=\"formatted-case-cycle\">\n                <xsl:with-param name=\"from\" select=\"$cycle-position\" />\n                <xsl:with-param name=\"to\" select=\"$cycle-position-plus-one\" />\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"proof[not(@ref)]/case\" mode=\"case-cycle\">\n    <xsl:variable name=\"cycle-numbers\">\n        <xsl:apply-templates select=\".\" mode=\"case-cycle-numbers\" />\n    </xsl:variable>\n    <xsl:variable name=\"cycle-position\" select=\"substring-before($cycle-numbers,'|')\" />\n    <xsl:variable name=\"cycle-position-plus-one\" select=\"substring-after($cycle-numbers,'|')\" />\n    <xsl:choose>\n        <!-- Check if the \"proof\" has a \"statement\" sibling    -->\n        <!-- (implying the \"proof\" is a child of THEOREM-LIKE) -->\n        <!-- where that \"statement\" sibling contains an \"ol\"   -->\n        <!-- from which we can copy the marker information.    -->\n        <!-- NB We don't filter on \"ol[@marker]\" because we    -->\n        <!-- still need to honour the format code which may    -->\n        <!-- be derived from nesting during -assembly. Not     -->\n        <!-- relevant now because our \"ol\" should be top level -->\n        <!-- in its \"statement\" but potentially relevant in    -->\n        <!-- future if THEOREM-LIKE supports multiple          -->\n        <!-- \"statement\" children which would then become the  -->\n        <!-- top-level numbering for any list-like children.   -->\n        <xsl:when test=\"../preceding-sibling::statement[1]//ol[1]\">\n            <xsl:apply-templates select=\"../preceding-sibling::statement[1]//ol[1]\" mode=\"marker-formatted-case-cycle\">\n                <xsl:with-param name=\"from\" select=\"$cycle-position\" />\n                <xsl:with-param name=\"to\" select=\"$cycle-position-plus-one\" />\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:call-template name=\"formatted-case-cycle\">\n                <xsl:with-param name=\"from\" select=\"$cycle-position\" />\n                <xsl:with-param name=\"to\" select=\"$cycle-position-plus-one\" />\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"case\" mode=\"case-direction\">\n    <xsl:choose>\n        <xsl:when test=\"@direction='forward'\">\n            <xsl:text>(</xsl:text>\n            <xsl:call-template name=\"double-right-arrow-symbol\" />\n            <xsl:text>)&#xa0;</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"@direction='backward'\">\n            <xsl:text>(</xsl:text>\n            <xsl:call-template name=\"double-left-arrow-symbol\" />\n            <xsl:text>)&#xa0;</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"@direction='cycle'\">\n            <xsl:apply-templates select=\".\" mode=\"case-cycle\" />\n        </xsl:when>\n        <!-- DTD will catch wrong values -->\n        <xsl:otherwise />\n    </xsl:choose>\n</xsl:template>\n\n<!-- TESTING -->\n<!-- Some test images and debugging output, -->\n<!-- while this is still in development -->\n\n<!--\n<image />\n<image margins=\"20% 5%\" />\n<image width=\"75%\" />\n<image margins=\"20% 5%\" width=\"75%\" />\n -->\n<!-- ~~~~~~~~~~~~~~ -->\n<!--\n<image margins=\"150pt\" />\n<image width=\"2000\" />\n<image margins=\"-40%\" />\n<image margins=\"300%\" />\n<image margins=\"-20% 5%\" />\n<image margins=\"20% 150%\" />\n<image margins=\"90% 40%\" />\n<image margins=\"5% 10%\" width=\"120%\" />\n<image margins=\"5% 10%\" width=\"-10%\" />\n<image margins=\"5% 10%\" width=\"90%\" />\n<image margins=\"35% 25%\" width=\"39.5%\" />\n-->\n\n<!--\n<xsl:template match=\"image[not(parent::sidebyside or parent::figure)]\">\n    <xsl:variable name=\"rtf-layout\">\n        <xsl:apply-templates select=\".\" mode=\"layout-parameters\" />\n    </xsl:variable>\n    <xsl:variable name=\"layout\" select=\"exsl:node-set($rtf-layout)\" />\n    <xsl:message><xsl:value-of select=\"$layout/left-margin\" /></xsl:message>\n    <xsl:message><xsl:value-of select=\"$layout/width\" /></xsl:message>\n    <xsl:message><xsl:value-of select=\"$layout/right-margin\" /></xsl:message>\n    <xsl:message><xsl:value-of select=\"$layout/left-margin = $layout/right-margin\" /></xsl:message>\n</xsl:template>\n-->\n\n<!-- ############## -->\n<!-- Simple Layouts -->\n<!-- ############## -->\n\n<!-- This template creates a RTF (result tree fragment), -->\n<!-- which needs to be captured in one variable, then    -->\n<!-- converted to a node-set with an extension function  -->\n\n<!-- aspect-ratio is only needed for videos in HTML.     -->\n<!-- Long story.  It needs to match what is provided     -->\n<!-- in the video (a file or an embedded player).  A     -->\n<!-- sensible default is \"1:1\" but in context we might   -->\n<!-- want to supply some other sensible default like     -->\n<!-- \"16:9\".  The ONLY purpose of specifying an          -->\n<!-- aspect-ratio is to compute some sort of height.     -->\n<!-- So we do not report the aspect-ratio itself, but    -->\n<!-- instead compute a height (*only* for video).        -->\n\n<!-- NB: An RTF has a \"root\" node.  Then the elements    -->\n<!-- manufactured for it occur as children.  If the      -->\n<!-- \"apply-templates\" fails to have the \"/*\" at the end -->\n<!-- of the \"select\", then the main entry template will  -->\n<!-- be called to do any housekeeping it might do.       -->\n<!-- This was a really tough bug to track down.          -->\n\n<xsl:template match=\"image|audio|video|program|console|tabular\" mode=\"layout-parameters\">\n    <xsl:param name=\"default-aspect\" select=\"'1:1'\"/>\n\n    <!-- clean up margins -->\n    <xsl:variable name=\"normalized-margins\">\n        <xsl:choose>\n            <xsl:when test=\"@margins\">\n                <xsl:value-of select=\"normalize-space(@margins)\" />\n            </xsl:when>\n            <!-- not placed on image, or figure/image,      -->\n            <!-- but a document-wide default margins exists -->\n            <xsl:when test=\"self::image and not(ancestor::sidebyside) and $docinfo/defaults/images/@margins\">\n                <xsl:value-of select=\"normalize-space($docinfo/defaults/images/@margins)\" />\n            </xsl:when>\n            <!-- default if not specified -->\n            <xsl:otherwise>\n                <xsl:text>auto</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n\n    <!-- split on space, or else duplicate (signals centered) -->\n    <xsl:variable name=\"normalized-left-margin\">\n        <xsl:choose>\n            <xsl:when test=\"contains($normalized-margins, ' ')\">\n                <xsl:value-of select=\"substring-before($normalized-margins, ' ')\" />\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$normalized-margins\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n\n    <xsl:variable name=\"normalized-right-margin\">\n        <xsl:choose>\n            <xsl:when test=\"contains($normalized-margins, ' ')\">\n                <xsl:value-of select=\"substring-after($normalized-margins, ' ')\" />\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$normalized-margins\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n\n    <!-- clean-up single width -->\n    <xsl:variable name=\"normalized-width\">\n        <xsl:choose>\n            <xsl:when test=\"@width\">\n                <xsl:value-of select=\"normalize-space(@width)\" />\n            </xsl:when>\n            <!-- not placed on image, or figure/image,    -->\n            <!-- but a document-wide default width exists -->\n            <xsl:when test=\"self::image and not(ancestor::sidebyside) and $docinfo/defaults/images/@width\">\n                <xsl:value-of select=\"$docinfo/defaults/images/@width\" />\n            </xsl:when>\n            <!-- default setting if not specified, and not global -->\n            <xsl:otherwise>\n                <xsl:value-of select=\"'auto'\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n\n    <!-- clean-up aspect-ratio -->\n    <!-- may be a hollow exercise, but no harm since a -->\n    <!-- valid ratio is given in parameter default     -->\n    <xsl:variable name=\"normalized-aspect\">\n        <xsl:variable name=\"entered-aspect\">\n            <xsl:choose>\n                <xsl:when test=\"@aspect\">\n                    <xsl:value-of select=\"normalize-space(@aspect)\"/>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:value-of select=\"normalize-space($default-aspect)\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:variable>\n        <xsl:choose>\n            <!-- test if a ratio is given, and assume parts are -->\n            <!-- good and that there is only one colon, etc,... -->\n            <xsl:when test=\"contains($entered-aspect, ':')\">\n                <xsl:variable name=\"width\" select=\"substring-before($entered-aspect, ':')\" />\n                <xsl:variable name=\"height\" select=\"substring-after($entered-aspect, ':')\" />\n                <xsl:value-of select=\"$width div $height\" />\n            </xsl:when>\n            <!-- else assume a number was entered -->\n            <xsl:otherwise>\n                <xsl:value-of select=\"$entered-aspect\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n\n    <!-- Error checks on author's specifications     -->\n    <!-- First, normalized to strings or percentages -->\n\n    <xsl:if test=\"not(($normalized-left-margin = 'auto') or substring($normalized-left-margin, string-length($normalized-left-margin)) = '%')\">\n        <xsl:message>PTX:ERROR:   left margin (<xsl:value-of select=\"$normalized-left-margin\" />) should be given as a percentage (such as \"40%\"), or as the string \"auto\"</xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\" />\n    </xsl:if>\n\n    <xsl:if test=\"not(($normalized-width = 'auto') or substring($normalized-width, string-length($normalized-width)) = '%')\">\n        <xsl:message>PTX:ERROR:   width (<xsl:value-of select=\"$normalized-width\" />) should be given as a percentage (such as \"40%\"), or as the string \"auto\"</xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\" />\n    </xsl:if>\n\n    <xsl:if test=\"not(($normalized-right-margin = 'auto') or substring($normalized-right-margin, string-length($normalized-right-margin)) = '%')\">\n        <xsl:message>PTX:ERROR:   right margin (<xsl:value-of select=\"$normalized-right-margin\" />) should be given as a percentage (such as \"40%\"), or as the string \"auto\"</xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\" />\n    </xsl:if>\n\n    <!-- Second, cases where computed values could be negative or too large -->\n\n    <!-- Sanity check author's left margin -->\n    <xsl:if test=\"not($normalized-left-margin = 'auto') and ((substring-before($normalized-left-margin, '%') &lt; 0) or (substring-before($normalized-left-margin, '%') &gt; 100))\">\n        <xsl:message>PTX:ERROR:   left margin (<xsl:value-of select=\"$normalized-left-margin\" />) must be in the interval [0%, 100%]</xsl:message>\n        <xsl:apply-templates select=\".\" mode=\"location-report\" />\n    </xsl:if>\n\n    <!-- Sanity check author's width -->\n    <xsl:if test=\"not($normalized-width= 'auto') and ((substring-before($normalized-width, '%') &lt; 0) or (substring-before($normalized-width, '%') &gt; 100))\">\n        <xsl:message>PTX:ERROR:   width (<xsl:value-of select=\"$normalized-width\" />) must be in the interval [0%, 100%]</xsl:message>\n        <xsl:apply-templates select=\".\" mode=\"location-report\" />\n    </xsl:if>\n\n    <!-- Sanity check author's right margin -->\n    <xsl:if test=\"not($normalized-right-margin = 'auto') and ((substring-before($normalized-right-margin, '%') &lt; 0) or (substring-before($normalized-right-margin, '%') &gt; 100))\">\n        <xsl:message>PTX:ERROR:   right margin (<xsl:value-of select=\"$normalized-right-margin\" />) must be in the interval [0%, 100%]</xsl:message>\n        <xsl:apply-templates select=\".\" mode=\"location-report\" />\n    </xsl:if>\n\n    <!-- Sanity check author's cumulative margins -->\n    <xsl:if test=\"not($normalized-left-margin = 'auto') and ((substring-before($normalized-left-margin, '%') + substring-before($normalized-right-margin, '%') &gt; 100))\">\n        <xsl:message>PTX:ERROR:   margins (<xsl:value-of select=\"$normalized-left-margin\" />, <xsl:value-of select=\"$normalized-right-margin\" />) must not have a sum exceeding 100%</xsl:message>\n        <xsl:apply-templates select=\".\" mode=\"location-report\" />\n    </xsl:if>\n\n    <!-- Sanity check all parameters together as too large -->\n    <xsl:if test=\"not($normalized-left-margin = 'auto') and not($normalized-width= 'auto') and ((substring-before($normalized-left-margin, '%') + substring-before($normalized-width, '%') + substring-before($normalized-right-margin, '%') &gt; 100))\">\n        <xsl:message>PTX:ERROR:   margins and width (<xsl:value-of select=\"$normalized-left-margin\" />, <xsl:value-of select=\"$normalized-width\" />, <xsl:value-of select=\"$normalized-right-margin\" />) must not have a sum exceeding 100%</xsl:message>\n        <xsl:apply-templates select=\".\" mode=\"location-report\" />\n    </xsl:if>\n\n    <!-- Sanity check that all three parameters together sum to 100 *exactly* -->\n    <xsl:if test=\"not($normalized-left-margin = 'auto') and not($normalized-width= 'auto') and not((substring-before($normalized-left-margin, '%') + substring-before($normalized-width, '%') + substring-before($normalized-right-margin, '%') = 100))\">\n        <xsl:message>PTX:ERROR:   margins and width (<xsl:value-of select=\"$normalized-left-margin\" />, <xsl:value-of select=\"$normalized-width\" />, <xsl:value-of select=\"$normalized-right-margin\" />) must sum to 100%</xsl:message>\n        <xsl:apply-templates select=\".\" mode=\"location-report\" />\n    </xsl:if>\n\n    <!-- Sanity check on the aspect-ratio -->\n    <!-- NaN does not equal *anything*, so tests if a number  -->\n    <!-- http://stackoverflow.com/questions/6895870           -->\n    <xsl:if test=\"not(number($normalized-aspect) = number($normalized-aspect)) or ($normalized-aspect &lt; 0)\">\n        <xsl:message>PTX:ERROR:   the @aspect attribute should be a ratio, like 4:3, or a positive number, not \"<xsl:value-of select=\"@aspect\" />\"</xsl:message>\n        <xsl:apply-templates select=\".\" mode=\"location-report\" />\n    </xsl:if>\n    <xsl:if test=\"$normalized-aspect = 0\">\n        <xsl:message>PTX:FATAL:   an @aspect attribute equal to zero will cause serious errors.</xsl:message>\n        <xsl:apply-templates select=\".\" mode=\"location-report\" />\n        <xsl:message terminate=\"yes\">PTX:FATAL:   Quitting...</xsl:message>\n    </xsl:if>\n\n    <!-- Perhaps save for debugging -->\n    <!-- <xsl:message>L:<xsl:value-of select=\"$normalized-left-margin\" />:L W:<xsl:value-of select=\"$normalized-width\" />:W R:<xsl:value-of select=\"$normalized-right-margin\" />:R</xsl:message> -->\n\n    <!-- Now have three \"normalized\" percentages, with percentages   -->\n    <!-- or default string values.  We would read the table below as -->\n    <!-- rows (cases), but we instead focus on the three outcomes    -->\n    <!-- as a single variable each.                                  -->\n    <!--                                                             -->\n    <!--     Margin   Width      Left      Width     Right           -->\n    <!--                                                             -->\n    <!--     auto     auto          0        100         0           -->\n    <!--     value    auto      value    compute     value           -->\n    <!--     auto     value    center      value    center           -->\n    <!--     value    value     value      value     value           -->\n    <!--                                                             -->\n    <!-- In contrast to earlier practice, we now (2018-07-20) return -->\n    <!-- percentages with no percent sign, so as to do the least     -->\n    <!-- manipulation possible here.  Consumers can add back the     -->\n    <!-- percent sign, divide by 100, take a fraction of a maximum   -->\n    <!-- width, and so on.                                           -->\n\n    <xsl:variable name=\"left-margin\">\n        <xsl:choose>\n            <xsl:when test=\"($normalized-left-margin = 'auto') and ($normalized-width = 'auto')\">\n                <xsl:value-of select=\"'0'\" />\n            </xsl:when>\n            <xsl:when test=\"not($normalized-left-margin = 'auto') and ($normalized-width = 'auto')\">\n                <xsl:value-of select=\"substring-before($normalized-left-margin, '%')\" />\n            </xsl:when>\n            <xsl:when test=\"($normalized-left-margin = 'auto') and not($normalized-width = 'auto')\">\n                <xsl:value-of select=\"(100 - substring-before($normalized-width, '%')) div 2\" />\n            </xsl:when>\n            <xsl:when test=\"not($normalized-left-margin = 'auto') and not($normalized-width = 'auto')\">\n                <xsl:value-of select=\"substring-before($normalized-left-margin, '%')\" />\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>OOOPS1111</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n\n    <xsl:variable name=\"right-margin\">\n        <xsl:choose>\n            <xsl:when test=\"($normalized-left-margin = 'auto') and ($normalized-width = 'auto')\">\n                <xsl:value-of select=\"'0'\" />\n            </xsl:when>\n            <xsl:when test=\"not($normalized-left-margin = 'auto') and ($normalized-width = 'auto')\">\n                <xsl:value-of select=\"substring-before($normalized-right-margin, '%')\" />\n            </xsl:when>\n            <xsl:when test=\"($normalized-left-margin = 'auto') and not($normalized-width = 'auto')\">\n                <xsl:value-of select=\"(100 - substring-before($normalized-width, '%')) div 2\" />\n            </xsl:when>\n            <xsl:when test=\"not($normalized-left-margin = 'auto') and not($normalized-width = 'auto')\">\n                <xsl:value-of select=\"substring-before($normalized-right-margin, '%')\" />\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>OOOPS22222</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n\n    <xsl:variable name=\"width\">\n        <xsl:choose>\n            <xsl:when test=\"($normalized-left-margin = 'auto') and ($normalized-width = 'auto')\">\n                <xsl:value-of select=\"'100'\" />\n            </xsl:when>\n            <xsl:when test=\"not($normalized-left-margin = 'auto') and ($normalized-width = 'auto')\">\n                <xsl:value-of select=\"100 - substring-before($normalized-left-margin, '%') - substring-before($normalized-right-margin, '%')\" />\n            </xsl:when>\n            <xsl:when test=\"($normalized-left-margin = 'auto') and not($normalized-width = 'auto')\">\n                <xsl:value-of select=\"substring-before($normalized-width, '%')\" />\n            </xsl:when>\n            <xsl:when test=\"not($normalized-left-margin = 'auto') and not($normalized-width = 'auto')\">\n                <xsl:value-of select=\"substring-before($normalized-width, '%')\" />\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>OOOPS33333</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n\n    <!-- \"height\" is derived from width and aspect-ratio.  -->\n    <!-- We warn above about a potential division by zero. -->\n    <xsl:variable name=\"height\" select=\"$width div $normalized-aspect\"/>\n\n    <xsl:variable name=\"centered\" select=\"$left-margin = $right-margin\" />\n\n    <!-- This is the RTF, which will automatically be bundled with -->\n    <!-- a root. Elements should be mostly self-explanatory.       -->\n    <!-- \"centered\" is reported NOW, not computed later, when the  -->\n    <!-- two margins are either                                    -->\n    <!--   (a) specified identically by the author,                -->\n    <!--   (b) computed identically above, or                      -->\n    <!--   (c) default to identical values.                        -->\n\n    <left-margin>\n        <xsl:value-of select=\"$left-margin\" />\n    </left-margin>\n    <width>\n        <xsl:value-of select=\"$width\" />\n    </width>\n    <!-- Only a \"video\" gets its height from this layout object, -->\n    <!-- so even if we have computed it, we do not report it     -->\n    <xsl:if test=\"self::video\">\n        <height>\n            <xsl:value-of select=\"$height\"/>\n        </height>\n    </xsl:if>\n    <right-margin>\n        <xsl:value-of select=\"$right-margin\" />\n    </right-margin>\n    <centered>\n        <xsl:value-of select=\"$centered\" />\n    </centered>\n\n    <!-- This will be useful in a debugging switch -->\n<!--\n    <xsl:message>l:<xsl:value-of select=\"$left-margin\" />:l w:<xsl:value-of select=\"$width\" />:w r:<xsl:value-of select=\"$right-margin\" />:r c:<xsl:value-of select=\"$centered\" />:c</xsl:message>\n    <xsl:message>- - - - - - - - - - - - - </xsl:message>\n-->\n</xsl:template>\n\n<!-- ################## -->\n<!-- SideBySide Layouts -->\n<!-- ################## -->\n\n<!-- Horizontal layouts of \"panels\" with vertical alignments      -->\n<!-- A container for layout of other elements, eg figures, images -->\n<!-- No notion of columns, no rules or dividers, no row headers   -->\n<!-- This is purely a container to specify layout parameters,     -->\n<!-- and place/control the horizontal arrangement in converters   -->\n\n<!-- Debug with sbs.debug string parameter, $sbsdebug variable  -->\n<!-- Colored boxes in HTML, black boxes in LaTeX with baselines -->\n\n<!-- A \"sidebyside\" is a sequence of objects laid out       -->\n<!-- horizontally in panels.  This is a deviation from      -->\n<!-- the usual vertical rythym of a page.  The \"best\"       -->\n<!-- objects are those that are pliable horizontally,       -->\n<!-- such as a paragraph, or a scalable image.  Rigid       -->\n<!-- objects, like pre-formatted text or some tables,       -->\n<!-- require some care from the author.  Attributes         -->\n<!-- that control the layout follow, and override           -->\n<!-- identical attributes placed on an enclosing            -->\n<!-- \"sbsgroup\" (if employed).                              -->\n<!--                                                        -->\n<!-- (a) \"margins\"                                          -->\n<!--  - one percentage for both left and right (nn%)        -->\n<!--  - \"auto\" => margins are half the space between panels -->\n<!--  - default is \"auto\"                                   -->\n<!-- (b) \"widths\"                                           -->\n<!--  - widths of panels, one per panel                     -->\n<!--  - space separated list of percentages                 -->\n<!--  - default is equal division of available total width  -->\n<!-- (c) \"valigns\", \"valign\"                                -->\n<!--  - vertical alignment of content within panel          -->\n<!--  - space separated list of top, middle, bottom         -->\n<!--  - singular is common alignment for all panels         -->\n<!--  - default is top                                      -->\n<!--                                                        -->\n<!-- Default behavior is automatic margins, no spacing      -->\n<!-- between panels and equally wide panels.                -->\n<!--                                                        -->\n<!-- With widths specified, remaining space is              -->\n<!-- used to create equal spacing between panels            -->\n\n<!-- Extensive layout analysis first, main templates follow -->\n\n<!-- We analyze the attributes of a \"sidebyside\" element -->\n<!-- in order to extract/compute the layout parameters   -->\n<!-- This template creates a RTF (result tree fragment), -->\n<!-- which needs to be captured in one variable, then    -->\n<!-- converted to a node-set with an extension function  -->\n<xsl:template match=\"sidebyside\" mode=\"layout-parameters\">\n\n    <!-- Number of Panels -->\n    <!-- count the elements destined for panels  -->\n    <xsl:variable name=\"number-panels\" select=\"count(*)\" />\n    <xsl:if test=\"$sbsdebug\">\n        <xsl:message>PTX:DEBUG: N:<xsl:value-of select=\"$number-panels\" />:N</xsl:message>\n    </xsl:if>\n    <!-- Add to RTF -->\n    <number-panels>\n        <xsl:value-of select=\"$number-panels\" />\n    </number-panels>\n\n    <!-- Vertical Alignments of Panels -->\n    <!-- Produce temporary space-separated list, with trailing space     -->\n    <!-- Look up into enclosing \"sbsgroup\" if none given on \"sidebyside\" -->\n    <!-- Error-check attribute values as $valigns string gets unpacked   -->\n    <xsl:variable name=\"valigns\">\n        <xsl:choose>\n            <!-- individual sbs takes priority -->\n            <xsl:when test=\"@valigns\">\n                <xsl:value-of select=\"concat(normalize-space(@valigns), ' ')\" />\n            </xsl:when>\n            <!-- singular form is convenience -->\n            <xsl:when test=\"@valign\">\n                <xsl:call-template name=\"duplicate-string\">\n                     <xsl:with-param name=\"text\" select=\"concat(normalize-space(@valign), ' ')\" />\n                     <xsl:with-param name=\"count\" select=\"$number-panels\" />\n                 </xsl:call-template>\n            </xsl:when>\n            <!-- look to enclosing sbsgroup -->\n            <xsl:when test=\"parent::sbsgroup[@valigns]\">\n                <xsl:value-of select=\"concat(normalize-space(parent::sbsgroup/@valigns), ' ')\" />\n            </xsl:when>\n            <!-- look to enclosing sbsgroup for singular convenience -->\n            <xsl:when test=\"parent::sbsgroup[@valign]\">\n                <xsl:call-template name=\"duplicate-string\">\n                     <xsl:with-param name=\"text\" select=\"concat(normalize-space(parent::sbsgroup/@valign), ' ')\" />\n                     <xsl:with-param name=\"count\" select=\"$number-panels\" />\n                 </xsl:call-template>\n            </xsl:when>\n            <!-- default: place all panels at the top   -->\n            <!-- NB: space at end of $text is separator -->\n            <xsl:otherwise>\n                <xsl:call-template name=\"duplicate-string\">\n                     <xsl:with-param name=\"text\" select=\"'top '\" />\n                     <xsl:with-param name=\"count\" select=\"$number-panels\" />\n                 </xsl:call-template>\n             </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:if test=\"$sbsdebug\">\n        <xsl:message>PTX:DEBUG: VA:<xsl:value-of select=\"$valigns\" />:VA</xsl:message>\n    </xsl:if>\n    <!-- check length (author-supplied could be wrong) -->\n    <xsl:variable name=\"nspaces-valigns\" select=\"string-length($valigns) - string-length(translate($valigns, ' ', ''))\" />\n    <xsl:choose>\n        <xsl:when test=\"$nspaces-valigns &lt; $number-panels\">\n            <xsl:message>PTX:FATAL:   a &lt;sidebyside&gt; or &lt;sbsgroup&gt; does not have enough \"@valigns\" (maybe you did not specify enough?)</xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\" />\n            <xsl:message terminate=\"yes\">PTX:FATAL:   Quitting...</xsl:message>\n        </xsl:when>\n        <xsl:when test=\"$nspaces-valigns &gt; $number-panels\">\n            <xsl:message>PTX:WARNING: a &lt;sidebyside&gt; or &lt;sbsgroup&gt; has extra \"@valigns\" (did you confuse singular and plural attribute names?)</xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\" />\n        </xsl:when>\n    </xsl:choose>\n    <!-- unpack with an error-check on attribute values -->\n    <!-- RTF formation happens with unpacking           -->\n    <xsl:call-template name=\"decompose-valigns\">\n        <xsl:with-param name=\"valigns\" select=\"$valigns\" />\n    </xsl:call-template>\n\n\n    <!-- Margins and Widths -->\n    <!-- clean up and organize widths                             -->\n    <!-- Always produces space-separated list with trailing space -->\n    <!-- Error-check as $widths string gets depleted below        -->\n    <xsl:variable name=\"normalized-widths\">\n        <xsl:choose>\n            <!-- individual sbs takes priority -->\n            <xsl:when test=\"@widths\">\n                <xsl:value-of select=\"concat(normalize-space(@widths), ' ')\" />\n            </xsl:when>\n            <!-- singular form is convenience -->\n            <xsl:when test=\"@width\">\n                <xsl:call-template name=\"duplicate-string\">\n                     <xsl:with-param name=\"text\" select=\"concat(normalize-space(@width), ' ')\" />\n                     <xsl:with-param name=\"count\" select=\"$number-panels\" />\n                 </xsl:call-template>\n            </xsl:when>\n            <!-- look to enclosing sidebyside group -->\n            <xsl:when test=\"parent::sbsgroup[@widths]\">\n                <xsl:value-of select=\"concat(normalize-space(parent::sbsgroup/@widths), ' ')\" />\n            </xsl:when>\n            <!-- look to enclosing sidebyside group for singular convenience -->\n            <xsl:when test=\"parent::sbsgroup[@width]\">\n                <xsl:call-template name=\"duplicate-string\">\n                     <xsl:with-param name=\"text\" select=\"concat(normalize-space(parent::sbsgroup/@width), ' ')\" />\n                     <xsl:with-param name=\"count\" select=\"$number-panels\" />\n                 </xsl:call-template>\n            </xsl:when>\n            <!-- defer default computation post-margins      -->\n            <!-- NB: \"undetermined\" widths is a single space -->\n            <xsl:otherwise>\n                <xsl:text> </xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n\n    <!-- clean up margins -->\n    <xsl:variable name=\"normalized-margins\">\n        <xsl:choose>\n            <!-- individual sbs takes priority -->\n            <xsl:when test=\"@margins\">\n                <xsl:value-of select=\"normalize-space(@margins)\" />\n            </xsl:when>\n            <!-- look to enclosing sidebyside group -->\n            <xsl:when test=\"parent::sbsgroup[@margins]\">\n                <xsl:value-of select=\"normalize-space(parent::sbsgroup/@margins)\" />\n            </xsl:when>\n            <!-- default will make pleasing layout: -->\n            <!--   (a) for one panel, no settings -->\n            <!--   (b) no margin given, all sensible widths -->\n            <xsl:otherwise>\n                <xsl:text>auto</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n\n    <!-- construct left and right margins, possibly identical      -->\n    <!-- these may be 'auto' and get updated later (hence \"early\") -->\n    <xsl:variable name=\"left-margin-early\">\n        <xsl:choose>\n            <xsl:when test=\"contains($normalized-margins, ' ')\">\n                <xsl:value-of select=\"substring-before($normalized-margins, ' ')\" />\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$normalized-margins\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"right-margin-early\">\n        <xsl:choose>\n            <xsl:when test=\"contains($normalized-margins, ' ')\">\n                <xsl:value-of select=\"substring-after($normalized-margins, ' ')\" />\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$normalized-margins\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n\n    <!-- total widths used/available    -->\n    <!-- no attributes, use 100         -->\n    <!-- no width, subtract two margins -->\n    <!-- widths given, sum them         -->\n    <!-- no percent sign, just internal -->\n    <!-- TOD: error-check that sum is 100 or less -->\n    <xsl:variable name=\"sum-widths\">\n        <xsl:choose>\n            <xsl:when test=\"$normalized-widths = ' ' and $normalized-margins = 'auto'\">\n                <xsl:text>100</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"$normalized-widths = ' '\">\n                <xsl:value-of select=\"100 - substring-before($left-margin-early, '%') - substring-before($right-margin-early, '%')\" />\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:call-template name=\"sum-percentages\">\n                    <xsl:with-param name=\"percent-list\" select=\"$normalized-widths\" />\n                    <xsl:with-param name=\"sum\" select=\"'0'\" />\n                </xsl:call-template>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n\n    <!-- have width totals, determine margins         -->\n    <!-- automatic creates margins that will be half -->\n    <!-- of the subsequent space-width computation   -->\n    <!-- Input assumes % present (unless 'auto')     -->\n    <!-- Output preserves % on result                -->\n    <xsl:variable name=\"left-margin\">\n        <xsl:choose>\n            <xsl:when test=\"$number-panels = 0\">\n                <xsl:text>0%</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"$normalized-margins = 'auto'\">\n                <xsl:value-of select=\"(100 - $sum-widths) div (2 * $number-panels)\" />\n                <xsl:text>%</xsl:text>\n            </xsl:when>\n            <!-- TODO: condition on % present, let otherwise report failure -->\n            <xsl:otherwise>\n                <xsl:value-of select=\"$left-margin-early\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"right-margin\">\n        <xsl:choose>\n            <xsl:when test=\"$number-panels = 0\">\n                <xsl:text>0%</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"$normalized-margins = 'auto'\">\n                <xsl:value-of select=\"(100 - $sum-widths) div (2 * $number-panels)\" />\n                <xsl:text>%</xsl:text>\n            </xsl:when>\n            <!-- TODO: condition on % present, let otherwise report failure -->\n            <xsl:otherwise>\n                <xsl:value-of select=\"$right-margin-early\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:if test=\"$sbsdebug\">\n        <xsl:message>PTX:DEBUG: M:<xsl:value-of select=\"$left-margin\" />:<xsl:value-of select=\"$right-margin\" />:M</xsl:message>\n    </xsl:if>\n    <!-- error check for reasonable values -->\n    <!-- When there are three values, the \"left\" margin still -->\n    <!-- has a space character to split on (which of course,  -->\n    <!-- we don't do!).  It seems to survive until here.      -->\n    <xsl:if test=\"contains($right-margin, ' ')\">\n        <xsl:message>PTX:ERROR:   it appears that a &lt;sidebyside&gt; has a @margins attribute with three or more values (\"<xsl:value-of select=\"@margins\" />\").  There should be at most two values (a left margin and a right margin).  Results may be unpredictable.</xsl:message>\n        <xsl:apply-templates select=\".\" mode=\"location-report\" />\n    </xsl:if>\n    <xsl:if test=\"(substring-before($left-margin, '%') &lt; 0) or (substring-before($left-margin, '%') &gt; 100)\">\n        <xsl:message>PTX:ERROR:   left margin of a &lt;sidebyside&gt; (\"<xsl:value-of select=\"$left-margin\" />\") is outside the interval [0%, 100%], (this may be computed, check consistency of \"@margins\" and \"@widths\")</xsl:message>\n        <xsl:apply-templates select=\".\" mode=\"location-report\" />\n    </xsl:if>\n    <xsl:if test=\"(substring-before($right-margin, '%') &lt; 0) or (substring-before($right-margin, '%') &gt; 100)\">\n        <xsl:message>PTX:ERROR:   right margin of a &lt;sidebyside&gt; (\"<xsl:value-of select=\"$right-margin\" />\") is outside the interval [0%, 100%], (this may be computed, check consistency of \"@margins\" and \"@widths\")</xsl:message>\n        <xsl:apply-templates select=\".\" mode=\"location-report\" />\n    </xsl:if>\n    <!-- Add to RTF -->\n    <left-margin>\n        <xsl:value-of select=\"$left-margin\" />\n    </left-margin>\n    <right-margin>\n        <xsl:value-of select=\"$right-margin\" />\n    </right-margin>\n\n    <!-- if no widths given, distribute excess beyond margins -->\n    <!-- NB: with percent signs, blank at end always          -->\n    <!-- Error-check as $widths string gets depleted below    -->\n    <xsl:variable name=\"widths\">\n        <xsl:choose>\n            <xsl:when test=\"$normalized-widths = ' '\">\n                <xsl:variable name=\"common-width\" select=\"(100 - substring-before($left-margin, '%') - substring-before($right-margin, '%')) div $number-panels\" />\n                <!-- transfer as percentages (abstract), with blank at end -->\n                <xsl:call-template name=\"duplicate-string\">\n                     <xsl:with-param name=\"text\" select=\"concat($common-width, '% ')\" />\n                     <xsl:with-param name=\"count\" select=\"$number-panels\" />\n                 </xsl:call-template>\n             </xsl:when>\n             <xsl:otherwise>\n                <xsl:value-of select=\"$normalized-widths\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:if test=\"$sbsdebug\">\n        <xsl:message>PTX:DEBUG: W:<xsl:value-of select=\"$widths\" />:W</xsl:message>\n    </xsl:if>\n    <!-- check length (author-supplied could be wrong) -->\n    <xsl:variable name=\"nspaces-widths\" select=\"string-length($widths) - string-length(translate($widths, ' ', ''))\" />\n    <xsl:choose>\n        <xsl:when test=\"$nspaces-widths &lt; $number-panels\">\n            <xsl:message>PTX:FATAL:   a &lt;sidebyside&gt; or &lt;sbsgroup&gt; does not have enough \"@widths\" (maybe you did not specify enough?)</xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\" />\n            <xsl:message terminate=\"yes\">PTX:FATAL:   Quitting...</xsl:message>\n        </xsl:when>\n        <xsl:when test=\"$nspaces-widths &gt; $number-panels\">\n            <xsl:message>PTX:WARNING: a &lt;sidebyside&gt; or &lt;sbsgroup&gt; has extra \"@widths\" (did you confuse singular and plural attribute names?)</xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\" />\n        </xsl:when>\n    </xsl:choose>\n    <!-- unpack with an error-check on attribute values -->\n    <!-- RTF formation happens with unpacking           -->\n    <xsl:call-template name=\"decompose-widths\">\n        <xsl:with-param name=\"widths\" select=\"$widths\" />\n    </xsl:call-template>\n\n    <!-- Spacing Between Panels -->\n    <!-- compute common spacing between panels, as percent -->\n    <!-- subtract margins and sum-widths from 100,         -->\n    <!-- and then distribute to n - 1 spaces               -->\n    <!-- includes % for external use                       -->\n    <xsl:variable name=\"space-width\">\n        <xsl:choose>\n            <xsl:when test=\"$number-panels &lt; 2\">\n                <!-- no spaces, avoids all division by zero -->\n                <xsl:text>0</xsl:text>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"(100 - $sum-widths  - substring-before($left-margin, '%') - substring-before($right-margin, '%')) div ($number-panels - 1)\" />\n            </xsl:otherwise>\n        </xsl:choose>\n        <xsl:text>%</xsl:text>\n    </xsl:variable>\n    <xsl:if test=\"$sbsdebug\">\n        <xsl:message>PTX:DEBUG: SW:<xsl:value-of select=\"$space-width\" />:SW</xsl:message>\n    </xsl:if>\n    <!-- overall error check on space width -->\n    <xsl:choose>\n        <xsl:when test=\"substring-before($space-width, '%') &lt; 0\">\n            <xsl:message>PTX:ERROR:   computed space between panels of a &lt;sidebyside&gt; (\"<xsl:value-of select=\"$space-width\" />\") is negative (this value is computed, check consistency of \"@margins\" and \"@widths\")</xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\" />\n        </xsl:when>\n        <xsl:when test=\"substring-before($space-width, '%') = 'NaN'\">\n            <xsl:message>PTX:ERROR:   computed space between panels of a &lt;sidebyside&gt; is not a number (this value is computed, check that margins (\"<xsl:value-of select=\"$left-margin\" />, <xsl:value-of select=\"$right-margin\" />\") and widths (\"<xsl:value-of select=\"$widths\" />\") are percentages of the form \"nn%\")</xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\" />\n        </xsl:when>\n    </xsl:choose>\n    <!-- Add to RTF -->\n    <space-width>\n        <xsl:value-of select=\"$space-width\" />\n    </space-width>\n</xsl:template>\n\n<!-- ########################### -->\n<!-- SidebySide Layout Utilities -->\n<!-- ########################### -->\n\n<!-- From a space-separated list of vertical alignments       -->\n<!-- create a result tree fragment.  The schema enforces      -->\n<!-- \"top\" | \"middle\" | \"bottom\" on each list item, so no     -->\n<!-- defensive value check is needed here.                    -->\n<xsl:template name=\"decompose-valigns\">\n    <xsl:param name=\"valigns\" />\n    <xsl:variable name=\"the-valign\" select=\"substring-before($valigns, ' ')\" />\n    <xsl:if test=\"not($the-valign = '')\">\n        <valign>\n            <xsl:value-of select=\"$the-valign\" />\n        </valign>\n        <!-- recurse on trailing -->\n        <xsl:call-template name=\"decompose-valigns\">\n            <xsl:with-param name=\"valigns\" select=\"substring-after($valigns, ' ')\" />\n        </xsl:call-template>\n    </xsl:if>\n</xsl:template>\n\n<!-- From a space-separated list of widths (percentages) -->\n<!-- create error-checked result tree fragment           -->\n<xsl:template name=\"decompose-widths\">\n    <xsl:param name=\"widths\" />\n    <xsl:variable name=\"the-width\" select=\"substring-before($widths, ' ')\" />\n    <xsl:if test=\"not($the-width = '')\">\n        <!-- error-check, since author-supplied could be wild -->\n        <xsl:choose>\n            <xsl:when test=\"substring-before($the-width, '%') &lt; 0\">\n                <xsl:message>PTX:ERROR:   panel width (\"<xsl:value-of select=\"$the-width\" />\") in a &lt;sidebyside&gt; or &lt;sbsgroup&gt; is negative (this may be computed, check \"@margin(s)\" and \"@width(s)\")</xsl:message>\n                <xsl:apply-templates select=\".\" mode=\"location-report\" />\n            </xsl:when>\n            <xsl:when test=\"substring-before($the-width, '%') &gt; 100\">\n                <xsl:message>PTX:ERROR:   panel width (\"<xsl:value-of select=\"$the-width\" />\") in a &lt;sidebyside&gt; or &lt;sbsgroup&gt; is bigger than 100% (this may be computed, check \"@margin(s)\" and \"@width(s)\")</xsl:message>\n                <xsl:apply-templates select=\".\" mode=\"location-report\" />\n            </xsl:when>\n        </xsl:choose>\n        <!-- output element -->\n        <width>\n            <xsl:value-of select=\"$the-width\" />\n        </width>\n        <!-- recurse on trailing -->\n        <xsl:call-template name=\"decompose-widths\">\n            <xsl:with-param name=\"widths\" select=\"substring-after($widths, ' ')\" />\n        </xsl:call-template>\n    </xsl:if>\n</xsl:template>\n\n<!-- recursive template to sum percentages         -->\n<!-- input: a space-separated list, with %'s'      -->\n<!-- NB: expect trailing space as sentinel for end -->\n<!-- Output: total, without %, -common use only    -->\n<xsl:template name=\"sum-percentages\">\n    <xsl:param name=\"percent-list\" />\n    <xsl:param name=\"sum\" />\n    <xsl:choose>\n        <xsl:when test=\"$percent-list = ''\">\n            <xsl:value-of select=\"$sum\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:call-template name=\"sum-percentages\">\n                <xsl:with-param name=\"percent-list\" select=\"substring-after($percent-list, ' ')\" />\n                <xsl:with-param name=\"sum\" select=\"$sum + substring-before($percent-list, '%')\" />\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- ######################## -->\n<!-- SideBySide Main Template -->\n<!-- ######################## -->\n\n<!-- Panels are converted first, each through the modal             -->\n<!-- \"panel-panel\" template, and the results accumulate into a      -->\n<!-- single result-tree fragment.  That fragment, plus the computed -->\n<!-- layout, goes to the modal \"compose-panels\" template, which can -->\n<!-- wrap the finished panels but cannot place structure between    -->\n<!-- them.  The \"panel-panel\" parameters are the union of what the  -->\n<!-- implementations need, so any one implementation may ignore     -->\n<!-- some of them.  This two-phase contract fits a conversion whose -->\n<!-- target expresses the entire layout declaratively on a          -->\n<!-- container: HTML (CSS grid on a wrapping div; EPUB and Jupyter  -->\n<!-- inherit), LaTeX (arguments of the \"sidebyside\" environment;    -->\n<!-- Beamer and the solution manual inherit), and Reveal.js (CSS    -->\n<!-- table display).  A target that must interleave structure among -->\n<!-- the panels (XSL-FO: margin and gap table cells) or that has no -->\n<!-- horizontal layout at all (text, and Markdown by import;        -->\n<!-- braille) instead overrides this template entirely and reuses   -->\n<!-- the \"layout-parameters\" computation where meaningful; each     -->\n<!-- such stylesheet documents its reasons.  The panel vocabulary   -->\n<!-- is context-dependent beyond what the schema expresses: an      -->\n<!-- \"exercise\" panel only within a \"worksheet\" or \"handout\", a     -->\n<!-- \"slate\" panel only within an \"interactive\", and never an       -->\n<!-- \"audio\", \"video\", or \"interactive\", whose static               -->\n<!-- representation is itself a manufactured \"sidebyside\", which    -->\n<!-- must not nest.  The validation-plus stylesheet enforces all    -->\n<!-- three restrictions.                                            -->\n\n<xsl:template match=\"sidebyside\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:variable name=\"rtf-layout\">\n        <xsl:apply-templates select=\".\" mode=\"layout-parameters\" />\n    </xsl:variable>\n    <xsl:variable name=\"layout\" select=\"exsl:node-set($rtf-layout)\" />\n\n    <!-- local names of objects? -->\n    <!-- below useful for debugging, worth keeping for a while, 2017-07 -->\n    <!--\n    <xsl:message>N:<xsl:value-of select=\"$layout/number-panels\" />:N</xsl:message>\n    <xsl:message>\n        <xsl:text>VA:</xsl:text>\n        <xsl:for-each select=\"$layout/valign\">\n            <xsl:value-of select=\".\" />\n            <xsl:text> </xsl:text>\n        </xsl:for-each>\n        <xsl:text>:VA</xsl:text>\n    </xsl:message>\n    <xsl:message>\n        <xsl:text>W:</xsl:text>\n        <xsl:for-each select=\"$layout/width\">\n            <xsl:value-of select=\".\" />\n            <xsl:text> </xsl:text>\n        </xsl:for-each>\n        <xsl:text>:W</xsl:text>\n    </xsl:message>\n    <xsl:message>\n        <xsl:text>M:</xsl:text>\n        <xsl:value-of select=\"$layout/margins\" />\n        <xsl:text>:M</xsl:text>\n    </xsl:message>\n    <xsl:message>\n        <xsl:text>SW:</xsl:text>\n        <xsl:value-of select=\"$layout/space-width\" />\n        <xsl:text>:SW</xsl:text>\n    </xsl:message>\n    <xsl:message>~~~~~~~~~~~~~~~~~~~~</xsl:message>\n     -->\n\n    <xsl:variable name=\"panels\" select=\"&SBSPANEL;\" />\n\n    <!-- TODO: Instead we could pass the $layout to \"panel-panel\",  -->\n    <!-- and infer the $panel-number in the receiving templates.    -->\n\n    <xsl:variable name=\"panel-panels\">\n        <xsl:for-each select=\"$panels\">\n            <!-- context is now a particular panel -->\n            <xsl:variable name=\"panel-number\" select=\"count(preceding-sibling::*) + 1\" />\n            <xsl:apply-templates select=\".\" mode=\"panel-panel\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                <xsl:with-param name=\"width\" select=\"$layout/width[$panel-number]\" />\n                <xsl:with-param name=\"left-margin\" select=\"$layout/left-margin\" />\n                <xsl:with-param name=\"right-margin\" select=\"$layout/right-margin\" />\n                <xsl:with-param name=\"valign\" select=\"$layout/valign[$panel-number]\" />\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:for-each>\n    </xsl:variable>\n\n    <xsl:apply-templates select=\".\" mode=\"pre-sidebyside\"/>\n    <!-- now collect components into output wrappers -->\n    <xsl:apply-templates select=\".\" mode=\"compose-panels\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n\n        <xsl:with-param name=\"layout\" select=\"$layout\" />\n        <xsl:with-param name=\"panels\" select=\"$panel-panels\" />\n    </xsl:apply-templates>\n    <xsl:apply-templates select=\".\" mode=\"post-sidebyside\"/>\n</xsl:template>\n\n<!-- ########################################### -->\n<!-- Side-By-Side Group (sbsgroup) main template -->\n<!-- ########################################### -->\n\n<!-- A side-by-side group (\"sbsgroup\") is a wrapper    -->\n<!-- around a sequence of \"sidebyside\".  It provides   -->\n<!-- a place to specify common parameters for several  -->\n<!-- side-by-side, for uniformity.  Also sub-captions  -->\n<!-- should respect the grouping.  It is as pure a     -->\n<!-- container as there can be.  Output is to just     -->\n<!-- pile them up vertically.  Note, layout parameters -->\n<!-- on enclosed \"sidebyside\" take precedence, and     -->\n<!-- it is the layout template for each sidebyside     -->\n<!-- that goes out to the enclosing group to get them  -->\n\n<!-- default wrapper does nothing, output modes may    -->\n<!-- optionally provide some containing structure      -->\n<xsl:template name=\"sbsgroup-wrapper\">\n    <xsl:param name=\"sbsgroup-content\"/>\n    <xsl:copy-of select=\"$sbsgroup-content\"/>\n</xsl:template>\n\n<xsl:template match=\"sbsgroup\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:variable name=\"data\">\n        <xsl:apply-templates select=\".\" mode=\"pre-sbsgroup\"/>\n        <xsl:apply-templates select=\"sidebyside\">\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n        <xsl:apply-templates select=\".\" mode=\"post-sbsgroup\"/>\n    </xsl:variable>\n    <xsl:call-template name=\"sbsgroup-wrapper\">\n        <xsl:with-param name=\"sbsgroup-content\" select=\"$data\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- Since stackable items do not carry titles or captions,   -->\n<!-- their templates do the right thing.  Items that normally -->\n<!-- could go nline within a paragraph without any spacing    -->\n<!-- will be preceded by a \\par in their LaTeX representation -->\n<!-- to get them onto a line of their own                     -->\n<!-- 2019-06-28: parameters only consumed by HTML templates   -->\n<xsl:template match=\"sidebyside/stack\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"width\" />\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:apply-templates select=\"&STACKABLE;\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n        <xsl:with-param name=\"width\" select=\"$width\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- ################# -->\n<!-- Post-Layout Hooks -->\n<!-- ################# -->\n\n<!-- We may wish to add information above or below a \"sidebyside\"  -->\n<!-- or a \"sbsgroup\".  Motivation is keyboard shortcut help for    -->\n<!-- interactive accessible diagrams out of PreFigure code with    -->\n<!-- the diagcess JS library.  See invocations above, with no-op   -->\n<!-- stubs here. -->\n\n<xsl:template match=\"sidebyside\" mode=\"pre-sidebyside\"/>\n<xsl:template match=\"sbsgroup\" mode=\"pre-sbsgroup\"/>\n<xsl:template match=\"sidebyside\" mode=\"post-sidebyside\"/>\n<xsl:template match=\"sbsgroup\" mode=\"post-sbsgroup\"/>\n\n<!-- ############## -->\n<!-- List Utilities -->\n<!-- ############## -->\n\n<!-- A list item may be:                                        -->\n<!--   * unstructured, like a sentence of a \"p\"                 -->\n<!--   * structured into paragraphs, sublists, etc.             -->\n<!-- For the first, we cannot automatically strip space         -->\n<!-- To be flexible about the second, we kill interstitial text -->\n<xsl:template match=\"li[p|ol|ul|dl]/text()\">\n    <xsl:variable name=\"text\" select=\"normalize-space(.)\" />\n    <xsl:if test=\"$text\">\n        <xsl:message>PTX:ERROR:   Unstructured content within a list item is being ignored (\"<xsl:value-of select=\"$text\" />\")</xsl:message>\n         <xsl:apply-templates select=\"..\" mode=\"location-report\" />\n    </xsl:if>\n</xsl:template>\n\n<!-- List Levels -->\n<!-- Utility templates to determine the depth      -->\n<!-- of a list, relative to nesting in other lists -->\n\n<!-- To indent properly in markdown, we  -->\n<!-- need to count every type of list    -->\n<xsl:template match=\"*\" mode=\"list-level\">\n    <xsl:param name=\"level\" select=\"0\" />\n    <xsl:choose>\n        <xsl:when test=\"ancestor-or-self::ol or ancestor-or-self::ul or ancestor-or-self::dl\">\n            <xsl:choose>\n                <!-- at a node to count -->\n                <xsl:when test=\"self::ol or self::ul or self::dl\">\n                    <xsl:apply-templates select=\"parent::*\" mode=\"list-level\">\n                        <xsl:with-param name=\"level\" select=\"$level + 1\" />\n                    </xsl:apply-templates>\n                </xsl:when>\n                <!-- go up a level w/out incrementing-->\n                <xsl:otherwise>\n                    <xsl:apply-templates select=\"parent::*\" mode=\"list-level\">\n                        <xsl:with-param name=\"level\" select=\"$level\" />\n                    </xsl:apply-templates>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- now done, report level -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$level\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- CSS class for multi-column lists.  Context is an element with -->\n<!-- a potential \"cols\" attribute.  Return value is \"colsN\" with   -->\n<!-- 2 <= N <= 6, or empty when @cols is absent.                   -->\n<!-- Schema enforces @cols to be one of \"2\", \"3\", \"4\", \"5\", \"6\"    -->\n<!-- on each of \"ol\", \"ul\", and \"exercisegroup\" (and on the        -->\n<!-- variant of \"ol\" used inside exercise statements), so this     -->\n<!-- template just emits the class string whenever @cols is        -->\n<!-- present.                                                      -->\n<xsl:template match=\"ol|ul|exercisegroup\" mode=\"number-cols-CSS-class\">\n    <xsl:if test=\"@cols\">\n        <xsl:text>cols</xsl:text>\n        <xsl:value-of select=\"@cols\" />\n        <xsl:text> multicolumn</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<!-- ################## -->\n<!-- Exercise Utilities -->\n<!-- ################## -->\n\n<!-- Exercises, projects and tasks, generally have \"statement\",    -->\n<!-- \"hint\", \"answer\", and \"solution\".  Switches control           -->\n<!-- appearance in the main matter and in solution lists.          -->\n<!--                                                               -->\n<!-- But they are surrounded by infrastructure:  number and title, -->\n<!-- exercise group with introduction and conclusion, division     -->\n<!-- headings.  If switches make all the content disappear within  -->\n<!-- some infrastructure, then the infrastructure becomes          -->\n<!-- superfluous.  So we provide a hierarchy of templates to       -->\n<!-- determine if structure and content yield output.              -->\n\n<!-- Bottom-up, a \"traditional\" exercise is clearest, so first.   -->\n<!-- Strategy is to produce non-empty output if the item would    -->\n<!-- normally produce some *real* output.                         -->\n\n<!-- \"exercise\", not WeBWorK or MyOpenMath, plus project-like. -->\n<!-- Easiest to switch on structured by task, or simpler       -->\n<!-- \"traditional\" exercise.                                   -->\n\n<xsl:template match=\"exercise[not(webwork-reps or myopenmath)]|&PROJECT-LIKE;\" mode=\"dry-run\">\n    <xsl:param name=\"admit\"/>\n    <xsl:param name=\"b-has-statement\" />\n    <xsl:param name=\"b-has-hint\" />\n    <xsl:param name=\"b-has-answer\" />\n    <xsl:param name=\"b-has-solution\" />\n\n    <xsl:variable name=\"admitted\">\n        <xsl:apply-templates select=\".\" mode=\"determine-admission\">\n            <xsl:with-param name=\"admit\" select=\"$admit\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <xsl:variable name=\"b-admitted\" select=\"boolean($admitted = 'yes')\"/>\n\n    <xsl:choose>\n        <!-- return nothing if not admitted -->\n        <xsl:when test=\"not($b-admitted)\"/>\n        <!-- recurse down into \"task\" via two templates above -->\n        <xsl:when test=\"task\">\n            <xsl:apply-templates select=\"task\" mode=\"dry-run\">\n                <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\" />\n                <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-hint\" />\n                <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-answer\" />\n                <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-solution\" />\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- simple \"traditional\" exercise -->\n        <xsl:otherwise>\n            <xsl:if test=\"$b-has-statement or ($b-has-hint and hint) or ($b-has-answer and answer) or ($b-has-solution and solution)\">\n                <xsl:text>X</xsl:text>\n            </xsl:if>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- We explicitly burrow down into tasks, since when we produce -->\n<!-- the solutions, the labels on the tasks are infrastructure   -->\n<!-- and we need the precision of knowing just which \"task\"      -->\n<!-- harbor solutions (and which do not).                        -->\n\n<!-- terminal (leaf) tasks -->\n<xsl:template match=\"task[not(task)]\" mode=\"dry-run\">\n    <xsl:param name=\"b-has-statement\" />\n    <xsl:param name=\"b-has-hint\" />\n    <xsl:param name=\"b-has-answer\" />\n    <xsl:param name=\"b-has-solution\" />\n\n    <xsl:if test=\"$b-has-statement or ($b-has-hint and hint) or ($b-has-answer and answer) or ($b-has-solution and solution)\">\n        <xsl:text>X</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<!-- Simply pass through intermediate task since they  -->\n<!-- cannot harbor solutions (says schema) -->\n<xsl:template match=\"task[task]\" mode=\"dry-run\">\n    <xsl:param name=\"b-has-statement\" />\n    <xsl:param name=\"b-has-hint\" />\n    <xsl:param name=\"b-has-answer\" />\n    <xsl:param name=\"b-has-solution\" />\n\n    <xsl:apply-templates select=\"task\" mode=\"dry-run\">\n        <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\" />\n        <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-hint\" />\n        <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-answer\" />\n        <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-solution\" />\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- WeBWorK are exceptional.  We use the \"webwork-reps\" element -->\n<!-- added by the assembly routine to examine \"static\" for the   -->\n<!-- indication of existence of solutions - even if the problem  -->\n <!-- is \"live\" in interactive output.  Note that \"stage\" is     -->\n <!-- similar to \"task\" above, we need to carefully burrow down  -->\n <!-- into them to get indications of infrastructure when        -->\n <!-- producing output.                                          -->\n\n<!-- WeBWorK exercise, structured by stages or not -->\n<xsl:template match=\"exercise[webwork-reps]\" mode=\"dry-run\">\n    <xsl:param name=\"admit\"/>\n    <xsl:param name=\"b-has-statement\" />\n    <xsl:param name=\"b-has-hint\" />\n    <xsl:param name=\"b-has-answer\" />\n    <xsl:param name=\"b-has-solution\" />\n\n    <xsl:variable name=\"admitted\">\n        <xsl:apply-templates select=\".\" mode=\"determine-admission\">\n            <xsl:with-param name=\"admit\" select=\"$admit\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <xsl:variable name=\"b-admitted\" select=\"boolean($admitted = 'yes')\"/>\n\n    <xsl:choose>\n        <!-- return nothing if not admitted -->\n        <xsl:when test=\"not($b-admitted)\"/>\n        <xsl:when test=\"webwork-reps/static/task|webwork-reps/static/stage\">\n            <xsl:apply-templates select=\"webwork-reps/static/task|webwork-reps/static/stage\" mode=\"dry-run\">\n                <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\" />\n                <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-hint\" />\n                <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-answer\" />\n                <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-solution\" />\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:if test=\"$b-has-statement or ($b-has-hint and webwork-reps/static/hint) or ($b-has-answer and webwork-reps/static/answer) or ($b-has-solution and webwork-reps/static/solution)\">\n                <xsl:text>X</xsl:text>\n            </xsl:if>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- webwork stage is like a problem by itself-->\n<xsl:template match=\"exercise/webwork-reps/static/stage\" mode=\"dry-run\">\n    <xsl:param name=\"b-has-statement\" />\n    <xsl:param name=\"b-has-hint\" />\n    <xsl:param name=\"b-has-answer\" />\n    <xsl:param name=\"b-has-solution\" />\n\n    <xsl:if test=\"$b-has-statement or ($b-has-hint and hint) or ($b-has-answer and answer) or ($b-has-solution and solution)\">\n        <xsl:text>X</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<!-- 2020-08-31: MyOpenMath is not really implemented fully, this is a -->\n<!-- marker that will just prevent thse problems from appearing at all -->\n<xsl:template match=\"exercise[myopenmath]\" mode=\"dry-run\"/>\n\n\n<!-- Now we can tell is a given exercise (or project-like) will -->\n<!-- generate some solutions, relative to the various switches  -->\n<!-- in play.  So we now decide if various bits of surrounding  -->\n<!-- infrastructure need repeating, since they do, or do not,   -->\n<!-- contain exercises which will produce solutions.            -->\n\n\n<!-- An \"exercisegroup\" potentially has an \"introduction\"  -->\n<!-- and \"conclusion\" as infrastructure, and can only      -->\n<!-- contain divisional \"exercise\" as varying items        -->\n<!-- In a way, this is like an \"exercise\", it has content  -->\n<!-- that is like a \"statement\", so a \"dry-run\" is checked -->\n<!-- before outputting its introduction/conclusion         -->\n<xsl:template match=\"exercisegroup\" mode=\"dry-run\">\n    <xsl:param name=\"admit\"/>\n    <xsl:param name=\"b-has-statement\" />\n    <xsl:param name=\"b-has-hint\" />\n    <xsl:param name=\"b-has-answer\" />\n    <xsl:param name=\"b-has-solution\" />\n\n    <xsl:apply-templates select=\"exercise\" mode=\"dry-run\">\n        <xsl:with-param name=\"admit\"           select=\"$admit\"/>\n        <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\" />\n        <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-hint\" />\n        <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-answer\" />\n        <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-solution\" />\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- A \"subexercises\" potentially has an \"introduction\"    -->\n<!-- and \"conclusion\" as infrastructure, and can only      -->\n<!-- contain divisional \"exercise\" as varying items        -->\n<!-- in addition to possible \"exercisegroup\"               -->\n<!-- In a way, this is like an \"exercisegroup\", it has     -->\n<!-- content that is like a \"statement\", so a \"dry-run\" is -->\n<!-- checked before outputting its introduction/conclusion -->\n<xsl:template match=\"subexercises\" mode=\"dry-run\">\n    <xsl:param name=\"admit\"/>\n    <xsl:param name=\"b-has-statement\" />\n    <xsl:param name=\"b-has-hint\" />\n    <xsl:param name=\"b-has-answer\" />\n    <xsl:param name=\"b-has-solution\" />\n\n    <xsl:apply-templates select=\"exercise|exercisegroup\" mode=\"dry-run\">\n        <xsl:with-param name=\"admit\"           select=\"$admit\"/>\n        <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\" />\n        <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-hint\" />\n        <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-answer\" />\n        <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-solution\" />\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Now specialized divisions that can hold \"exercise\".  These      -->\n<!-- typically receive many parameters (~20) but only react/consider -->\n<!-- the ones relevant to the type of division being investigated.   -->\n\n<xsl:template match=\"exercises\" mode=\"dry-run\">\n    <xsl:param name=\"admit\"/>\n    <xsl:param name=\"component-spec\"/>\n\n    <xsl:variable name=\"divisional-components\">\n        <xsl:call-template name=\"solutions-components\">\n            <xsl:with-param name=\"component-spec\" select=\"$component-spec\"/>\n            <xsl:with-param name=\"category\" select=\"'divisional'\"/>\n        </xsl:call-template>\n    </xsl:variable>\n    <xsl:apply-templates select=\".//exercise\" mode=\"dry-run\">\n        <xsl:with-param name=\"admit\"           select=\"$admit\"/>\n        <xsl:with-param name=\"b-has-statement\" select=\"contains($divisional-components, 'statement')\" />\n        <xsl:with-param name=\"b-has-hint\"      select=\"contains($divisional-components, 'hint')\" />\n        <xsl:with-param name=\"b-has-answer\"    select=\"contains($divisional-components, 'answer')\" />\n        <xsl:with-param name=\"b-has-solution\"  select=\"contains($divisional-components, 'solution')\" />\n    </xsl:apply-templates>\n</xsl:template>\n\n<xsl:template match=\"worksheet\" mode=\"dry-run\">\n    <xsl:param name=\"admit\"/>\n    <xsl:param name=\"component-spec\"/>\n\n    <xsl:variable name=\"worksheet-components\">\n        <xsl:call-template name=\"solutions-components\">\n            <xsl:with-param name=\"component-spec\" select=\"$component-spec\"/>\n            <xsl:with-param name=\"category\" select=\"'worksheet'\"/>\n        </xsl:call-template>\n    </xsl:variable>\n    <xsl:variable name=\"project-components\">\n        <xsl:call-template name=\"solutions-components\">\n            <xsl:with-param name=\"component-spec\" select=\"$component-spec\"/>\n            <xsl:with-param name=\"category\" select=\"'project'\"/>\n        </xsl:call-template>\n    </xsl:variable>\n    <xsl:apply-templates select=\".//exercise\" mode=\"dry-run\">\n        <xsl:with-param name=\"admit\"           select=\"$admit\"/>\n        <xsl:with-param name=\"b-has-statement\" select=\"contains($worksheet-components, 'statement')\" />\n        <xsl:with-param name=\"b-has-hint\"      select=\"contains($worksheet-components, 'hint')\" />\n        <xsl:with-param name=\"b-has-answer\"    select=\"contains($worksheet-components, 'answer')\" />\n        <xsl:with-param name=\"b-has-solution\"  select=\"contains($worksheet-components, 'solution')\" />\n    </xsl:apply-templates>\n    <xsl:apply-templates select=\".//activity|.//exploration|.//investigation|.//project\" mode=\"dry-run\">\n        <xsl:with-param name=\"admit\"           select=\"$admit\"/>\n        <xsl:with-param name=\"b-has-statement\" select=\"contains($project-components, 'statement')\" />\n        <xsl:with-param name=\"b-has-hint\"      select=\"contains($project-components, 'hint')\" />\n        <xsl:with-param name=\"b-has-answer\"    select=\"contains($project-components, 'answer')\" />\n        <xsl:with-param name=\"b-has-solution\"  select=\"contains($project-components, 'solution')\" />\n    </xsl:apply-templates>\n\n</xsl:template>\n\n<xsl:template match=\"reading-questions\" mode=\"dry-run\">\n    <xsl:param name=\"admit\"/>\n    <xsl:param name=\"component-spec\"/>\n\n    <xsl:variable name=\"reading-components\">\n        <xsl:call-template name=\"solutions-components\">\n            <xsl:with-param name=\"component-spec\" select=\"$component-spec\"/>\n            <xsl:with-param name=\"category\" select=\"'reading'\"/>\n        </xsl:call-template>\n    </xsl:variable>\n    <xsl:apply-templates select=\"exercise\" mode=\"dry-run\">\n        <xsl:with-param name=\"admit\"           select=\"$admit\"/>\n        <xsl:with-param name=\"b-has-statement\" select=\"contains($reading-components, 'statement')\" />\n        <xsl:with-param name=\"b-has-hint\"      select=\"contains($reading-components, 'hint')\" />\n        <xsl:with-param name=\"b-has-answer\"    select=\"contains($reading-components, 'answer')\" />\n        <xsl:with-param name=\"b-has-solution\"  select=\"contains($reading-components, 'solution')\" />\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- An arbitrary division will have a heading as infrastructure.     -->\n<!-- We drill down into the division at any depth looking for objects -->\n<!-- based on the switches that control them.  This means we do not   -->\n<!-- have to examine all possible subdivisions, both traditional      -->\n<!-- and specialized.  Instead, we just pass through them.  But we do -->\n<!-- need to be careful about sort of division is being considered    -->\n<!-- and what switches are passed along.                              -->\n<xsl:template match=\"part|chapter|section|subsection|subsubsection\" mode=\"dry-run\">\n    <xsl:param name=\"admit\"/>\n    <xsl:param name=\"component-spec\"/>\n\n    <xsl:variable name=\"inline-components\">\n        <xsl:call-template name=\"solutions-components\">\n            <xsl:with-param name=\"component-spec\" select=\"$component-spec\"/>\n            <xsl:with-param name=\"category\" select=\"'inline'\"/>\n        </xsl:call-template>\n    </xsl:variable>\n    <xsl:variable name=\"divisional-components\">\n        <xsl:call-template name=\"solutions-components\">\n            <xsl:with-param name=\"component-spec\" select=\"$component-spec\"/>\n            <xsl:with-param name=\"category\" select=\"'divisional'\"/>\n        </xsl:call-template>\n    </xsl:variable>\n    <xsl:variable name=\"worksheet-components\">\n        <xsl:call-template name=\"solutions-components\">\n            <xsl:with-param name=\"component-spec\" select=\"$component-spec\"/>\n            <xsl:with-param name=\"category\" select=\"'worksheet'\"/>\n        </xsl:call-template>\n    </xsl:variable>\n    <xsl:variable name=\"reading-components\">\n        <xsl:call-template name=\"solutions-components\">\n            <xsl:with-param name=\"component-spec\" select=\"$component-spec\"/>\n            <xsl:with-param name=\"category\" select=\"'reading'\"/>\n        </xsl:call-template>\n    </xsl:variable>\n    <xsl:variable name=\"project-components\">\n        <xsl:call-template name=\"solutions-components\">\n            <xsl:with-param name=\"component-spec\" select=\"$component-spec\"/>\n            <xsl:with-param name=\"category\" select=\"'project'\"/>\n        </xsl:call-template>\n    </xsl:variable>\n    <xsl:apply-templates select=\".//exercise[boolean(&INLINE-EXERCISE-FILTER;)]\" mode=\"dry-run\">\n        <xsl:with-param name=\"admit\"           select=\"$admit\"/>\n        <xsl:with-param name=\"b-has-statement\" select=\"contains($inline-components, 'statement')\" />\n        <xsl:with-param name=\"b-has-hint\"      select=\"contains($inline-components, 'hint')\" />\n        <xsl:with-param name=\"b-has-answer\"    select=\"contains($inline-components, 'answer')\" />\n        <xsl:with-param name=\"b-has-solution\"  select=\"contains($inline-components, 'solution')\" />\n    </xsl:apply-templates>\n    <xsl:apply-templates select=\".//exercises//exercise\" mode=\"dry-run\">\n        <xsl:with-param name=\"admit\"           select=\"$admit\"/>\n        <xsl:with-param name=\"b-has-statement\" select=\"contains($divisional-components, 'statement')\" />\n        <xsl:with-param name=\"b-has-hint\"      select=\"contains($divisional-components, 'hint')\" />\n        <xsl:with-param name=\"b-has-answer\"    select=\"contains($divisional-components, 'answer')\" />\n        <xsl:with-param name=\"b-has-solution\"  select=\"contains($divisional-components, 'solution')\" />\n    </xsl:apply-templates>\n    <xsl:apply-templates select=\".//worksheet//exercise\" mode=\"dry-run\">\n        <xsl:with-param name=\"admit\"           select=\"$admit\"/>\n        <xsl:with-param name=\"b-has-statement\" select=\"contains($worksheet-components, 'statement')\" />\n        <xsl:with-param name=\"b-has-hint\"      select=\"contains($worksheet-components, 'hint')\" />\n        <xsl:with-param name=\"b-has-answer\"    select=\"contains($worksheet-components, 'answer')\" />\n        <xsl:with-param name=\"b-has-solution\"  select=\"contains($worksheet-components, 'solution')\" />\n    </xsl:apply-templates>\n    <xsl:apply-templates select=\".//reading-questions//exercise\" mode=\"dry-run\">\n        <xsl:with-param name=\"admit\"           select=\"$admit\"/>\n        <xsl:with-param name=\"b-has-statement\" select=\"contains($reading-components, 'statement')\" />\n        <xsl:with-param name=\"b-has-hint\"      select=\"contains($reading-components, 'hint')\" />\n        <xsl:with-param name=\"b-has-answer\"    select=\"contains($reading-components, 'answer')\" />\n        <xsl:with-param name=\"b-has-solution\"  select=\"contains($reading-components, 'solution')\" />\n    </xsl:apply-templates>\n    <!-- &PROJECT-LIKE; \"project|activity|exploration|investigation\"> -->\n    <xsl:apply-templates select=\".//project|.//activity|.//exploration|.//investigation\" mode=\"dry-run\">\n        <xsl:with-param name=\"admit\"           select=\"$admit\"/>\n        <xsl:with-param name=\"b-has-statement\" select=\"contains($project-components, 'statement')\" />\n        <xsl:with-param name=\"b-has-hint\"      select=\"contains($project-components, 'hint')\" />\n        <xsl:with-param name=\"b-has-answer\"    select=\"contains($project-components, 'answer')\" />\n        <xsl:with-param name=\"b-has-solution\"  select=\"contains($project-components, 'solution')\" />\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- If not explicitly addressed in another template, dry-run returns      -->\n<!-- empty. This is necessary when stacking headings in output from the    -->\n<!-- solutions generator.  The preceding siblings are examined, and it     -->\n<!-- may include elements that do not naturally does a dry-run inspection. -->\n<!-- This wildcard match could make debugging harder, perhaps reporting    -->\n<!-- the element from this template would be useful.                       -->\n<xsl:template match=\"*\" mode=\"dry-run\"/>\n\n<!-- A PROJECT-LIKE which is *not* already inside a printout, but which   -->\n<!-- requests workspace, is a printout in its own right: it is meant to be -->\n<!-- worked on paper, so each conversion gives it the treatment it gives   -->\n<!-- a worksheet.  In HTML that is a print preview icon, page margins, and -->\n<!-- workspace divs the preview javascript expands to fill pages; in       -->\n<!-- LaTeX it is a page of its own, with the worksheet margins.  Inside a  -->\n<!-- worksheet or handout there is nothing to do, since the enclosing      -->\n<!-- printout already provides all of this.                                -->\n<xsl:template match=\"*\" mode=\"is-standalone-printout\">\n    <xsl:value-of select=\"false()\"/>\n</xsl:template>\n\n<xsl:template match=\"&PROJECT-LIKE;\" mode=\"is-standalone-printout\">\n    <xsl:value-of select=\"boolean(not(ancestor::worksheet|ancestor::handout) and (@workspace|.//@workspace))\"/>\n</xsl:template>\n\n<!-- This template is called for items in a printout that can have a   -->\n<!-- workspace specified.  It is important that this sometimes returns -->\n<!-- an empty string, since that is a signal to not construct some     -->\n<!-- surrounding infrastructure to implement the necessary space.      -->\n<xsl:template match=\"*\" mode=\"sanitize-workspace\">\n    <!-- bail out quickly and empty if not on a printout     -->\n    <!-- bail out if at a \"task\" that is not a terminal task -->\n    <!-- we assume LaTeX will only request this template if  -->\n    <!-- the publisher file allows it.                       -->\n    <!-- NB: a blank workspace is used as a signal in \"divisionexercise\" -->\n    <!--     in LaTeX conversion, via parameter #3 of the  environment   -->\n\n    <xsl:if test=\"(ancestor::worksheet or ancestor::handout or ancestor-or-self::*[&PROJECT-FILTER;]) and not(child::task)\">\n        <!-- First element with @workspace, confined to the printout   -->\n        <!-- Could be empty node-set, which will be empty string later -->\n        <xsl:variable name=\"raw-workspace\">\n            <xsl:choose>\n                <!-- @workspace on the terminal task or exercise, if it has it. -->\n                <!-- NB can't have children tasks by conditional above. -->\n                <xsl:when test=\"self::task[@workspace] or self::exercise[@workspace]\">\n                    <xsl:value-of select=\"normalize-space(@workspace)\"/>\n                </xsl:when>\n                <!-- task/exercise w/out workspace but @workspace on the first ancestor with it, if any -->\n                <!-- This can happen for an exercise in an exercisegroup -->\n                <xsl:when test=\"(self::task or self::exercise) and ancestor::*[@workspace][1]\">\n                    <xsl:value-of select=\"normalize-space(ancestor::*[@workspace][1]/@workspace)\"/>\n                </xsl:when>\n                <!-- otherwise, @workspace on the element, if any -->\n                <xsl:otherwise>\n                    <xsl:value-of select=\"normalize-space(@workspace)\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:variable>\n        <xsl:choose>\n            <!-- bail out empty if empty or absent -->\n            <xsl:when test=\"$raw-workspace = ''\"/>\n            <!-- old-style fraction of a page, indicated by a % at end   -->\n            <!-- warn and convert to inches based on 10-inch page height -->\n            <!-- ( (percent div 100) * 10 inch = div 10 )                -->\n            <xsl:when test=\"substring($raw-workspace, string-length($raw-workspace) - 0) = '%'\">\n                <xsl:variable name=\"approximate-inches\" select=\"concat(substring($raw-workspace, 1, string-length($raw-workspace) - 1) div 10, 'in')\"/>\n                <xsl:value-of select=\"$approximate-inches\"/>\n                <xsl:message>PTX:FALLBACK:  as of 2020-03-17 worksheet exercises' workspace should be specified in 'in' or in 'cm'.  Approximating a page fraction of <xsl:value-of select=\"@workspace\"/> by <xsl:value-of select=\"$approximate-inches\"/>.</xsl:message>\n                <xsl:apply-templates select=\".\" mode=\"location-report\"/>\n            </xsl:when>\n            <xsl:when test=\"substring($raw-workspace, string-length($raw-workspace) - 1) = 'in'\">\n                <xsl:value-of select=\"$raw-workspace\"/>\n            </xsl:when>\n            <xsl:when test=\"substring($raw-workspace, string-length($raw-workspace) - 1) = 'cm'\">\n                <xsl:value-of select=\"$raw-workspace\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:message>PTX:FALLBACK:  a worksheet exercises', project-likes' or tasks' workspace should be specified with units of 'in' or 'cm', and not as \"<xsl:value-of select=\"@workspace\"/>\".  Using a default of \"2in\".</xsl:message>\n                <xsl:text>2in</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:if>\n</xsl:template>\n\n<!-- We have a restrictive match above on a modal template,            -->\n<!-- but it is employed with a wider variety of objects so we          -->\n<!-- need an implementation that does nothing                          -->\n<!-- We kill the worksheet @workspace option for WW exercises until    -->\n<!-- we have a better understanding of just how this will be specified -->\n<!-- A no-op, just remove to enable, but will need testing             -->\n<xsl:template match=\"webwork-reps/static|webwork-reps/static/stage|exercisegroup|&SOLUTION-LIKE;\" mode=\"sanitize-workspace\"/>\n\n\n<!-- Get an RTF element containing information about what components of an exercise -->\n<!-- should be rendered based on its type and publisher settings                    -->\n<xsl:template match=\"exercise|&PROJECT-LIKE;|task\" mode=\"exercise-components-report\">\n    <xsl:variable name=\"exercise-type\">\n        <xsl:choose>\n            <xsl:when test=\"self::task\">project</xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"./@pi:exercise-customization\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$exercise-type = 'inline'\">\n            <exercise-component-report has-hint=\"{$b-has-inline-hint}\" has-answer=\"{$b-has-inline-answer}\" has-solution=\"{$b-has-inline-solution}\"/>\n        </xsl:when>\n        <xsl:when test=\"$exercise-type = 'project'\">\n            <exercise-component-report has-hint=\"{$b-has-project-hint}\" has-answer=\"{$b-has-project-answer}\" has-solution=\"{$b-has-project-solution}\"/>\n        </xsl:when>\n        <xsl:when test=\"$exercise-type = 'divisional'\">\n            <exercise-component-report has-hint=\"{$b-has-divisional-hint}\" has-answer=\"{$b-has-divisional-answer}\" has-solution=\"{$b-has-divisional-solution}\"/>\n        </xsl:when>\n        <xsl:when test=\"$exercise-type = 'worksheet'\">\n            <exercise-component-report has-hint=\"{$b-has-worksheet-hint}\" has-answer=\"{$b-has-worksheet-answer}\" has-solution=\"{$b-has-worksheet-solution}\"/>\n        </xsl:when>\n        <xsl:when test=\"$exercise-type = 'reading'\">\n            <exercise-component-report has-hint=\"{$b-has-reading-hint}\" has-answer=\"{$b-has-reading-answer}\" has-solution=\"{$b-has-reading-solution}\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message>PTX:BUG:   can't determine exercise type</xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- ####################################### -->\n<!-- Solutions Divisions, Content Generation -->\n<!-- ####################################### -->\n\n<!-- A light wrapper around the \"solutions-generator\" template (next). -->\n<!-- We just examine the attributes describing a \"solutions\" division. -->\n<!-- The division is one-off (not knowled), so we treat the            -->\n<!-- introduction and conclusion as original                           -->\n<xsl:template match=\"solutions\" mode=\"solutions\">\n    <xsl:param name=\"heading-level\"/>\n\n    <!-- A \"solutions\" division may exist in the main matter  -->\n    <!-- or the back matter.  When we generate a solution, we -->\n    <!-- want to know which kind it is, so it can be labeled  -->\n    <!-- so that a forward-reference is accurate.             -->\n    <xsl:variable name=\"purpose\">\n        <xsl:choose>\n            <xsl:when test=\"parent::backmatter\">\n                <xsl:text>backmatter</xsl:text>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>mainmatter</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n\n    <!-- A \"solutions\" may have an @admit that indicates a subset -->\n    <!-- of which exercises to admit. The default is 'all'        -->\n    <xsl:variable name=\"admit\">\n        <xsl:choose>\n            <xsl:when test=\"@admit\">\n                <xsl:value-of select=\"@admit\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>all</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n\n    <!-- The five attributes describing which solution components    -->\n    <!-- are requested, packed into one string parameter.  See the   -->\n    <!-- \"solutions-component-spec\" template for the packing format. -->\n    <xsl:variable name=\"component-spec\">\n        <xsl:call-template name=\"solutions-component-spec\">\n            <xsl:with-param name=\"inline\"     select=\"@inline\"/>\n            <xsl:with-param name=\"divisional\" select=\"@divisional\"/>\n            <xsl:with-param name=\"worksheet\"  select=\"@worksheet\"/>\n            <xsl:with-param name=\"reading\"    select=\"@reading\"/>\n            <xsl:with-param name=\"project\"    select=\"@project\"/>\n        </xsl:call-template>\n    </xsl:variable>\n\n    <xsl:apply-templates select=\"introduction\">\n        <xsl:with-param name=\"b-original\" select=\"true()\" />\n    </xsl:apply-templates>\n\n    <xsl:if test=\"@scope\">\n        <!-- Check that the scope is reasonable, i.e. it exists and is -->\n        <!-- one of the elements defined for the \"solutions-generator\" -->\n        <!-- template                                                  -->\n        <xsl:variable name=\"scope\" select=\"id(@scope)\"/>\n        <xsl:if test=\"not($scope)\">\n            <xsl:message>PTX:ERROR:   unresolved @scope (\"<xsl:value-of select=\"@scope\"/>\") for a &lt;solutions&gt; division</xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\" />\n        </xsl:if>\n        <xsl:if test=\"not($scope/self::book|$scope/self::article|$scope/self::chapter|$scope/self::section|$scope/self::subsection|$scope/self::subsubsection|$scope/self::exercises|$scope/self::worksheet|$scope/self::reading-questions)\">\n            <xsl:message>PTX:ERROR: the @scope (\"<xsl:value-of select=\"@scope\"/>\") of a &lt;solutions&gt; division is not a supported division.  If you think your attempt is reasonable, please make a feature request.  Results now will be unpredictable</xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\" />\n        </xsl:if>\n    </xsl:if>\n\n    <!-- We call the solutions-generator on a single target: either the -->\n    <!-- division specified by @scope, or the parent (jumping over      -->\n    <!-- \"backmatter\").  The union computing $target has at most one    -->\n    <!-- node, since id() is empty without a @scope attribute, and the  -->\n    <!-- ancestor member is only admitted when @scope is absent.        -->\n    <xsl:variable name=\"target\" select=\"id(@scope) | ancestor::*[not(self::backmatter)][1][not(current()/@scope)]\"/>\n    <xsl:apply-templates select=\"$target\" mode=\"solutions-generator\">\n        <xsl:with-param name=\"purpose\" select=\"$purpose\" />\n        <xsl:with-param name=\"admit\"   select=\"$admit\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"scope\" select=\"$target\"/>\n        <xsl:with-param name=\"component-spec\" select=\"$component-spec\"/>\n    </xsl:apply-templates>\n\n    <xsl:apply-templates select=\"conclusion\">\n        <xsl:with-param name=\"b-original\" select=\"true()\" />\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- The components of solutions (\"statement\", \"hint\", \"answer\",        -->\n<!-- \"solution\") are requested per category of exercise, matching the   -->\n<!-- five attributes of a \"solutions\" division: \"inline\", \"divisional\", -->\n<!-- \"worksheet\", \"reading\", \"project\".  We pack the five component     -->\n<!-- lists into a single string parameter, rather than threading twenty -->\n<!-- boolean parameters through every template of the generator.  The   -->\n<!-- format, with every piece employed, is                              -->\n<!--                                                                    -->\n<!--   |inline:statement hint|divisional:solution|worksheet:|reading:|project:statement| -->\n<!--                                                                    -->\n<xsl:template name=\"solutions-component-spec\">\n    <xsl:param name=\"inline\"/>\n    <xsl:param name=\"divisional\"/>\n    <xsl:param name=\"worksheet\"/>\n    <xsl:param name=\"reading\"/>\n    <xsl:param name=\"project\"/>\n    <xsl:value-of select=\"concat('|inline:', $inline, '|divisional:', $divisional, '|worksheet:', $worksheet, '|reading:', $reading, '|project:', $project, '|')\"/>\n</xsl:template>\n\n<!-- Extract one category's component list from a packed specification -->\n<xsl:template name=\"solutions-components\">\n    <xsl:param name=\"component-spec\"/>\n    <xsl:param name=\"category\"/>\n    <xsl:value-of select=\"substring-before(substring-after($component-spec, concat('|', $category, ':')), '|')\"/>\n</xsl:template>\n\n<!-- Determine whether an exercise should be admitted, given its serial -->\n<!-- number and some specification for what should be admitted.         -->\n<xsl:template match=\"exercise|&PROJECT-LIKE;\" mode=\"determine-admission\">\n    <xsl:param name=\"admit\"/>\n    <xsl:variable name=\"serial-number\">\n        <xsl:apply-templates select=\".\" mode=\"serial-number\"/>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"($admit='odd') and ($serial-number mod 2 = 1)\">\n            <xsl:value-of select=\"'yes'\"/>\n        </xsl:when>\n        <xsl:when test=\"($admit='even') and ($serial-number mod 2 = 0)\">\n            <xsl:value-of select=\"'yes'\"/>\n        </xsl:when>\n        <xsl:when test=\"$admit='all'\">\n            <xsl:value-of select=\"'yes'\"/>\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Solutions Generator -->\n\n<!-- Context is the originally the scope (root of subtree examined)      -->\n<!-- and is meant to be a \"traditional\" division, as expressed in        -->\n<!-- the schema.  However, on recursion context can be any division      -->\n<!-- containing exercises, such as \"worksheet\".  We do not allow a       -->\n<!-- \"solutions\" division to live inside a \"part\", so in the default     -->\n<!-- use a part is not the context.  This is all to explain that         -->\n<!-- the match is more expansive than first use, in practice.            -->\n<!--                                                                     -->\n<!-- On first call, the placing division should have a descriptive       -->\n<!-- title from the author, such as \"Solutions to Chapter Exercises\",    -->\n<!-- when placed at the level of a section (and assuming default scope). -->\n<!--                                                                     -->\n<!-- \"scope\" is replicated/preserved/remembered in recursive calls.      -->\n<!--                                                                     -->\n<!-- \"heading-stack\" is a node set consisting of all divisional nodes    -->\n<!-- between the current node and the scope that warrant having their    -->\n<!-- heading printed when the \"leaf\" division is finally dropping its    -->\n<!-- content. It includes the \"scope\" even though the scope's heading    -->\n<!-- may ultimately not be printed. The \"division-in-solutions\"          -->\n<!-- template can cut scope from the heading-stack when desired.         -->\n<!--                                                                     -->\n<!-- NB: this template is used/called directly by the                    -->\n<!-- \"solution-manual-latex.xsl\" stylesheet, so coordinate               -->\n<!-- changes here with usage there.                                      -->\n\n<xsl:template match=\"book|article|part|chapter|section|subsection|subsubsection|exercises|worksheet|reading-questions\" mode=\"solutions-generator\">\n    <xsl:param name=\"purpose\"/>\n    <xsl:param name=\"admit\"/>\n    <xsl:param name=\"heading-level\"/>\n    <xsl:param name=\"heading-stack\" select=\".\"/>\n    <xsl:param name=\"scope\"/>\n    <xsl:param name=\"component-spec\"/>\n\n    <!-- See if division has *any* content, at any depth, in light of switches. -->\n    <!-- Traditional divisions expect many switches, while specialized          -->\n    <!-- divisions expect a limited subset                                      -->\n    <xsl:variable name=\"dry-run\">\n        <xsl:apply-templates select=\".\" mode=\"dry-run\">\n            <xsl:with-param name=\"admit\"                  select=\"$admit\"/>\n            <xsl:with-param name=\"component-spec\" select=\"$component-spec\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n\n    <!-- Now apply dry-run to preceding-siblings. If this comes back empty, -->\n    <!-- we know that this division should pass along the heading-stack     -->\n    <!-- node set of ancestors for grouping stacked headings.               -->\n    <!-- Otherwise, set the heading-stack to just this division.            -->\n    <xsl:variable name=\"preceding-sibling-dry-run\">\n        <xsl:apply-templates select=\"preceding-sibling::*\" mode=\"dry-run\">\n            <xsl:with-param name=\"admit\"                  select=\"$admit\"/>\n            <xsl:with-param name=\"component-spec\" select=\"$component-spec\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <xsl:variable name=\"b-preceding-empty\" select=\"$preceding-sibling-dry-run = ''\"/>\n    <xsl:variable name=\"next-heading-stack\" select=\".|ancestor::*[$b-preceding-empty and (count(.|$heading-stack) = count($heading-stack))]\"/>\n\n    <xsl:if test=\"not($dry-run = '')\">\n        <!-- We call the only real abstract template, it simply        -->\n        <!-- provides the correct wrapping for a division appearing    -->\n        <!-- to aid in organizing a collection of solutions.           -->\n        <!--                                                           -->\n        <!-- Context is a division: traditional, or specialized.       -->\n        <!-- We want all \"exercise\" and \"project\", in document order,  -->\n        <!-- without descending into subdivisions.  We handle          -->\n        <!-- \"exercisegroup\" specially, since it has \"statement\"       -->\n        <!-- characteristics.  In a traditional division, an inline    -->\n        <!-- exercise can be inside a \"paragraphs\".  If we divide an   -->\n        <!-- \"exercises\" division, we will need to explicitly burrow   -->\n        <!-- down into it.  Finally, a \"worksheet\" can have \"exercise\" -->\n        <!-- laid out via \"sidebyside\".                                -->\n        <!-- The purpose is sent to the modal \"solutions\" templates    -->\n        <!-- in order to generate accurate labels based on position    -->\n        <!-- The \"heading-level\" is the same as the originating        -->\n        <!-- \"solutions\" division on the first call here               -->\n\n        <!-- But first, we see if just one type of component has been  -->\n        <!-- requested, across the various types of \"exercise\".  The   -->\n        <!-- point is to squelch a repetitive heading all through a    -->\n        <!-- list of solutions, so we need to pass the condition on    -->\n        <!-- through.                                                  -->\n        <!-- NB: this gets recomputed as we recurse into subdivisions, -->\n        <!-- but it must be awful fast, so we don't try to set some    -->\n        <!-- flag indicating necessity of computing it.  But recognize -->\n        <!-- we don't need to pass it in the recursive call below.     -->\n        <!-- NB: this is different than the actual components selected -->\n        <!-- all ending up as the same type in the output, because     -->\n        <!-- some requested type never appears.                        -->\n\n        <xsl:variable name=\"variety\">\n            <xsl:if test=\"contains($component-spec, 'statement')\">\n                <xsl:text>T</xsl:text>\n            </xsl:if>\n            <xsl:if test=\"contains($component-spec, 'hint')\">\n                <xsl:text>H</xsl:text>\n            </xsl:if>\n            <xsl:if test=\"contains($component-spec, 'answer')\">\n                <xsl:text>A</xsl:text>\n            </xsl:if>\n            <xsl:if test=\"contains($component-spec, 'solution')\">\n                <xsl:text>S</xsl:text>\n            </xsl:if>\n        </xsl:variable>\n        <xsl:variable name=\"b-component-heading\" select=\"string-length($variety) &gt; 1\"/>\n\n        <!-- Specialized divisions in unstructured divisions have a heading   -->\n        <!-- level that is 2 deeper from invoking \"solutions\".                -->\n        <!-- Other leaf divisions are 1 deeper than the invoking \"solutions\". -->\n        <xsl:variable name=\"is-specialized-division\">\n            <xsl:apply-templates select=\".\" mode=\"is-specialized-division\"/>\n        </xsl:variable>\n        <xsl:variable name=\"is-child-of-structured\">\n            <xsl:apply-templates select=\"parent::*\" mode=\"is-structured-division\"/>\n        </xsl:variable>\n        <xsl:variable name=\"next-heading-level\">\n            <xsl:choose>\n                <xsl:when test=\"$is-specialized-division = 'true' and $is-child-of-structured = 'false'\">\n                    <xsl:value-of select=\"$heading-level + 2\"/>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:value-of select=\"$heading-level + 1\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:variable>\n\n        <xsl:apply-templates select=\".\" mode=\"division-in-solutions\">\n            <xsl:with-param name=\"scope\" select=\"$scope\" />\n            <xsl:with-param name=\"heading-level\" select=\"$next-heading-level\"/>\n            <xsl:with-param name=\"heading-stack\" select=\"$next-heading-stack\"/>\n            <xsl:with-param name=\"content\">\n\n                <!-- N.B.: inline exercises and PROJECT-LIKE can be   -->\n                <!-- \"hidden\" inside the \"paragraphs\" pseudo-division -->\n                <!-- Everything below is 1 deeper than the division's heading -->\n                <xsl:for-each select=\"exercise|subexercises|exercisegroup|&PROJECT-LIKE;|paragraphs/*[self::exercise or &PROJECT-FILTER;]|self::worksheet//*[self::exercise or &PROJECT-FILTER;]\">\n                    <!-- Classify each item into one of the five categories of  -->\n                    <!-- exercise, which selects the relevant component list.   -->\n                    <!-- The order of the tests mirrors the dispatch this       -->\n                    <!-- replaces.  An element matching no test is unexpected,  -->\n                    <!-- yields no category, and so produces no output.         -->\n                    <xsl:variable name=\"category\">\n                        <xsl:choose>\n                            <xsl:when test=\"self::exercise and boolean(&INLINE-EXERCISE-FILTER;)\">\n                                <xsl:text>inline</xsl:text>\n                            </xsl:when>\n                            <xsl:when test=\"self::subexercises or self::exercisegroup\">\n                                <xsl:text>divisional</xsl:text>\n                            </xsl:when>\n                            <xsl:when test=\"self::exercise and ancestor::exercises\">\n                                <xsl:text>divisional</xsl:text>\n                            </xsl:when>\n                            <xsl:when test=\"self::exercise and ancestor::worksheet\">\n                                <xsl:text>worksheet</xsl:text>\n                            </xsl:when>\n                            <xsl:when test=\"self::exercise and ancestor::reading-questions\">\n                                <xsl:text>reading</xsl:text>\n                            </xsl:when>\n                            <xsl:when test=\"&PROJECT-FILTER;\">\n                                <xsl:text>project</xsl:text>\n                            </xsl:when>\n                        </xsl:choose>\n                    </xsl:variable>\n                    <xsl:variable name=\"components\">\n                        <xsl:call-template name=\"solutions-components\">\n                            <xsl:with-param name=\"component-spec\" select=\"$component-spec\"/>\n                            <xsl:with-param name=\"category\" select=\"$category\"/>\n                        </xsl:call-template>\n                    </xsl:variable>\n                    <xsl:if test=\"not($category = '')\">\n                        <xsl:apply-templates select=\".\" mode=\"solutions\">\n                            <xsl:with-param name=\"purpose\" select=\"$purpose\" />\n                            <xsl:with-param name=\"admit\"   select=\"$admit\"/>\n                            <xsl:with-param name=\"b-component-heading\" select=\"$b-component-heading\"/>\n                            <xsl:with-param name=\"heading-level\"       select=\"$next-heading-level + 1\"/>\n                            <xsl:with-param name=\"b-has-statement\" select=\"contains($components, 'statement')\" />\n                            <xsl:with-param name=\"b-has-hint\"      select=\"contains($components, 'hint')\" />\n                            <xsl:with-param name=\"b-has-answer\"    select=\"contains($components, 'answer')\" />\n                            <xsl:with-param name=\"b-has-solution\"  select=\"contains($components, 'solution')\" />\n                        </xsl:apply-templates>\n                    </xsl:if>\n                </xsl:for-each>\n            </xsl:with-param>\n        </xsl:apply-templates>\n    </xsl:if>\n    <!-- recurse into (sub)divisions which can contain exercises     -->\n    <!-- On every recursion (not initial call) we request a heading  -->\n    <!-- and we pass in the scope of original call for help deciding -->\n    <!-- the level of headings given surroundings.                   -->\n    <!-- This is recurrence, so one might expect to increment $heading-level. -->\n    <!-- But to collapse stacked headings, we leave heading-level stable at   -->\n    <!-- the \"solutions\" level and the output stylesheet should increment 1.  -->\n    <!-- NB: $b-component-heading is recomputed, so is not passed    -->\n    <xsl:apply-templates select=\"book|article|part|chapter|section|subsection|subsubsection|exercises|worksheet|reading-questions\" mode=\"solutions-generator\">\n        <xsl:with-param name=\"purpose\" select=\"$purpose\" />\n        <xsl:with-param name=\"admit\"   select=\"$admit\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"heading-stack\" select=\"$next-heading-stack\"/>\n        <xsl:with-param name=\"scope\" select=\"$scope\" />\n        <xsl:with-param name=\"component-spec\" select=\"$component-spec\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- An abstract outer template for each division when repeated in the solutions.                             -->\n<!-- This calls \"duplicate-heading\" modal template, which implements output-specific mechanisms for headings. -->\n\n<xsl:template match=\"book|article|part|chapter|section|subsection|subsubsection|exercises|worksheet|reading-questions\" mode=\"division-in-solutions\">\n    <xsl:param name=\"scope\" />\n    <xsl:param name=\"heading-level\"/>\n    <xsl:param name=\"heading-stack\"/>\n    <xsl:param name=\"content\" />\n    <xsl:variable name=\"is-specialized-division\">\n        <xsl:apply-templates select=\".\" mode=\"is-specialized-division\"/>\n    </xsl:variable>\n    <xsl:variable name=\"is-structured\">\n        <xsl:choose>\n            <xsl:when test=\"$is-specialized-division = 'false'\">\n                <xsl:apply-templates select=\".\" mode=\"is-structured-division\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"false()\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"is-child-of-structured\">\n        <xsl:apply-templates select=\"parent::*\" mode=\"is-structured-division\"/>\n    </xsl:variable>\n\n    <!-- We cut \"scope\" from heading-stack if needed.                    -->\n    <!-- Or reset stack if specialized division in unstructured division -->\n    <xsl:variable name=\"final-heading-stack\" select=\".|ancestor-or-self::*[\n        ($is-specialized-division = 'false' or $is-child-of-structured = 'true')\n        and (count(.|$heading-stack) = count($heading-stack))\n        and (count(.|$scope) != count($scope))]\"\n    />\n\n    <!-- A structured division cannot have children that have solution-like things   -->\n    <!-- So we withhold headings for such divisions, passing to the \"leaf\" division, -->\n    <!-- which must itself be unstructured.                                          -->\n    <xsl:choose>\n        <xsl:when test=\"count($final-heading-stack) = 0\">\n            <xsl:copy-of select=\"$content\" />\n        </xsl:when>\n        <xsl:when test=\"not($is-structured = 'true')\">\n            <xsl:apply-templates select=\".\" mode=\"duplicate-heading\">\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                <xsl:with-param name=\"heading-stack\" select=\"$final-heading-stack\"/>\n            </xsl:apply-templates>\n            <xsl:copy-of select=\"$content\" />\n        </xsl:when>\n        <!-- Content in something structred should just be recursing down to unstructured leaves. -->\n        <xsl:otherwise>\n            <xsl:copy-of select=\"$content\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- A division echoed in a \"solutions\" division (or in a \"list-of\")     -->\n<!-- shows its number, except when it is a specialized division serving  -->\n<!-- as the unstructured remainder of its parent: there it shares the    -->\n<!-- parent's number, and echoing that number would misattribute it.     -->\n<!-- This is THE decision, shared by every conversion's implementation   -->\n<!-- of the \"duplicate-heading\" template: 'true' means show the number.  -->\n<!-- A \"task\" can arrive here via a \"list-of\"; it is not a division at   -->\n<!-- all, and always keeps its number.                                   -->\n<xsl:template match=\"*\" mode=\"duplicate-heading-show-number\">\n    <xsl:variable name=\"is-specialized-division\">\n        <xsl:choose>\n            <xsl:when test=\"self::task\">\n                <xsl:value-of select=\"false()\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:apply-templates select=\".\" mode=\"is-specialized-division\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"is-child-of-structured\">\n        <xsl:choose>\n            <xsl:when test=\"parent::*[&TRADITIONAL-DIVISION-FILTER;]\">\n                <xsl:apply-templates select=\"parent::*[&TRADITIONAL-DIVISION-FILTER;]\" mode=\"is-structured-division\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"false()\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:value-of select=\"($is-specialized-division = 'false') or ($is-child-of-structured = 'true')\"/>\n</xsl:template>\n\n<!-- ##################################### -->\n<!-- Containers of Exercises, in Solutions -->\n<!-- ##################################### -->\n\n<!-- A \"subexercises\" or an \"exercisegroup\" echoed in a \"solutions\"     -->\n<!-- division repeats its infrastructure only when some descendant      -->\n<!-- exercise contributes something: the dry-run decides.  Introduction -->\n<!-- and conclusion ride with the statement's visibility, an item can   -->\n<!-- be withheld entirely, and a \"subexercises\" has a heading, so its   -->\n<!-- items sit one outline level deeper.  Those decisions are made      -->\n<!-- here; the surrounding structure is the per-conversion              -->\n<!-- \"present-solutions-container\" hook, which receives the rendered    -->\n<!-- items as its content parameter.                                    -->\n<xsl:template match=\"subexercises|exercisegroup\" mode=\"solutions\">\n    <xsl:param name=\"purpose\"/>\n    <xsl:param name=\"admit\"/>\n    <xsl:param name=\"b-component-heading\"/>\n    <xsl:param name=\"heading-level\"/>\n    <xsl:param name=\"b-has-statement\"/>\n    <xsl:param name=\"b-has-hint\"/>\n    <xsl:param name=\"b-has-answer\"/>\n    <xsl:param name=\"b-has-solution\"/>\n\n    <!-- When we subset exercises for solutions, an entire container -->\n    <!-- can become empty.  So we do a dry-run and if there is no    -->\n    <!-- content at all we bail out.                                 -->\n    <xsl:variable name=\"dry-run\">\n        <xsl:apply-templates select=\".\" mode=\"dry-run\">\n            <xsl:with-param name=\"admit\" select=\"$admit\"/>\n            <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\"/>\n            <xsl:with-param name=\"b-has-hint\" select=\"$b-has-hint\"/>\n            <xsl:with-param name=\"b-has-answer\" select=\"$b-has-answer\"/>\n            <xsl:with-param name=\"b-has-solution\" select=\"$b-has-solution\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n\n    <xsl:if test=\"not($dry-run = '')\">\n        <xsl:variable name=\"child-heading-level\">\n            <xsl:choose>\n                <xsl:when test=\"self::subexercises\">\n                    <xsl:value-of select=\"$heading-level + 1\"/>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:value-of select=\"$heading-level\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:variable>\n        <xsl:apply-templates select=\".\" mode=\"present-solutions-container\">\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\"/>\n            <xsl:with-param name=\"content\">\n                <xsl:apply-templates select=\"exercise|exercisegroup\" mode=\"solutions\">\n                    <xsl:with-param name=\"purpose\" select=\"$purpose\"/>\n                    <xsl:with-param name=\"admit\" select=\"$admit\"/>\n                    <xsl:with-param name=\"b-component-heading\" select=\"$b-component-heading\"/>\n                    <xsl:with-param name=\"heading-level\" select=\"$child-heading-level\"/>\n                    <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\"/>\n                    <xsl:with-param name=\"b-has-hint\" select=\"$b-has-hint\"/>\n                    <xsl:with-param name=\"b-has-answer\" select=\"$b-has-answer\"/>\n                    <xsl:with-param name=\"b-has-solution\" select=\"$b-has-solution\"/>\n                </xsl:apply-templates>\n            </xsl:with-param>\n        </xsl:apply-templates>\n    </xsl:if>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"present-solutions-container\">\n    <xsl:message>PTX:BUG:     a conversion to a new output format requires implementation of the template with match=\"*\" and mode=\"present-solutions-container\"</xsl:message>\n</xsl:template>\n\n<!-- ####################### -->\n<!-- Components of Exercises -->\n<!-- ####################### -->\n\n<!-- An exercise (or PROJECT-LIKE, or EXAMPLE-LIKE, or \"task\") shows     -->\n<!-- some of its components: \"statement\", \"hint\", \"answer\", \"solution\".  -->\n<!-- Which ones is a *decision*, made from the $b-has-* parameters       -->\n<!-- (a desire, from publisher switches or a \"solutions\" division) and   -->\n<!-- from what the exercise actually possesses.  The decision procedure  -->\n<!-- lives here, once; the markup is supplied by each conversion through -->\n<!-- the \"present-*\" hooks below.                                        -->\n<!--                                                                     -->\n<!-- N.B. the HTML conversion does not yet participate: its version of   -->\n<!-- \"exercise-components\" interleaves Runestone interactive exercises   -->\n<!-- with this generic procedure, and its templates shadow these by      -->\n<!-- import precedence.  Converging it onto these drivers is planned.    -->\n\n<!-- The leaf form: a statement, then chosen appendages.  The $b-has-*   -->\n<!-- parameters express a desire to see a component; an exercise missing -->\n<!-- a component cannot show it, hence the $b-showing-* refinements.     -->\n<!-- With no \"statement\" shown, a \"title\" may still be presented inline, -->\n<!-- so a separator is necessary in that case as well.                   -->\n<xsl:template match=\"exercise|&EXAMPLE-LIKE;|&PROJECT-LIKE;|task[not(task)]|webwork-reps/static|webwork-reps/static/task|webwork-reps/static/stage\" mode=\"exercise-components\">\n    <xsl:param name=\"b-original\"/>\n    <xsl:param name=\"purpose\"/>\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n    <xsl:param name=\"b-component-heading\"/>\n    <xsl:param name=\"run-in-heading\"/>\n    <xsl:param name=\"b-has-statement\"/>\n    <xsl:param name=\"b-has-hint\"/>\n    <xsl:param name=\"b-has-answer\"/>\n    <xsl:param name=\"b-has-solution\"/>\n\n    <xsl:variable name=\"b-showing-statement\" select=\"$b-has-statement or title\"/>\n    <xsl:variable name=\"b-showing-hints\" select=\"$b-has-hint and hint\"/>\n    <xsl:variable name=\"b-showing-answers\" select=\"$b-has-answer and answer\"/>\n    <xsl:variable name=\"b-showing-solutions\" select=\"$b-has-solution and solution\"/>\n\n    <!-- structured (with components) versus unstructured (a bare statement) -->\n    <xsl:choose>\n        <xsl:when test=\"statement\">\n            <xsl:choose>\n                <xsl:when test=\"$b-has-statement\">\n                    <xsl:apply-templates select=\".\" mode=\"present-exercise-statement\">\n                        <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                        <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n                        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                        <xsl:with-param name=\"run-in-heading\" select=\"$run-in-heading\"/>\n                    </xsl:apply-templates>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:apply-templates select=\".\" mode=\"present-exercise-statement-omitted\">\n                        <xsl:with-param name=\"run-in-heading\" select=\"$run-in-heading\"/>\n                    </xsl:apply-templates>\n                </xsl:otherwise>\n            </xsl:choose>\n            <!-- inline presentation used up, and more coming: a separator -->\n            <xsl:if test=\"$b-showing-statement and ($b-showing-hints or $b-showing-answers or $b-showing-solutions)\">\n                <xsl:apply-templates select=\".\" mode=\"exercise-component-separator\"/>\n            </xsl:if>\n            <xsl:if test=\"$b-showing-hints or $b-showing-answers or $b-showing-solutions\">\n                <xsl:apply-templates select=\".\" mode=\"present-exercise-solutions\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                    <xsl:with-param name=\"purpose\" select=\"$purpose\"/>\n                    <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n                    <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                    <xsl:with-param name=\"b-component-heading\" select=\"$b-component-heading\"/>\n                    <xsl:with-param name=\"b-has-hint\" select=\"$b-has-hint\"/>\n                    <xsl:with-param name=\"b-has-answer\" select=\"$b-has-answer\"/>\n                    <xsl:with-param name=\"b-has-solution\" select=\"$b-has-solution\"/>\n                    <xsl:with-param name=\"b-showing-hints\" select=\"$b-showing-hints\"/>\n                    <xsl:with-param name=\"b-showing-answers\" select=\"$b-showing-answers\"/>\n                    <xsl:with-param name=\"b-showing-solutions\" select=\"$b-showing-solutions\"/>\n                </xsl:apply-templates>\n            </xsl:if>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- no explicit \"statement\", so all content is the statement -->\n            <xsl:if test=\"$b-has-statement\">\n                <xsl:apply-templates select=\".\" mode=\"present-exercise-statement-bare\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                    <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n                    <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                    <xsl:with-param name=\"run-in-heading\" select=\"$run-in-heading\"/>\n                </xsl:apply-templates>\n                <!-- no separator, since no trailing components -->\n            </xsl:if>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- The structured form: an optional \"introduction\", a sequence of      -->\n<!-- \"task\" (some possibly withheld, so each is checked by a \"dry-run\"), -->\n<!-- and an optional \"conclusion\".  The introduction and conclusion ride -->\n<!-- with the statement's visibility.                                    -->\n<xsl:template match=\"exercise[task]|project[task]|activity[task]|exploration[task]|investigation[task]|example[task]|question[task]|problem[task]|task[task]\" mode=\"exercise-components\">\n    <xsl:param name=\"b-original\"/>\n    <xsl:param name=\"purpose\"/>\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n    <xsl:param name=\"b-component-heading\"/>\n    <xsl:param name=\"run-in-heading\"/>\n    <xsl:param name=\"b-has-statement\"/>\n    <xsl:param name=\"b-has-hint\"/>\n    <xsl:param name=\"b-has-answer\"/>\n    <xsl:param name=\"b-has-solution\"/>\n\n    <xsl:apply-templates select=\".\" mode=\"present-tasks-introduction\">\n        <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\"/>\n        <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n        <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"run-in-heading\" select=\"$run-in-heading\"/>\n    </xsl:apply-templates>\n\n    <!-- Now we see if the list of contained tasks is empty or not -->\n    <xsl:variable name=\"task-list-dry-run\">\n        <xsl:apply-templates select=\"task\" mode=\"dry-run\">\n            <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\" />\n            <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-answer\" />\n            <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-hint\" />\n            <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-solution\" />\n        </xsl:apply-templates>\n    </xsl:variable>\n\n    <xsl:if test=\"not($task-list-dry-run = '')\">\n        <xsl:apply-templates select=\".\" mode=\"begin-task-list\"/>\n        <xsl:for-each select=\"task\">\n            <!-- just for this particular task -->\n            <xsl:variable name=\"dry-run\">\n                <xsl:apply-templates select=\".\" mode=\"dry-run\">\n                    <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\" />\n                    <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-answer\" />\n                    <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-hint\" />\n                    <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-solution\" />\n                </xsl:apply-templates>\n            </xsl:variable>\n            <!-- The entire task list is non-empty, so some particular task -->\n            <!-- must be non-empty, ensuring a conversion never creates an  -->\n            <!-- empty list structure.                                      -->\n            <xsl:if test=\"not($dry-run = '')\">\n                <xsl:apply-templates select=\".\" mode=\"present-task-item\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                    <xsl:with-param name=\"purpose\" select=\"$purpose\"/>\n                    <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n                    <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                    <xsl:with-param name=\"b-component-heading\" select=\"$b-component-heading\"/>\n                    <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\" />\n                    <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-hint\" />\n                    <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-answer\" />\n                    <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-solution\" />\n                </xsl:apply-templates>\n            </xsl:if>\n        </xsl:for-each>\n        <xsl:apply-templates select=\".\" mode=\"end-task-list\"/>\n    </xsl:if>\n\n    <xsl:apply-templates select=\".\" mode=\"present-tasks-conclusion\">\n        <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\"/>\n        <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n        <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- The hooks.  A conversion participating in the drivers above         -->\n<!-- must implement the four essential presentation hooks; the stubs     -->\n<!-- here fail loudly.  The remaining hooks are optional decorations     -->\n<!-- with quiet no-op defaults.                                          -->\n\n<xsl:template match=\"*\" mode=\"present-exercise-statement\">\n    <xsl:message>PTX:BUG:     a conversion to a new output format requires implementation of the template with match=\"*\" and mode=\"present-exercise-statement\"</xsl:message>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"present-exercise-statement-bare\">\n    <xsl:message>PTX:BUG:     a conversion to a new output format requires implementation of the template with match=\"*\" and mode=\"present-exercise-statement-bare\"</xsl:message>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"present-exercise-solutions\">\n    <xsl:message>PTX:BUG:     a conversion to a new output format requires implementation of the template with match=\"*\" and mode=\"present-exercise-solutions\"</xsl:message>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"present-task-item\">\n    <xsl:message>PTX:BUG:     a conversion to a new output format requires implementation of the template with match=\"*\" and mode=\"present-task-item\"</xsl:message>\n</xsl:template>\n\n<!-- A heading with no statement to carry it may still need presenting -->\n<xsl:template match=\"*\" mode=\"present-exercise-statement-omitted\"/>\n\n<!-- Punctuation between components, when more are coming -->\n<xsl:template match=\"*\" mode=\"exercise-component-separator\"/>\n\n<!-- Infrastructure around a sequence of \"task\" -->\n<xsl:template match=\"*\" mode=\"begin-task-list\"/>\n<xsl:template match=\"*\" mode=\"end-task-list\"/>\n\n<!-- The introduction (or a stand-in) preceding a sequence of \"task\", -->\n<!-- and the conclusion following it; both ride with the statement's   -->\n<!-- visibility                                                        -->\n<xsl:template match=\"*\" mode=\"present-tasks-introduction\">\n    <xsl:param name=\"b-has-statement\"/>\n    <xsl:if test=\"$b-has-statement\">\n        <xsl:apply-templates select=\"introduction\"/>\n    </xsl:if>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"present-tasks-conclusion\">\n    <xsl:param name=\"b-has-statement\"/>\n    <xsl:if test=\"$b-has-statement\">\n        <xsl:apply-templates select=\"conclusion\"/>\n    </xsl:if>\n</xsl:template>\n\n<!-- ################ -->\n<!-- Printout Margins -->\n<!-- ################ -->\n\n<!-- PROJECT-LIKE is here for standalone printout previews. -->\n<xsl:template match=\"&PRINTOUT;|&PROJECT-LIKE;\" mode=\"printout-margin\">\n    <xsl:param name=\"author-side\"/>\n    <xsl:param name=\"publisher-side\"/>\n    <xsl:choose>\n        <xsl:when test=\"$author-side\">\n            <xsl:value-of select=\"normalize-space($author-side)\"/>\n        </xsl:when>\n        <xsl:when test=\"@margin\">\n            <xsl:value-of select=\"normalize-space(@margin)\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"normalize-space($publisher-side)\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- ##################-->\n<!-- Frontmatter Items -->\n<!-- ##################-->\n\n<!-- Bibliographic information for a document is contained in the     -->\n<!-- frontmatter/bibinfo element.  Items then move to either a        -->\n<!-- titlepage or colophon that contain then empty titlepage-items    -->\n<!-- or colophon-items.  These are implemented by each template.      -->\n <!--Here we define these abstract templates with warnings to do this.-->\n<xsl:template match=\"titlepage-items\">\n    <xsl:message>PTX:BUG:    a conversion to a new output format requires implementation of a named template (\"titlepage-items\") in order to specify which bibliographic information to include in the titlepage.</xsl:message>\n</xsl:template>\n\n<xsl:template match=\"colophon-items\">\n    <xsl:message>PTX:BUG:    a conversion to a new output format requires implementation of a named template (\"colophon-items\") in order to specify which bibliographic information to include in the front colophon.</xsl:message>\n</xsl:template>\n\n<!-- No conversion will create content directly from bibinfo -->\n<xsl:template match=\"bibinfo\"/>\n\n<!-- Keywords: create a comma-separated list of each keyword -->\n<!-- (the comma can be overridden by a passed param).        -->\n<!-- Include \"Primary\" or \"Secondary\" appropriately, \";\" to  -->\n<!-- separate the list of primary and secondary keywords.    -->\n<!-- No ending period (some styles don't include it).        -->\n<xsl:template match=\"keywords/keyword\">\n    <xsl:param name=\"sep\" select=\"', '\"/>\n    <xsl:if test=\"@primary='yes'\">\n        <xsl:text>Primary </xsl:text>\n    </xsl:if>\n    <xsl:if test=\"@primary='no' or @secondary='yes'\">\n        <xsl:text>Secondary </xsl:text>\n    </xsl:if>\n    <xsl:value-of select=\"normalize-space(.)\"/>\n    <xsl:choose>\n        <xsl:when test=\"following-sibling::keyword[1][@primary='no' or @secondary='yes']\">\n            <xsl:text>; </xsl:text>\n        </xsl:when>\n        <xsl:when test=\"following-sibling::keyword\">\n            <xsl:value-of select=\"$sep\"/>\n        </xsl:when>\n        <xsl:otherwise/>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- ############# -->\n<!-- Notation List -->\n<!-- ############# -->\n\n<!-- A list/table where each row is a sample usage (as mathematics), -->\n<!-- a short narrative description, and then a cross-reference or    -->\n<!-- locator to the place where the original \"notation\" element was  -->\n<!-- authored, presumably in the vicinity of a more complete         -->\n<!-- explanation.  These appear in the order of appearance, so no    -->\n<!-- sorting takes place here, document order is what we want.       -->\n\n<!-- Abstract Templates -->\n<!--                                                             -->\n<!-- These require implementation for a new conversion to        -->\n<!-- provide formatting peculiar to an output format.            -->\n<!-- Logic/organization is provided here.                        -->\n<!--                                                             -->\n<!-- \"present-notation-list\"                                     -->\n<!-- A named template (context is not employed), typically with  -->\n<!-- infrastructure to surround the \"content parameter, which is -->\n<!-- the rows of the list/table.  This is applied once.          -->\n<!--                                                             -->\n<!-- \"present-notation-item\"                                     -->\n<!-- A modal template (since a generic template kills \"notation\" -->\n<!-- on-sight) for each instance, forming one row of the table.  -->\n\n<!-- The \"notation\" element can be placed inside a \"p\" or inside a  -->\n<!-- \"definition\".  When encountered in document order it is simply -->\n<!-- killed.  We collect them as a group when forming the list.     -->\n<!-- NB: this is overidden in the conversion to LaTeX since a       -->\n<!-- marker needs to be dropped in order for the cross-reference    -->\n<!-- to find its target.                                            -->\n<xsl:template match=\"notation\"/>\n\n<!-- Match the (single?) \"notation-list\" element, presumably in a     -->\n<!-- back matter division (appendix?).  Provide infrastructure        -->\n<!-- (wrapping) and process global list of individual items in order. -->\n<!-- NB: we tried a \"for-each\", in hopes of easily determining the    -->\n<!-- last \"notation\" so the LaTeX table would not have a final        -->\n<!-- unnecessary \"\\\\\".  But that context switch was lost in the       -->\n<!-- transition to the LaTeX implementation template.  We might form  -->\n<!-- a boolean parameter here (\"$last\") to pass along to every        -->\n<!-- implementation, but that seems like a lot of effort for a        -->\n<!-- problem nobody has mentioned in years.                           -->\n<xsl:template match=\"notation-list\">\n    <xsl:call-template name=\"present-notation-list\">\n        <xsl:with-param name=\"content\">\n            <xsl:apply-templates select=\"$document-root//notation\" mode=\"present-notation-item\"/>\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- Stub abstract template, with warning -->\n<xsl:template name=\"present-notation-list\">\n    <xsl:param name=\"content\"/>\n\n    <xsl:message>PTX:BUG:    a conversion to a new output format requires implementation of a named template (\"present-notation-list\") in order to structure a notation list.</xsl:message>\n</xsl:template>\n\n<!-- Stub abstract template, with warning -->\n<xsl:template match=\"notation\" mode=\"present-notation-item\">\n\n    <xsl:message>PTX:BUG:    a conversion to a new output format requires implementation of a modal template (\"present-notation-item\") in order to structure an explanation of a single \"notation\" element.</xsl:message>\n</xsl:template>\n\n\n<!-- ################ -->\n<!-- Index Production -->\n<!-- ################ -->\n\n<!-- We have templates here that produce an index, provoked      -->\n<!-- by the \"index-list\" element.  They contain the logic of     -->\n<!-- collecting, analyzing, sorting, and grouping the index      -->\n<!-- entries found in the \"idx\" elements.  They rely on abstract -->\n<!-- templates found in conversion stylesheets which handle the  -->\n<!-- peculiarities of the relevant output format. We describe    -->\n<!-- these here, along with stub templates in the vicinity.      -->\n\n<!-- Abstract templates -->\n\n<!-- \"present-index\" -->\n<!-- A named template (context is not employed), typically with -->\n<!-- infrastructure to surround the \"content\" parameter, which  -->\n<!-- the entire body of the index.  This is applied once.       -->\n\n<!-- \"present-letter-group\" -->\n<!-- A named template (context is not employed), to present -->\n<!-- several entries, all leading with the same letter.     -->\n\n<!-- \"present-index-heading\" -->\n<!-- A named template (context is not employed), to format -->\n<!-- a single heading of an index entry (there may be up   -->\n<!-- to three of these).                                   -->\n\n<!-- \"present-index-locator\"  -->\n<!-- \"present-index-see\"      -->\n<!-- \"present-index-see-also\" -->\n<!-- \"present-index-italics\"  -->\n<!-- Named templates (context is not employed) for the  -->\n<!-- format of individual pieces of the locators at the -->\n<!-- end of an index entry.                             -->\n\n<!-- Used at the end of the next template to group index       -->\n<!-- entries by letter for eventual output organized by letter -->\n<xsl:key name=\"index-entry-by-letter\" match=\"index\" use=\"@letter\"/>\n\n<!-- \"index-list\":                                           -->\n<!--     build a sorted list of every \"index\" in text        -->\n<!--     use Muenchian Method to group by letter and process -->\n<!-- \"group-by-heading\":                                     -->\n<!--     consolidate/accumulate entries with common heading  -->\n<!-- \"knowl-list\":                                           -->\n<!--     output the locators, see, see also                  -->\n<xsl:template match=\"index-list\">\n    <!-- Save-off the \"index-list\" as context for placement  -->\n    <!-- of eventual xref/cross-references, since we use a   -->\n    <!-- for-each and context changes.  Not strictly         -->\n    <!-- necessary, but correct.                             -->\n    <!-- We also pass this node down into the construction   -->\n    <!-- of headings, to provide context for the             -->\n    <!-- localization of words like \"see\" and \"see also\" in  -->\n    <!-- the index.  (So it is an @xml:lang on the           -->\n    <!-- \"index-list\" generator which dictates this,         -->\n    <!-- allowing for indices in two different languages.)   -->\n    <!-- TODO: perhaps the originating \"index-list\" should   -->\n    <!-- be the context of this chain of templates, moving   -->\n    <!-- later ones away from named templates?               -->\n    <xsl:variable name=\"the-index-list\" select=\".\"/>\n    <!-- \"idx\" as mixed content.                             -->\n    <!-- Or, \"idx\" structured with up to three \"h\"           -->\n    <!-- Start attribute is actual end of a \"page            -->\n    <!-- range\", goodies at @finish.                         -->\n\n    <!-- \"index-items\" is an internal structure, so very     -->\n    <!-- predictable.  Looks like:                           -->\n    <!--                                                     -->\n    <!-- text/key: always three pairs, some may be empty.    -->\n    <!-- \"text\" is author's heading and will be output at    -->\n    <!-- the end, \"key\" is a sanitized version for sorting,  -->\n    <!-- and could be an entire replacement if the @sortby   -->\n    <!-- attribute is used.                                  -->\n    <!--                                                     -->\n    <!-- locator-type: used to identify a \"traditional\" page -->\n    <!-- locator which points back to a place in the text,   -->\n    <!-- versus a \"see\" or \"see also\" entry.  Only used for  -->\n    <!-- sorting, and really only used to be sure a \"see\"    -->\n    <!-- *follows* the page locator.                         -->\n    <xsl:variable name=\"index-items\">\n        <xsl:for-each select=\"$document-root//idx[not(@start)]\">\n            <index>\n                <!-- identify content of primary sort key      -->\n                <!-- this follows the logic of creating key[1] -->\n                <!-- TODO: this may be too ad-hoc, study       -->\n                <!--       closely on a refactor               -->\n                <xsl:variable name=\"letter-content\">\n                    <xsl:choose>\n                        <xsl:when test=\"@sortby\">\n                            <xsl:value-of select=\"@sortby\" />\n                        </xsl:when>\n                        <xsl:when test=\"not(h)\">\n                            <xsl:apply-templates/>\n                        </xsl:when>\n                        <xsl:when test=\"h and h[1]/@sortby\">\n                            <xsl:apply-templates select=\"h[1]/@sortby\"/>\n                        </xsl:when>\n                        <xsl:when test=\"h\">\n                            <xsl:apply-templates select=\"h[1]\"/>\n                        </xsl:when>\n                        <xsl:otherwise/>\n                    </xsl:choose>\n                </xsl:variable>\n                <!-- lowercase first letter of primary sort key    -->\n                <!-- used later to group items by letter in output -->\n                <xsl:attribute name=\"letter\">\n                    <xsl:value-of select=\"translate(substring($letter-content,1,1), &UPPERCASE;, &LOWERCASE;)\"/>\n                </xsl:attribute>\n                <xsl:choose>\n                    <!-- simple mixed-content first, no structure -->\n                    <!-- one text-key pair, two more empty        -->\n                    <xsl:when test=\"not(h)\">\n                        <xsl:variable name=\"content\">\n                            <xsl:apply-templates/>\n                        </xsl:variable>\n                        <!-- text, key-value for single index heading -->\n                        <text>\n                            <xsl:copy-of select=\"$content\" />\n                        </text>\n                        <key>\n                            <xsl:choose>\n                                <xsl:when test=\"@sortby\">\n                                    <xsl:value-of select=\"translate(@sortby, &UPPERCASE;, &LOWERCASE;)\" />\n                                </xsl:when>\n                                <xsl:otherwise>\n                                    <xsl:value-of select=\"translate($content, &UPPERCASE;, &LOWERCASE;)\" />\n                                </xsl:otherwise>\n                            </xsl:choose>\n                        </key>\n                        <!-- plus two more empty text, key pairs -->\n                        <text/><key/>\n                        <text/><key/>\n                    </xsl:when>\n                    <!-- structured index entry, multiple text-key pairs -->\n                    <!-- \"main\" as indicator is deprecated               -->\n                    <xsl:when test=\"h\">\n                        <!-- \"h\" occur in order, main-sub-sub deprecated -->\n                        <xsl:for-each select=\"h\">\n                            <xsl:variable name=\"content\">\n                                <xsl:apply-templates/>\n                            </xsl:variable>\n                            <text>\n                                <xsl:copy-of select=\"$content\" />\n                            </text>\n                            <key>\n                                <xsl:choose>\n                                    <xsl:when test=\"@sortby\">\n                                        <xsl:value-of select=\"translate(@sortby, &UPPERCASE;, &LOWERCASE;)\" />\n                                    </xsl:when>\n                                    <xsl:otherwise>\n                                        <xsl:value-of select=\"translate($content, &UPPERCASE;, &LOWERCASE;)\" />\n                                    </xsl:otherwise>\n                                </xsl:choose>\n                            </key>\n                        </xsl:for-each>\n                        <!-- add additional empty text, key pairs -->\n                        <!-- so there are always three            -->\n                        <xsl:if test=\"(count(h) = 1) or (count(h) = 2)\">\n                            <text/><key/>\n                        </xsl:if>\n                        <xsl:if test=\"count(h) = 1\">\n                            <text/><key/>\n                        </xsl:if>\n                        <!-- final sort key will prioritize  -->\n                        <!-- this mimics LaTeX's ordering    -->\n                        <!--   0 - has \"see also\"            -->\n                        <!--   1 - has \"see\"                 -->\n                        <!--   2 - is usual index reference  -->\n                        <xsl:if test=\"not(following-sibling::*[self::h])\">\n                            <locator-type>\n                                <xsl:choose>\n                                    <xsl:when test=\"seealso\">\n                                        <xsl:text>2</xsl:text>\n                                    </xsl:when>\n                                    <xsl:when test=\"see\">\n                                        <xsl:text>1</xsl:text>\n                                    </xsl:when>\n                                    <xsl:otherwise>\n                                        <xsl:text>0</xsl:text>\n                                    </xsl:otherwise>\n                                </xsl:choose>\n                            </locator-type>\n                        </xsl:if>\n                    </xsl:when>\n                </xsl:choose>\n                <!-- Create the full locator and save now, since context will -->\n                <!-- be lost later.  Save a page locator in \"cross-reference\" -->\n                <!-- element.  We use the context of the index itself as the  -->\n                <!-- location where the cross-reference is placed.  The       -->\n                <!-- location of the \"idx\" is the start of a search for the   -->\n                <!-- enclosing element.  See and \"see also\" take precedence.  -->\n                <xsl:choose>\n                    <xsl:when test=\"see\">\n                        <see>\n                            <xsl:apply-templates select=\"see\"/>\n                        </see>\n                    </xsl:when>\n                    <xsl:when test=\"seealso\">\n                        <seealso>\n                            <xsl:apply-templates select=\"seealso\"/>\n                        </seealso>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <cross-reference>\n                            <xsl:apply-templates select=\"$the-index-list\" mode=\"index-enclosure\">\n                                <xsl:with-param name=\"enclosure\" select=\".\"/>\n                            </xsl:apply-templates>\n                        </cross-reference>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </index>\n        </xsl:for-each>\n    </xsl:variable>\n    <!-- Sort, now that info from document tree ordering is recorded     -->\n    <!-- Keys, normalized to lowercase, or @sortby attributes, are the   -->\n    <!-- primary key for sorting, but if we have index entries that just -->\n    <!-- differ by upper- or lower-case distinctions, we need to have    -->\n    <!-- identical variants sort next to each other so they get grouped  -->\n    <!-- as one entry with multiple cross-references, so we sort         -->\n    <!-- secondarily on the actual text as well.  The page locators were -->\n    <!-- built in document order and so should remain that way after the -->\n    <!-- sort and so be output in order of appearance.                   -->\n    <xsl:variable name=\"sorted-index\">\n        <xsl:for-each select=\"exsl:node-set($index-items)/*\">\n            <xsl:sort select=\"./key[1]\" />\n            <xsl:sort select=\"./text[1]\"/>\n            <xsl:sort select=\"./key[2]\" />\n            <xsl:sort select=\"./text[2]\"/>\n            <xsl:sort select=\"./key[3]\" />\n            <xsl:sort select=\"./text[3]\"/>\n            <xsl:sort select=\"./locator-type\" />\n            <xsl:sort select=\"./see\"/>\n            <xsl:sort select=\"./seealso\"/>\n            <xsl:copy-of select=\".\" />\n        </xsl:for-each>\n    </xsl:variable>\n    <!-- Group by Letter -->\n    <!-- A careful exposition of the Muenchian Method, named after Steve Muench  -->\n    <!-- of Oracle.  This is an well-known, but complicated, XSLT 1.0 technique. -->\n    <!-- (This is much easier in XSLT 2.0 with certain instructions).  We follow -->\n    <!-- the XSLT Cookbook 2.0, Recipe 6.2, modulo one critical typo, and also   -->\n    <!-- Jeni Tennison's instructive  \"Grouping Using the Muenchian Method\" at   -->\n    <!-- http://www.jenitennison.com/xslt/grouping/muenchian.html.               -->\n    <!--                                                                         -->\n    <!-- Initial \"for-each\" sieves out a single (the first) representative of    -->\n    <!-- each group of \"index\" that have a common initial letter for their sort  -->\n    <!-- criteria.  Each becomes the context node for the remainder.             -->\n    <xsl:call-template name=\"present-index\">\n        <xsl:with-param name=\"content\">\n            <xsl:for-each select=\"exsl:node-set($sorted-index)/index[count(.|key('index-entry-by-letter', @letter)[1]) = 1]\">\n                <!-- save the key to use again in selecting the group -->\n                <xsl:variable name=\"current-letter\" select=\"@letter\"/>\n                <!-- collect all the \"index\" with the same initial letter as representative    -->\n                <!-- this key is still perusing the nodes of $sorted-index as context document -->\n                <xsl:variable name=\"letter-group\" select=\"key('index-entry-by-letter', $current-letter)\"/>\n                <!-- Employ abstract template to present/style a letter group -->\n                <xsl:call-template name=\"present-letter-group\">\n                    <xsl:with-param name=\"the-index-list\" select=\"$the-index-list\"/>\n                    <xsl:with-param name=\"letter-group\" select=\"$letter-group\"/>\n                    <xsl:with-param name=\"current-letter\" select=\"$current-letter\"/>\n                    <xsl:with-param name=\"content\">\n                        <!-- send to group-by-headings, which is vestigal -->\n                        <xsl:apply-templates select=\"$letter-group[1]\" mode=\"group-by-heading\">\n                            <xsl:with-param name=\"the-index-list\" select=\"$the-index-list\"/>\n                            <xsl:with-param name=\"heading-group\" select=\"/..\" />\n                            <xsl:with-param name=\"letter-group\" select=\"$letter-group\" />\n                        </xsl:apply-templates>\n                    </xsl:with-param>\n                </xsl:call-template>\n            </xsl:for-each>\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n\n<xsl:template name=\"present-index\">\n    <xsl:param name=\"content\"/>\n\n    <xsl:message>PTX:BUG:    a conversion to a new output format requires implementation of a named template (\"present-index\") in order to structure the overall index.</xsl:message>\n</xsl:template>\n\n<xsl:template name=\"present-letter-group\">\n    <xsl:param name=\"the-index-list\"/>\n    <xsl:param name=\"letter-group\"/>\n    <xsl:param name=\"current-letter\"/>\n    <xsl:param name=\"content\"/>\n\n    <xsl:message>PTX:BUG:    a conversion to a new output format requires implementation of a named template (\"present-letter-group\") in order to structure a group of entries all leading with the same letter.</xsl:message>\n</xsl:template>\n\n<!-- Accumulate index entries with identical headings - their    -->\n<!-- exact text, not anything related to the keys.  Quit         -->\n<!-- accumulating when look-ahead shows next entry differs.      -->\n<!-- Output the (3-part) heading and locators before restarting. -->\n<!-- TODO: investigate reworking this via Muenchian Method       -->\n<xsl:template match=\"index\" mode=\"group-by-heading\">\n    <xsl:param name=\"the-index-list\"/>\n    <!-- Empty node list from parent of root node -->\n    <xsl:param name=\"heading-group\"/>\n    <xsl:param name=\"letter-group\"/>\n\n    <!-- look ahead at next index entry -->\n    <xsl:variable name=\"next-index\" select=\"following-sibling::index[1]\"/>\n    <!-- check if context node is still in the letter-group -->\n    <xsl:if test=\"count(.|$letter-group) = count($letter-group)\">\n        <xsl:variable name=\"new-heading-group\" select=\"$heading-group|.\"/>\n        <xsl:choose>\n            <!-- same heading, accumulate and iterate -->\n            <xsl:when test=\"($next-index/text[1] = ./text[1]) and ($next-index/text[2] = ./text[2]) and ($next-index/text[3] = ./text[3])\">\n                <xsl:apply-templates select=\"$next-index\" mode=\"group-by-heading\">\n                    <xsl:with-param name=\"the-index-list\" select=\"$the-index-list\"/>\n                    <xsl:with-param name=\"heading-group\" select=\"$new-heading-group\" />\n                    <xsl:with-param name=\"letter-group\" select=\"$letter-group\"/>\n                </xsl:apply-templates>\n            </xsl:when>\n            <!-- some text differs in next index entry, -->\n            <!-- write and restart heading accumulation -->\n            <xsl:otherwise>\n                <xsl:call-template name=\"output-one-heading-group\">\n                    <xsl:with-param name=\"the-index-list\" select=\"$the-index-list\"/>\n                    <xsl:with-param name=\"heading-group\" select=\"$new-heading-group\" />\n                </xsl:call-template>\n                <!-- restart grouping by heading, pass through letter-group -->\n                <xsl:apply-templates select=\"$next-index\" mode=\"group-by-heading\">\n                    <xsl:with-param name=\"the-index-list\" select=\"$the-index-list\"/>\n                    <xsl:with-param name=\"heading-group\" select=\"/..\" />\n                    <xsl:with-param name=\"letter-group\" select=\"$letter-group\"/>\n                </xsl:apply-templates>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- Place the (possibly three) components of -->\n<!-- the heading(s) into their proper divs.   -->\n<!-- Do not duplicate prior components that   -->\n<!-- match, do not write an empty heading.    -->\n<xsl:template name=\"output-one-heading-group\">\n    <xsl:param name=\"the-index-list\"/>\n    <xsl:param name=\"heading-group\" />\n\n    <xsl:if test=\"$heading-group/see and $heading-group/cross-reference\">\n        <xsl:message>PTX:WARNING: an index entry should not have both a locator and a \"see\" reference.  Results may be unpredictable.  Perhaps you meant to employ a \"seealso\" reference?  Heading is: \"<xsl:value-of select=\"text[1]\"/>; <xsl:value-of select=\"text[2]\"/>; <xsl:value-of select=\"text[3]\"/>\"</xsl:message>\n    </xsl:if>\n    <xsl:if test=\"$heading-group/seealso and not($heading-group/cross-reference)\">\n        <xsl:message>PTX:WARNING: an index entry should not have a \"seealso\" reference without also having a locator.  Results may be unpredictable.  Perhaps you meant to employ a \"see\" reference?  Heading is: \"<xsl:value-of select=\"text[1]\"/>; <xsl:value-of select=\"text[2]\"/>; <xsl:value-of select=\"text[3]\"/>\"</xsl:message>\n    </xsl:if>\n\n    <xsl:variable name=\"pattern\" select=\"$heading-group[1]\" />\n    <xsl:variable name=\"pred\" select=\"$pattern/preceding-sibling::index[1]\" />\n    <!-- booleans for analysis of format of heading, locators -->\n    <xsl:variable name=\"match1\" select=\"($pred/text[1] = $pattern/text[1]) and $pred\" />\n    <xsl:variable name=\"match2\" select=\"($pred/text[2] = $pattern/text[2]) and $pred\" />\n    <xsl:variable name=\"match3\" select=\"($pred/text[3] = $pattern/text[3]) and $pred\" />\n    <xsl:variable name=\"empty2\" select=\"boolean($pattern/text[2] = '')\" />\n    <xsl:variable name=\"empty3\" select=\"boolean($pattern/text[3] = '')\" />\n    <!-- Write headings of a group, indicating the level of -->\n    <!-- each heading (up to 3 levels) and then follow with -->\n    <!-- the associated locators.                           -->\n\n    <!-- First key differs from predecessor, or leads letter group  -->\n    <!-- if $empty2 is true, then headings are complete and time to -->\n    <!-- write locators.  The next conditional will fail so no more -->\n    <!-- output for this heading group. -->\n    <xsl:if test=\"not($match1)\">\n        <xsl:call-template name=\"present-index-heading\">\n            <xsl:with-param name=\"the-index-list\" select=\"$the-index-list\"/>\n            <xsl:with-param name=\"heading-group\" select=\"$heading-group\"/>\n            <xsl:with-param name=\"b-write-locators\" select=\"$empty2\"/>\n            <xsl:with-param name=\"heading-level\" select=\"1\"/>\n            <xsl:with-param name=\"content\" select=\"$pattern/text[1]/node()\"/>\n        </xsl:call-template>\n    </xsl:if>\n\n    <!-- Second key is substantial, and mis-match is in the second key,  -->\n    <!-- or first key (ie to the left).  If $empty3 is true, then        -->\n    <!-- headings are complete and time to write locators.  The next     -->\n    <!-- conditional will fail so no more output for this heading group. -->\n    <xsl:if test=\"not($empty2) and (not($match1) or not($match2))\">\n        <xsl:call-template name=\"present-index-heading\">\n            <xsl:with-param name=\"the-index-list\" select=\"$the-index-list\"/>\n            <xsl:with-param name=\"heading-group\" select=\"$heading-group\"/>\n            <xsl:with-param name=\"b-write-locators\" select=\"$empty3\"/>\n            <xsl:with-param name=\"heading-level\" select=\"2\"/>\n            <xsl:with-param name=\"content\" select=\"$pattern/text[2]/node()\"/>\n        </xsl:call-template>\n    </xsl:if>\n\n    <!-- Third key is substantial, and mis-match is in the first key, -->\n    <!-- the second key, or the third key (ie to the left).  Last     -->\n    <!-- chance to write locators, so we pass true.                   -->\n    <xsl:if test=\"not($empty3) and (not($match1) or not($match2) or not($match3))\">\n        <xsl:call-template name=\"present-index-heading\">\n            <xsl:with-param name=\"the-index-list\" select=\"$the-index-list\"/>\n            <xsl:with-param name=\"heading-group\" select=\"$heading-group\"/>\n            <xsl:with-param name=\"b-write-locators\" select=\"true()\"/>\n            <xsl:with-param name=\"heading-level\" select=\"3\"/>\n            <xsl:with-param name=\"content\" select=\"$pattern/text[3]/node()\"/>\n        </xsl:call-template>\n    </xsl:if>\n</xsl:template>\n\n<xsl:template name=\"present-index-heading\">\n    <xsl:param name=\"the-index-list\"/>\n    <xsl:param name=\"heading-group\"/>\n    <xsl:param name=\"b-write-locators\"/>\n    <xsl:param name=\"heading-level\"/>\n    <xsl:param name=\"content\"/>\n\n    <xsl:message>PTX:BUG:    a conversion to a new output format requires implementation of a named template (\"present-index-heading\") in order to format a single heading of an index entry.</xsl:message>\n</xsl:template>\n\n\n<!-- Place all the locators into the div for -->\n<!-- the final (sub)item in its own span.    -->\n\n<!-- Chicago Manual of Style, 15th edition, 18.14 - 18.22  -->\n<!-- \"see\", following main entry, 18.16                    -->\n<!--    Period after entry                                 -->\n<!--    \"See\" capitalized (assumed from localization file) -->\n<!--     multiple: alphabetical order, semicolon separator -->\n<!-- \"see\", following a subentry, 18.17                    -->\n<!--    Space after entry                                  -->\n<!--    \"see\" lower case                                   -->\n<!--    wrapped in parentheses                             -->\n<!-- \"see also\", following main entry, 18.19               -->\n<!--    Period after entry                                 -->\n<!--    \"See\" capitalized (assumed from localization file) -->\n<!--     multiple: alphabetical order, semicolon separator -->\n<!-- \"see\", following a subentry, 18.19                    -->\n<!--    Space after entry                                  -->\n<!--    \"see\" lower case                                   -->\n<!--    wrapped in parentheses                             -->\n<!-- generic references, 18.22                             -->\n<!--   TODO: use content of \"see\" and \"seealso\"            -->\n<xsl:template name=\"locator-list\">\n    <xsl:param name=\"the-index-list\"/>\n    <xsl:param name=\"heading-group\"/>\n    <xsl:param name=\"cross-reference-separator\"/>\n\n    <!-- Some formatting depends on presence of subentries -->\n    <xsl:variable name=\"b-has-subentry\" select=\"not(text[2] = '')\"/>\n    <!-- range through node-list, making cross-references -->\n    <!-- Use a comma after the heading, then prefix each  -->\n    <!-- cross-reference with a space as separators       -->\n    <xsl:call-template name=\"present-index-locator\">\n        <xsl:with-param name=\"content\">\n            <xsl:choose>\n                <xsl:when test=\"$heading-group/see and not($b-has-subentry)\">\n                    <xsl:text>. </xsl:text>\n                </xsl:when>\n                <!-- no punctuation, will earn parentheses -->\n                <xsl:when test=\"$heading-group/see and $b-has-subentry\">\n                    <xsl:text> </xsl:text>\n                </xsl:when>\n                <!-- cross-reference, w/ or w/out \"see also\" -->\n                <!-- don't do anything as we will prefix     -->\n                <!-- instances of \"cross-reference\" below    -->\n                <xsl:otherwise/>\n            </xsl:choose>\n            <!-- course over the \"index\" in the group -->\n            <xsl:for-each select=\"$heading-group\">\n                <xsl:choose>\n                    <!--  -->\n                    <xsl:when test=\"cross-reference\">\n                        <!-- *prefix* with a separator, since we do not     -->\n                        <!-- create it previously and this way we can avoid -->\n                        <!-- determining the last \"cross-reference\" element -->\n                        <!-- (which seems difficult)                        -->\n                        <xsl:value-of select=\"$cross-reference-separator\"/>\n                        <xsl:copy-of select=\"cross-reference/node()\"/>\n                    </xsl:when>\n                    <!--  -->\n                    <!-- Various uses of  position()  here are not as dangerous -->\n                    <!-- as they seem, since the nodeset comes from an RTF of   -->\n                    <!-- our construction.  Still, remove them in an eventual   -->\n                    <!-- refactor and abstraction of index construction.        -->\n                    <xsl:when test=\"see\">\n                        <xsl:call-template name=\"present-index-see\">\n                            <xsl:with-param name=\"content\">\n                            <xsl:if test=\"position() = 1\">\n                                <xsl:if test=\"$b-has-subentry\">\n                                    <xsl:text>(</xsl:text>\n                                </xsl:if>\n                                <xsl:call-template name=\"present-index-italics\">\n                                    <xsl:with-param name=\"content\">\n                                    <xsl:choose>\n                                        <xsl:when test=\"$b-has-subentry\">\n                                            <!-- lower-case \"see\" -->\n                                            <xsl:variable name=\"upper\">\n                                                <xsl:apply-templates select=\"$the-index-list\" mode=\"type-name\">\n                                                    <xsl:with-param name=\"string-id\" select=\"'see'\"/>\n                                                </xsl:apply-templates>\n                                            </xsl:variable>\n                                            <xsl:value-of select=\"translate(substring($upper, 1, 1), &UPPERCASE;, &LOWERCASE;)\"/>\n                                            <xsl:value-of select=\"substring($upper, 2)\"/>\n                                        </xsl:when>\n                                        <xsl:otherwise>\n                                            <!-- upper-case \"See\" -->\n                                            <xsl:apply-templates select=\"$the-index-list\" mode=\"type-name\">\n                                                <xsl:with-param name=\"string-id\" select=\"'see'\"/>\n                                            </xsl:apply-templates>\n                                        </xsl:otherwise>\n                                    </xsl:choose>\n                                    </xsl:with-param>\n                                </xsl:call-template>\n                            </xsl:if>\n                            <!-- just a space after \"see\", before first  -->\n                            <!-- semi-colon before second and subsequent -->\n                            <xsl:choose>\n                                <xsl:when test=\"position() = 1\">\n                                    <xsl:text> </xsl:text>\n                                </xsl:when>\n                                <xsl:otherwise>\n                                    <xsl:text>; </xsl:text>\n                                </xsl:otherwise>\n                            </xsl:choose>\n                            <xsl:copy-of select=\"see/node()\" />\n                            <xsl:if test=\"$b-has-subentry and (position() = last())\">\n                                <xsl:text>)</xsl:text>\n                            </xsl:if>\n                        </xsl:with-param>\n                    </xsl:call-template>\n                    </xsl:when>\n                    <!--  -->\n                    <xsl:when test=\"seealso\">\n                        <xsl:if test=\"preceding-sibling::index[1]/cross-reference and not($b-has-subentry)\">\n                            <xsl:text>. </xsl:text>\n                        </xsl:if>\n                        <xsl:call-template name=\"present-index-see-also\">\n                            <xsl:with-param name=\"content\">\n                            <xsl:choose>\n                                <xsl:when test=\"preceding-sibling::index[1]/cross-reference\">\n                                    <xsl:choose>\n                                        <xsl:when test=\"$b-has-subentry\">\n                                            <xsl:text> </xsl:text>\n                                            <xsl:text>(</xsl:text>\n                                            <xsl:call-template name=\"present-index-italics\">\n                                                <xsl:with-param name=\"content\">\n                                                <!-- lower-case \"see also\" -->\n                                                <xsl:variable name=\"upper\">\n                                                    <xsl:apply-templates select=\"$the-index-list\" mode=\"type-name\">\n                                                            <xsl:with-param name=\"string-id\" select=\"'also'\"/>\n                                                    </xsl:apply-templates>\n                                                </xsl:variable>\n                                                <xsl:value-of select=\"translate(substring($upper, 1, 1), &UPPERCASE;, &LOWERCASE;)\"/>\n                                                <xsl:value-of select=\"substring($upper, 2)\"/>\n                                                </xsl:with-param>\n                                            </xsl:call-template>\n                                        </xsl:when>\n                                        <xsl:otherwise>\n                                            <xsl:call-template name=\"present-index-italics\">\n                                                <xsl:with-param name=\"content\">\n                                                <!-- upper-case \"See also\" -->\n                                                <xsl:apply-templates select=\"$the-index-list\" mode=\"type-name\">\n                                                        <xsl:with-param name=\"string-id\" select=\"'also'\"/>\n                                                </xsl:apply-templates>\n                                                </xsl:with-param>\n                                            </xsl:call-template>\n                                        </xsl:otherwise>\n                                    </xsl:choose>\n                                </xsl:when>\n                                <xsl:otherwise>\n                                    <xsl:text>;</xsl:text>\n                                </xsl:otherwise>\n                            </xsl:choose>\n                            <xsl:text> </xsl:text>\n                            <xsl:copy-of select=\"seealso/node()\"/>\n                            <xsl:if test=\"(position() = last()) and $b-has-subentry\">\n                                <xsl:text>)</xsl:text>\n                            </xsl:if>\n                        </xsl:with-param>\n                    </xsl:call-template>\n                    </xsl:when>\n                </xsl:choose>\n            </xsl:for-each>\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n\n<xsl:template name=\"present-index-locator\">\n    <xsl:param name=\"content\"/>\n\n    <xsl:message>PTX:BUG:    a conversion to a new output format requires implementation of a named template (\"present-index-locator\") in order to format a locator at the end of an index entry.</xsl:message>\n</xsl:template>\n\n<xsl:template name=\"present-index-see\">\n    <xsl:param name=\"content\"/>\n\n    <xsl:message>PTX:BUG:    a conversion to a new output format requires implementation of a named template (\"present-index-see\") in order to format a \"see\" cross-reference at the end of an index entry.</xsl:message>\n</xsl:template>\n\n<xsl:template name=\"present-index-see-also\">\n    <xsl:param name=\"content\"/>\n\n    <xsl:message>PTX:BUG:    a conversion to a new output format requires implementation of a named template (\"present-index-see-also\") in order to format a \"see also\" coross-reference at the end of an index entry.</xsl:message>\n</xsl:template>\n\n<xsl:template name=\"present-index-italics\">\n    <xsl:param name=\"content\"/>\n\n    <xsl:message>PTX:BUG:    a conversion to a new output format requires implementation of a named template (\"present-index-italics\") in order to format italic text at the end of an index entry.</xsl:message>\n</xsl:template>\n\n\n\n<!-- ############### -->\n<!-- Arbitrary Lists -->\n<!-- ############### -->\n\n<!-- Format-independent construction of a list of    -->\n<!-- intermediate elements, in order of appearance,  -->\n<!-- with headings from indicated divisions          -->\n<!--                                                 -->\n<!-- Implementation requires four abstract templates -->\n<!--                                                 -->\n<!-- 1.  name=\"list-of-begin\"                        -->\n<!-- hook for start of list                          -->\n<!--                                                 -->\n<!-- 2.  mode=\"list-of-heading\"                      -->\n<!-- Format/output per division                      -->\n<!--                                                 -->\n<!-- 3.  mode=\"list-of-element\"                      -->\n<!-- Format/output per element                       -->\n<!--                                                 -->\n<!-- 4. name=\"list-of-end\"                           -->\n<!-- hook for end of list                            -->\n\n<!-- NB: possible improvements -->\n<!-- 1.  Get $subroot via @ref and work with element, not a string            -->\n<!-- 2.  Somehow abandon user strings sooner, so less reliant on local-name() -->\n\n<xsl:template match=\"list-of\">\n    <xsl:param name=\"heading-level\"/>\n\n    <!-- \"str:tokenize()\" in this form makes a node-set, which has no root -->\n    <!-- the elements may be \"token\" but that is irrelevant for use below  -->\n    <!-- Documentation may say spaces, we also allow comma as a delimiter  -->\n    <xsl:variable name=\"elements\" select=\"str:tokenize(@elements, ', ')\"/>\n    <xsl:variable name=\"divisions\" select=\"str:tokenize(@divisions, ', ')\"/>\n    <!-- Lists of various types of exercises can be useful, but they are         -->\n    <!-- categorized by their ancestors.  So we recognize certain strings        -->\n    <!-- as \"pseudo-elements\".  We do this once and then pass them along.        -->\n    <!--                                                                         -->\n    <!--   * inlineexercise                                                      -->\n    <!--   * divisionexercise                                                    -->\n    <!--   * worksheetexercise                                                   -->\n    <!--   * readingquestion                                                     -->\n    <!--                                                                         -->\n    <!-- Equality of strings (e.g. 'inlineexercise') and the node-set ($elements)-->\n    <!-- is true when the *string-value* of *one* node in the set is identical   -->\n    <!-- NB: if this gets out-of-hand, it should be passed as a structure        -->\n    <xsl:variable name=\"b-inline-exercises\" select=\"'inlineexercise' = $elements\"/>\n    <xsl:variable name=\"b-division-exercises\" select=\"'divisionexercise' = $elements\"/>\n    <xsl:variable name=\"b-worksheet-exercises\" select=\"'worksheetexercise' = $elements\"/>\n    <xsl:variable name=\"b-reading-questions\" select=\"'readingquestion' = $elements\"/>\n    <!-- display subdivision headings with empty contents? -->\n    <xsl:variable name=\"entered-empty\">\n        <xsl:choose>\n            <xsl:when test=\"not(@empty)\">\n                <xsl:text>no</xsl:text>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"@empty\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- Schema restricts to 'yes' or 'no'.  Thus we can just interpret -->\n    <!-- absent or anything-but-yes indicating to skip empty divisions. -->\n    <xsl:variable name=\"b-empty\" select=\"$entered-empty = 'yes'\"/>\n    <!-- root of the document subtree for list formation     -->\n    <!-- defaults to document-wide                           -->\n    <!-- DTD should enforce subdivisions as values for scope -->\n    <!-- TODO: perhaps use @ref to indicate $subroot,  -->\n    <!-- and protect against both a @scope and a @ref  -->\n    <xsl:variable name=\"scope\">\n        <xsl:choose>\n            <xsl:when test=\"@scope\">\n                <xsl:value-of select=\"@scope\" />\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"local-name($document-root)\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"subroot\" select=\"ancestor-or-self::*[local-name() = $scope]\" />\n    <!-- variable behavior set, now setup -->\n    <xsl:call-template name=\"list-of-begin\" />\n    <!-- recursive procedure, starting from indicated scope -->\n    <xsl:apply-templates select=\"$subroot\" mode=\"list-of-content\">\n        <!-- list-of was passed a heading level that was incremented by its parent division -->\n        <!-- Since the list-of has no heading itself, we back this up by 1                  -->\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level - 1\"/>\n        <xsl:with-param name=\"elements\" select=\"$elements\"/>\n        <xsl:with-param name=\"divisions\" select=\"$divisions\"/>\n        <xsl:with-param name=\"b-empty\" select=\"$b-empty\"/>\n        <xsl:with-param name=\"b-inline-exercises\" select=\"$b-inline-exercises\"/>\n        <xsl:with-param name=\"b-division-exercises\" select=\"$b-division-exercises\"/>\n        <xsl:with-param name=\"b-worksheet-exercises\" select=\"$b-worksheet-exercises\"/>\n        <xsl:with-param name=\"b-reading-questions\" select=\"$b-reading-questions\"/>\n    </xsl:apply-templates>\n    <xsl:call-template name=\"list-of-end\" />\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"list-of-content\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:param name=\"elements\"/>\n    <xsl:param name=\"divisions\"/>\n    <xsl:param name=\"b-empty\"/>\n    <xsl:param name=\"b-inline-exercises\"/>\n    <xsl:param name=\"b-division-exercises\"/>\n    <xsl:param name=\"b-worksheet-exercises\"/>\n    <xsl:param name=\"b-reading-questions\"/>\n\n    <!-- Check if we are at a divison that needs a heading                      -->\n    <!-- match only the default namespace                                       -->\n    <xsl:variable name=\"b-division-element\" select=\"(local-name(.) = $divisions) and (namespace-uri(.) = '')\"/>\n    <xsl:choose>\n        <xsl:when test=\"$b-division-element\">\n            <!-- handling a division element that *may* need a heading -->\n            <xsl:choose>\n                <xsl:when test=\"not($b-empty)\">\n                    <!-- probe subtree, even if we found empty super-tree earlier -->\n                    <!-- to see if a heading is *needed*, author has elected to   -->\n                    <!-- not have a heading if there are no elements to list      -->\n                    <!-- N.B. these booleans look rather expensive, owing to the  -->\n                    <!-- extensive searching for \"exercise\", but we hope the      -->\n                    <!-- booleans passed in will short-circuit and result in no   -->\n                    <!-- searching when it is not necessary                       -->\n                    <!-- match only the default namespace                         -->\n                    <xsl:variable name=\"by-name-elements\" select=\"boolean(.//*[(local-name(.) = $elements) and (namespace-uri(.) = '')])\" />\n                    <xsl:variable name=\"division-exercises\" select=\"$b-division-exercises and .//exercise[ancestor::exercises]\"/>\n                    <xsl:variable name=\"worksheet-exercises\" select=\"$b-worksheet-exercises and .//exercise[ancestor::worksheet]\"/>\n                    <xsl:variable name=\"reading-questions\" select=\"$b-reading-questions and .//exercise[ancestor::reading-questions]\"/>\n                    <xsl:variable name=\"inline-exercises\" select=\"$b-inline-exercises and .//exercise[not(ancestor::exercises or ancestor::worksheet or ancestor::reading-questions)]\"/>\n                    <xsl:variable name=\"any-elements\" select=\"$by-name-elements or $inline-exercises or $division-exercises or $worksheet-exercises or $reading-questions\"/>\n                    <xsl:if test=\"$any-elements\">\n                        <xsl:apply-templates select=\".\" mode=\"list-of-heading\">\n                            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                        </xsl:apply-templates>\n                    </xsl:if>\n                </xsl:when>\n                <xsl:when test=\"$b-empty\">\n                    <!-- always write a heading, even if there will be no items listed -->\n                    <xsl:apply-templates select=\".\" mode=\"list-of-heading\">\n                        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                    </xsl:apply-templates>\n                </xsl:when>\n            </xsl:choose>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- not at a division, so test element for inclusion -->\n            <!-- match only the default namespace                 -->\n            <xsl:if test=\"((local-name(.) = $elements) and (namespace-uri(.) = ''))\n                       or ($b-division-exercises and self::exercise and ancestor::exercises)\n                       or ($b-worksheet-exercises and self::exercise and ancestor::worksheet)\n                       or ($b-reading-questions and self::exercise and ancestor::reading-questions)\n                       or ($b-inline-exercises and self::exercise and not(ancestor::exercises or ancestor::worksheet or ancestor::reading-questions))\">\n                <xsl:apply-templates select=\".\" mode=\"list-of-element\" />\n            </xsl:if>\n        </xsl:otherwise>\n    </xsl:choose>\n    <!-- recurse into children; recursion ends when no children   -->\n    <!-- increment heading-level, correct right now for divisions -->\n    <xsl:apply-templates select=\"*\" mode=\"list-of-content\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level + 1\"/>\n        <xsl:with-param name=\"elements\" select=\"$elements\"/>\n        <xsl:with-param name=\"divisions\" select=\"$divisions\"/>\n        <xsl:with-param name=\"b-empty\" select=\"$b-empty\"/>\n        <xsl:with-param name=\"b-inline-exercises\" select=\"$b-inline-exercises\"/>\n        <xsl:with-param name=\"b-division-exercises\" select=\"$b-division-exercises\"/>\n        <xsl:with-param name=\"b-worksheet-exercises\" select=\"$b-worksheet-exercises\"/>\n        <xsl:with-param name=\"b-reading-questions\" select=\"$b-reading-questions\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Stub implementations, with warnings -->\n<xsl:template name=\"list-of-begin\">\n     <xsl:message>PTX:BUG:   the \"list-of-begin\" template needs an implementation in the current conversion</xsl:message>\n     <xsl:text>[[[BEGINLIST]]]</xsl:text>\n </xsl:template>\n\n<xsl:template name=\"list-of-end\">\n     <xsl:message>PTX:BUG:   the \"list-of-end\" template needs an implementation in the current conversion</xsl:message>\n     <xsl:text>[[[ENDLIST]]]</xsl:text>\n </xsl:template>\n\n\n<!-- Programming Language Names -->\n<!-- Packages for listing and syntax highlighting      -->\n<!-- have their own ideas about the names of languages -->\n<!-- We use keys to perform the translation            -->\n\n<!-- The data: attribute is our usage, elements belong to     -->\n<!-- other packages. Blank means not explicitly supported.    -->\n<!-- Alphabetical by type.                                    -->\n\n<!-- Prism: -->\n<!-- Last reviewed 2020-10-21                        -->\n<!-- 2020-10-21: Cutover from Google Code Prettifier -->\n\n<!-- Listings: -->\n<!-- Last reviewed carefully: 2014/06/28           -->\n<!-- Exact matches, or best guesses, some          -->\n<!-- unimplemented.  [] notation is for variants.  -->\n<!-- 2019-09-23: minor review, v 1.7 (2018-09-02)  -->\n\n<!-- ActiveCode (Runestone) -->\n<!-- Languages supported by Runestone ActiveCode and  -->\n<!-- CodeLens interactive elements, added 2020-08-13. -->\n<!-- \"python3\" is just on Runestone servers where     -->\n<!-- additional popular packages (e.g. numpy, pandas) -->\n<!-- are available.                                   -->\n\n<!-- Our strings (@name) are always all-lowercase, no symbols, no punctuation -->\n<xsl:variable name=\"programming-language-rtf\">\n    <!-- Procedural -->\n    <language name=\"basic\"      active=\"\"            listings=\"Basic\"            prism=\"basic\"/>\n    <language name=\"c\"          active=\"c\"           listings=\"C\"                prism=\"c\"/>\n    <language name=\"cpp\"        active=\"cpp\"         listings=\"C++\"              prism=\"cpp\"/>\n    <!-- using Python as a closest match for now in listings. -->\n    <language name=\"gdscript\"   active=\"gdscript\"    listings=\"Python\"           prism=\"gdscript\"/>\n    <language name=\"go\"         active=\"\"            listings=\"C\"                prism=\"go\"/>\n    <language name=\"java\"       active=\"java\"        listings=\"Java\"             prism=\"java\"/>\n    <language name=\"javascript\" active=\"javascript\"  listings=\"\"                 prism=\"javascript\"/>\n    <language name=\"kotlin\"     active=\"kotlin\"      listings=\"\"                 prism=\"kotlin\"/>\n    <language name=\"lua\"        active=\"\"            listings=\"Lua\"              prism=\"lua\"/>\n    <language name=\"pascal\"     active=\"\"            listings=\"Pascal\"           prism=\"pascal\"/>\n    <language name=\"perl\"       active=\"\"            listings=\"Perl\"             prism=\"perl\"/>\n    <language name=\"python\"     active=\"python\"      listings=\"Python\"           prism=\"py\"/>\n    <language name=\"python3\"    active=\"python3\"     listings=\"Python\"           prism=\"py\"/>\n    <language name=\"r\"          active=\"\"            listings=\"R\"                prism=\"r\"/>\n    <language name=\"s\"          active=\"\"            listings=\"S\"                prism=\"s\"/>\n    <language name=\"sas\"        active=\"\"            listings=\"SAS\"              prism=\"s\"/>\n    <language name=\"sage\"       active=\"\"            listings=\"Python\"           prism=\"py\"/>\n    <language name=\"splus\"      active=\"\"            listings=\"[Plus]S\"          prism=\"s\"/>\n    <language name=\"vbasic\"     active=\"\"            listings=\"[Visual]Basic\"    prism=\"visual-basic\"/>\n    <language name=\"vbscript\"   active=\"\"            listings=\"VBscript\"         prism=\"visual-basic\"/>\n    <!-- Others (esp. functional)  -->\n    <language name=\"clojure\"    active=\"\"            listings=\"Lisp\"             prism=\"clojure\"/>\n    <language name=\"lisp\"       active=\"\"            listings=\"Lisp\"             prism=\"lisp\"/>\n    <language name=\"clisp\"      active=\"\"            listings=\"Lisp\"             prism=\"lisp\"/>\n    <language name=\"elisp\"      active=\"\"            listings=\"Lisp\"             prism=\"elisp\"/>\n    <language name=\"scheme\"     active=\"\"            listings=\"Lisp\"             prism=\"scheme\"/>\n    <language name=\"racket\"     active=\"\"            listings=\"Lisp\"             prism=\"racket\"/>\n    <language name=\"sql\"        active=\"sql\"         listings=\"SQL\"              prism=\"sql\"/>\n    <language name=\"llvm\"       active=\"\"            listings=\"LLVM\"             prism=\"llvm\"/>\n    <language name=\"matlab\"     active=\"\"            listings=\"Matlab\"           prism=\"matlab\"/>\n    <language name=\"octave\"     active=\"octave\"      listings=\"Octave\"           prism=\"matlab\"/>\n    <language name=\"ml\"         active=\"\"            listings=\"ML\"               prism=\"\"/>\n    <language name=\"ocaml\"      active=\"\"            listings=\"[Objective]Caml\"  prism=\"ocaml\"/>\n    <language name=\"fsharp\"     active=\"\"            listings=\"ML\"               prism=\"fsharp\"/>\n    <!-- Text Manipulation -->\n    <language name=\"css\"        active=\"\"            listings=\"\"                 prism=\"css\"/>\n    <language name=\"latex\"      active=\"\"            listings=\"[LaTeX]TeX\"       prism=\"latex\"/>\n    <language name=\"html\"       active=\"html\"        listings=\"HTML\"             prism=\"html\"/>\n    <language name=\"tex\"        active=\"\"            listings=\"[plain]TeX\"       prism=\"tex\"/>\n    <language name=\"xml\"        active=\"\"            listings=\"XML\"              prism=\"xml\"/>\n    <language name=\"xslt\"       active=\"\"            listings=\"XSLT\"             prism=\"xml\"/>\n</xsl:variable>\n\n<xsl:variable name=\"programming-language-table\"\n    select=\"exsl:node-set($programming-language-rtf)\"/>\n\n<!-- Define the key for indexing into the data list -->\n<xsl:key name=\"programming-language-key\" match=\"language\" use=\"@name\"/>\n\n<!-- Define variables for default active language - will be picked up by -->\n<!-- RS manifest and can be a different string than the raw language. -->\n<!-- NB: the language-default templates and variables here can be     -->\n<!-- invoked from within the assembly chain's \"representations\" pass  -->\n<!-- (via import precedence over their near-duplicates in the         -->\n<!-- -runestone-static stylesheet), where the tree behind  $docinfo   -->\n<!-- does not exist yet and referencing it is a circular definition.  -->\n<!-- So they read the version tree, and must recognize both the       -->\n<!-- \"docinfo/defaults\" home (preferred) and the deprecated top-level -->\n<!-- placement, which the later \"repair\" pass would have normalized.  -->\n<xsl:variable name=\"docinfo-programs-language\">\n    <xsl:choose>\n        <xsl:when test=\"$version-docinfo/defaults/programs/@language\">\n            <xsl:value-of select=\"$version-docinfo/defaults/programs/@language\"/>\n        </xsl:when>\n        <xsl:when test=\"$version-docinfo/programs/@language\">\n            <xsl:value-of select=\"$version-docinfo/programs/@language\"/>\n        </xsl:when>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"default-active-programming-language\">\n    <xsl:if test=\"not($docinfo-programs-language = '')\">\n        <xsl:for-each select=\"$programming-language-table\">\n            <xsl:value-of select=\"key('programming-language-key', $docinfo-programs-language)/@active\" />\n        </xsl:for-each>\n    </xsl:if>\n</xsl:variable>\n\n<!-- The content of a \"slide\" of a \"slideshow\" may be placed at   -->\n<!-- the top, middle, or bottom of the slide.  A document-wide    -->\n<!-- default comes from \"docinfo/defaults/slides/@valign\"; absent -->\n<!-- an expressed preference, content is placed at the top.       -->\n<xsl:variable name=\"slides-valign-default\">\n    <xsl:choose>\n        <xsl:when test=\"$docinfo/defaults/slides/@valign\">\n            <xsl:value-of select=\"$docinfo/defaults/slides/@valign\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>top</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- A \"slide\" may override the document-wide default with its  -->\n<!-- own \"@valign\"; the conversions consult this modal template -->\n<!-- for the effective vertical alignment of a slide's content. -->\n<xsl:template match=\"slide\" mode=\"valign\">\n    <xsl:choose>\n        <xsl:when test=\"@valign\">\n            <xsl:value-of select=\"@valign\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"$slides-valign-default\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Determine programming language to use. First choice is @language     -->\n<!-- on current element. If that is not available, check docinfo default. -->\n<!-- \"exercise\" might be a Runestone interactive (programming) exercise.  -->\n<xsl:template match=\"program|pf\" mode=\"get-programming-language\">\n    <xsl:call-template name=\"get-program-attr-or-default\">\n        <xsl:with-param name=\"attr\" select=\"'language'\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- For a parsons, use @language, default parsons language, or default -->\n<!-- programming language in that order of preference.                  -->\n<xsl:template match=\"*[@pi:exercise-interactive = 'parson' or @pi:exercise-interactive = 'parson-horizontal']\" mode=\"get-programming-language\">\n    <xsl:choose>\n        <xsl:when test=\"@language\">\n            <xsl:value-of select=\"@language\" />\n        </xsl:when>\n        <xsl:when test=\"$version-docinfo/defaults/parsons/@language\">\n            <xsl:value-of select=\"$version-docinfo/defaults/parsons/@language\" />\n        </xsl:when>\n        <xsl:when test=\"$version-docinfo/parsons/@language\">\n            <xsl:value-of select=\"$version-docinfo/parsons/@language\" />\n        </xsl:when>\n        <xsl:when test=\"not($docinfo-programs-language = '')\">\n            <xsl:value-of select=\"$docinfo-programs-language\" />\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n<!-- A whole <program> node comes in,  -->\n<!-- text of ActiveCode name comes out -->\n<xsl:template match=\"program|*[@pi:exercise-interactive = 'parson' or @pi:exercise-interactive = 'parson-horizontal']\" mode=\"active-language\">\n    <xsl:variable name=\"language\">\n        <xsl:apply-templates select=\".\" mode=\"get-programming-language\"/>\n    </xsl:variable>\n    <xsl:for-each select=\"$programming-language-table\">\n        <xsl:value-of select=\"key('programming-language-key', $language)/@active\" />\n    </xsl:for-each>\n</xsl:template>\n\n<!-- A whole <program> node comes in,  -->\n<!-- text of listings name comes out -->\n<xsl:template match=\"program|pf\" mode=\"listings-language\">\n    <xsl:variable name=\"language\">\n        <xsl:apply-templates select=\".\" mode=\"get-programming-language\"/>\n    </xsl:variable>\n    <xsl:for-each select=\"$programming-language-table\">\n        <xsl:value-of select=\"key('programming-language-key', $language)/@listings\" />\n    </xsl:for-each>\n</xsl:template>\n\n<!-- A whole <program> node comes in,  -->\n<!-- text of prism name comes out -->\n<xsl:template match=\"program|pf\" mode=\"prism-language\">\n    <xsl:variable name=\"language\">\n        <xsl:apply-templates select=\".\" mode=\"get-programming-language\"/>\n    </xsl:variable>\n    <xsl:for-each select=\"$programming-language-table\">\n        <xsl:value-of select=\"key('programming-language-key', $language)/@prism\" />\n    </xsl:for-each>\n</xsl:template>\n\n<!-- Try an attribute, and if it does not exist, try to get it from docinfo -->\n<!-- if that fails, use the optional default passed in                      -->\n<xsl:template name=\"get-program-attr-or-default\">\n    <xsl:param name=\"attr\"/>\n    <xsl:param name=\"default\" select=\"''\"/>\n    <xsl:choose>\n        <xsl:when test=\"@*[name() = $attr]\">\n            <xsl:value-of select=\"@*[name() = $attr]\" />\n        </xsl:when>\n        <xsl:when test=\"$version-docinfo/defaults/programs/@*[name() = $attr]\">\n            <xsl:value-of select=\"$version-docinfo/defaults/programs/@*[name() = $attr]\" />\n        </xsl:when>\n        <xsl:when test=\"$version-docinfo/programs/@*[name() = $attr]\">\n            <xsl:value-of select=\"$version-docinfo/programs/@*[name() = $attr]\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"$default\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Helper templates to ensure consistent processing of whitespace in programs. -->\n<!-- We trim leading/trailing whitespace, but preserve possible intentionally    -->\n<!-- authored space as follows:                                                  -->\n<!--   preamble: preserve trailing                                               -->\n<!--   code: preserve leading/trailing                                           -->\n<!--   postamble/tests: preserve leading                                         -->\n<xsl:template match=\"preamble|code|postamble|tests\" mode=\"program-part-processing\">\n    <xsl:call-template name=\"trim-start-lines\">\n        <xsl:with-param name=\"text\">\n            <xsl:call-template name=\"trim-end\">\n                <!-- only include immediate text content                   -->\n                <!-- we want to exclude any nested elements (tests/iotest) -->\n                <xsl:with-param name=\"text\" select=\"text()\" />\n                <xsl:with-param name=\"preserve-intentional\" select=\"self::preamble or self::code\" />\n            </xsl:call-template>\n        </xsl:with-param>\n        <xsl:with-param name=\"preserve-intentional\" select=\"self::code or self::postamble or self::tests\" />\n    </xsl:call-template>\n</xsl:template>\n\n<!-- ############################ -->\n<!-- Table construction utilities -->\n<!-- ############################ -->\n\n<!-- These templates provide frequently-used      -->\n<!-- functions for the construction of tables.    -->\n<!-- Document uses carefully when newly employed. -->\n\n<!-- Translate thickness attribute value to integer short name.  -->\n<!-- HTML: makes portion of CSS class names for cells.           -->\n<!-- PG: makes portion of optional parameter for DataTable       -->\n<!-- macro from niceTable.pl for thickness of table cells.       -->\n<!-- The schema restricts callers' @top, @bottom, @left, @right  -->\n<!-- (on \"tabular\", \"row\", \"col\", \"cell\") to these four values,  -->\n<!-- so no defensive otherwise is needed.                        -->\n<xsl:template name=\"thickness-specification\">\n    <xsl:param name=\"width\" />\n    <xsl:choose>\n        <xsl:when test=\"$width='none'\">\n            <xsl:text>0</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$width='minor'\">\n            <xsl:text>1</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$width='medium'\">\n            <xsl:text>2</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$width='major'\">\n            <xsl:text>3</xsl:text>\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Translate horizontal alignment to CSS short name.            -->\n<!-- HTML:  makes portion of CSS class names for cells.           -->\n<!-- LaTeX: provides standard LaTeX horizontal alignment.         -->\n<!-- PG: provide LaTeX-style alignment string for the             -->\n<!-- DataTable macro from niceTable.pl.                           -->\n<!-- The schema restricts callers' @halign (on \"tabular\", \"row\",  -->\n<!-- \"col\", \"cell\") to these four values, so no defensive         -->\n<!-- otherwise is needed.                                         -->\n<xsl:template name=\"halign-specification\">\n    <xsl:param name=\"align\" />\n    <xsl:choose>\n        <xsl:when test=\"$align='left' or $align='justify'\">\n            <xsl:text>l</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$align='center'\">\n            <xsl:text>c</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$align='right'\">\n            <xsl:text>r</xsl:text>\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Translate vertical alignment to CSS short name.              -->\n<!-- HTML:  makes portion of CSS class names for cells.           -->\n<!-- LaTeX: provides one standard LaTeX vertical alignment.       -->\n<!-- PG: provide LaTeX-style alignment string for the             -->\n<!-- DataTable macro from niceTable.pl.                           -->\n<!-- The schema restricts callers' @valign (on \"tabular\", \"row\")  -->\n<!-- to these three values, so no defensive otherwise is needed.  -->\n<xsl:template name=\"valign-specification\">\n    <xsl:param name=\"align\" />\n    <xsl:choose>\n        <xsl:when test=\"$align='top'\">\n            <xsl:text>t</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$align='middle'\">\n            <xsl:text>m</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$align='bottom'\">\n            <xsl:text>b</xsl:text>\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Effective rule weight and alignment for a \"cell\" edge.            -->\n<!--                                                                   -->\n<!-- The rule weight (\"none\"/\"minor\"/\"medium\"/\"major\") and the        -->\n<!-- alignment for a given cell edge are determined by a precedence    -->\n<!-- ladder over the four levels at which the attribute may appear     -->\n<!-- (\"cell\", \"row\", \"col\", \"tabular\"), with a default.  That          -->\n<!-- resolution is format-independent, so it is performed once here.   -->\n<!-- Each conversion consumes the resulting token and translates it    -->\n<!-- into its own markup (a CSS class, a LaTeX rule macro or column    -->\n<!-- letter, an FO \"border\" property).                                 -->\n<!--                                                                   -->\n<!--   halign:  cell > row > col > tabular > \"left\"                    -->\n<!--   valign:  row > tabular > \"middle\"                               -->\n<!--   bottom:  cell > row > tabular > \"none\"                          -->\n<!--   right:   cell > col > tabular > \"none\"                          -->\n<!--   left:    (leading cell only) row > tabular > \"none\"             -->\n<!--   top:     (first row only)    col > tabular > \"none\"             -->\n<!--                                                                   -->\n<!-- A \"cell\" finds its \"col\" by counting columns occupied by the      -->\n<!-- preceding cells of its row (each contributes its \"@colspan\", or   -->\n<!-- 1).  The left edge of the cell is in column \"column-left-number\"; -->\n<!-- a spanning cell's right edge is in \"column-right-number\".         -->\n<xsl:template match=\"cell\" mode=\"column-left-number\">\n    <xsl:value-of select=\"1 + sum(preceding-sibling::cell/@colspan) + count(preceding-sibling::cell[not(@colspan)])\"/>\n</xsl:template>\n\n<xsl:template match=\"cell\" mode=\"column-right-number\">\n    <xsl:variable name=\"left\">\n        <xsl:apply-templates select=\".\" mode=\"column-left-number\"/>\n    </xsl:variable>\n    <xsl:variable name=\"span\">\n        <xsl:choose>\n            <xsl:when test=\"@colspan\">\n                <xsl:value-of select=\"@colspan\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>1</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:value-of select=\"$left + $span - 1\"/>\n</xsl:template>\n\n<!-- The number of columns in a \"tabular\": the count of \"col\" elements  -->\n<!-- when a column group is present, otherwise the widest row (each      -->\n<!-- cell counting as its \"@colspan\", or one).  A well-formed table has  -->\n<!-- every row that wide; a ragged one (flagged by validation) is given  -->\n<!-- enough columns for its widest row.                                  -->\n<xsl:template match=\"tabular\" mode=\"column-count\">\n    <xsl:choose>\n        <xsl:when test=\"col\">\n            <xsl:value-of select=\"count(col)\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:for-each select=\"row\">\n                <xsl:sort select=\"count(cell[not(@colspan)]) + sum(cell/@colspan)\" data-type=\"number\" order=\"descending\"/>\n                <xsl:if test=\"position() = 1\">\n                    <xsl:value-of select=\"count(cell[not(@colspan)]) + sum(cell/@colspan)\"/>\n                </xsl:if>\n            </xsl:for-each>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- horizontal alignment: cell > row > col > tabular > \"left\" -->\n<xsl:template match=\"cell\" mode=\"effective-halign\">\n    <xsl:variable name=\"left-number\">\n        <xsl:apply-templates select=\".\" mode=\"column-left-number\"/>\n    </xsl:variable>\n    <xsl:variable name=\"left-col\" select=\"ancestor::tabular/col[number($left-number)]\"/>\n    <xsl:choose>\n        <xsl:when test=\"@halign\">\n            <xsl:value-of select=\"@halign\"/>\n        </xsl:when>\n        <xsl:when test=\"ancestor::row/@halign\">\n            <xsl:value-of select=\"ancestor::row/@halign\"/>\n        </xsl:when>\n        <xsl:when test=\"$left-col/@halign\">\n            <xsl:value-of select=\"$left-col/@halign\"/>\n        </xsl:when>\n        <xsl:when test=\"ancestor::tabular/@halign\">\n            <xsl:value-of select=\"ancestor::tabular/@halign\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>left</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- vertical alignment: row > tabular > \"middle\" -->\n<xsl:template match=\"cell\" mode=\"effective-valign\">\n    <xsl:choose>\n        <xsl:when test=\"ancestor::row/@valign\">\n            <xsl:value-of select=\"ancestor::row/@valign\"/>\n        </xsl:when>\n        <xsl:when test=\"ancestor::tabular/@valign\">\n            <xsl:value-of select=\"ancestor::tabular/@valign\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>middle</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- bottom rule: cell > row > tabular > \"none\" -->\n<xsl:template match=\"cell\" mode=\"effective-bottom\">\n    <xsl:choose>\n        <xsl:when test=\"@bottom\">\n            <xsl:value-of select=\"@bottom\"/>\n        </xsl:when>\n        <xsl:when test=\"ancestor::row/@bottom\">\n            <xsl:value-of select=\"ancestor::row/@bottom\"/>\n        </xsl:when>\n        <xsl:when test=\"ancestor::tabular/@bottom\">\n            <xsl:value-of select=\"ancestor::tabular/@bottom\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>none</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- right rule: cell > col > tabular > \"none\" -->\n<xsl:template match=\"cell\" mode=\"effective-right\">\n    <xsl:variable name=\"right-number\">\n        <xsl:apply-templates select=\".\" mode=\"column-right-number\"/>\n    </xsl:variable>\n    <xsl:variable name=\"right-col\" select=\"ancestor::tabular/col[number($right-number)]\"/>\n    <xsl:choose>\n        <xsl:when test=\"@right\">\n            <xsl:value-of select=\"@right\"/>\n        </xsl:when>\n        <xsl:when test=\"$right-col/@right\">\n            <xsl:value-of select=\"$right-col/@right\"/>\n        </xsl:when>\n        <xsl:when test=\"ancestor::tabular/@right\">\n            <xsl:value-of select=\"ancestor::tabular/@right\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>none</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- left rule: only the leading cell of a row has one; row > tabular > \"none\" -->\n<xsl:template match=\"cell\" mode=\"effective-left\">\n    <xsl:choose>\n        <xsl:when test=\"preceding-sibling::cell\">\n            <xsl:text>none</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"ancestor::row/@left\">\n            <xsl:value-of select=\"ancestor::row/@left\"/>\n        </xsl:when>\n        <xsl:when test=\"ancestor::tabular/@left\">\n            <xsl:value-of select=\"ancestor::tabular/@left\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>none</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- top rule: only cells of the first row have one; col > tabular > \"none\" -->\n<xsl:template match=\"cell\" mode=\"effective-top\">\n    <xsl:variable name=\"left-number\">\n        <xsl:apply-templates select=\".\" mode=\"column-left-number\"/>\n    </xsl:variable>\n    <xsl:variable name=\"left-col\" select=\"ancestor::tabular/col[number($left-number)]\"/>\n    <xsl:choose>\n        <xsl:when test=\"ancestor::row/preceding-sibling::row\">\n            <xsl:text>none</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$left-col/@top\">\n            <xsl:value-of select=\"$left-col/@top\"/>\n        </xsl:when>\n        <xsl:when test=\"ancestor::tabular/@top\">\n            <xsl:value-of select=\"ancestor::tabular/@top\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>none</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- ################### -->\n<!-- Structured by Lines -->\n<!-- ################### -->\n\n<!-- Some items, such as an address or an attribution,          -->\n<!-- can be formatted like a poem, as a sequence of lines,      -->\n<!-- without really being able to say just why or how in        -->\n<!-- advance via markup.  So the schema will allow an element   -->\n<!-- to be a simple, single line of text, OR a sequence of      -->\n<!-- \"line\" elements (only), each \"line\" being the same simple  -->\n<!-- text.  Generally, all we need is an abstract separator for -->\n<!-- the first n-1 lines.  What happens after the last line     -->\n<!-- should be in agreement with the single line version.       -->\n\n\n<!-- Allowed to be structured, and handled abstractly -->\n<!--   * department (author, editor, etc.)            -->\n<!--   * institution (author, editor, etc.)           -->\n<!--   * dedication/p                                 -->\n<!--   * attribution                                  -->\n<!--   * cell (tabular/row/cell/line)                 -->\n<!--                                                  -->\n<!-- Specialized, handled specifically (ie not here)  -->\n<!--   * poem/stanza/line                             -->\n<!--   * letter/frontmatter/to/line (from) (LaTeX)    -->\n<!--   * memo/frontmatter/to/line (from) (LaTeX)      -->\n\n<!-- The markup, and visual source necessary for the  -->\n<!-- end of each line, default indicates a problem    -->\n<!-- Needs an override for each conversion            -->\n<xsl:template name=\"line-separator\">\n    <xsl:text>[LINESEP]</xsl:text>\n</xsl:template>\n\n<!-- Explicitly assumes a sequence of \"line\" -->\n<xsl:template match=\"line\">\n    <xsl:apply-templates/>\n    <!-- is there a next line to separate? -->\n    <xsl:if test=\"following-sibling::line\">\n        <xsl:call-template name=\"line-separator\"/>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- ################ -->\n<!-- Poetry Utilities -->\n<!-- ################ -->\n\n<!-- These inherit from their containers,    -->\n<!-- which is why \"poem\" has a default value -->\n\n<xsl:template match=\"poem|poem/author|stanza|stanza/line\" mode=\"poem-indent\">\n    <xsl:choose>\n        <xsl:when test=\"@indent\">\n            <xsl:value-of select=\"@indent\" />\n        </xsl:when>\n        <xsl:when test=\"self::poem\">\n            <xsl:text>0</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\"parent::*\" mode=\"poem-indent\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"poem|poem/author|stanza|stanza/line\" mode=\"poem-halign\">\n    <xsl:choose>\n        <xsl:when test=\"@halign\">\n            <xsl:value-of select=\"@halign\" />\n        </xsl:when>\n        <xsl:when test=\"self::poem\">\n            <xsl:text>left</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\"parent::*\" mode=\"poem-halign\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- ##### -->\n<!-- Music -->\n<!-- ##### -->\n\n<!-- Uses inline math rendering -->\n<xsl:template match=\"n|scaledeg|timesignature|chord\">\n    <xsl:call-template name=\"inline-math-wrapper\">\n        <xsl:with-param name=\"math\">\n            <xsl:apply-templates select=\".\" mode=\"inner-music\"/>\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- Note -->\n<xsl:template match=\"n\" mode=\"inner-music\">\n    <!-- Test that pitch class is NOT castable as a number -->\n    <xsl:if test=\"not(number(@pc) = number(@pc))\">\n        <xsl:text>\\text{</xsl:text>\n        <xsl:value-of select=\"@pc\"/>\n        <xsl:text>}</xsl:text>\n    </xsl:if>\n    <!-- Provide something to place accidental -->\n    <!-- on if the pitch class is numeric.     -->\n    <xsl:if test=\"number(@pc) = number(@pc) and @acc\">\n        <xsl:text>{}</xsl:text>\n    </xsl:if>\n    <!-- Add an accidental if applicable -->\n    <xsl:if test=\"@acc\">\n        <xsl:text>^</xsl:text>\n        <xsl:call-template name=\"accidentals\">\n            <xsl:with-param name=\"accidental\"><xsl:value-of select=\"@acc\"/></xsl:with-param>\n        </xsl:call-template>\n    </xsl:if>\n    <!-- Test that pitch class IS castable as a number -->\n    <!-- Accidentals precede numeric pitch classes     -->\n    <xsl:if test=\"number(@pc) = number(@pc)\">\n        <xsl:value-of select=\"@pc\"/>\n    </xsl:if>\n    <!-- Add an octave number if applicable -->\n    <xsl:if test=\"@octave\">\n        <!-- Consideration: should we accommodate other octave notations?    -->\n        <!-- Current support is for scientific pitch notation (the standard), -->\n        <!-- other octave notation exists such as \"Helmholtz pitch notation\"  -->\n        <xsl:text>_{</xsl:text>\n        <xsl:value-of select=\"@octave\"/>\n        <xsl:text>}</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<!-- Scale Degrees -->\n<xsl:template match=\"scaledeg\" mode=\"inner-music\">\n    <!-- Arabic numeral with circumflex accent above)-->\n    <xsl:text>\\hat{</xsl:text>\n    <xsl:apply-templates/>\n    <xsl:text>}</xsl:text>\n    <!-- TODO: unclear if trailing space is necessary -->\n    <xsl:text> </xsl:text>\n</xsl:template>\n\n<!-- Time Signatures -->\n<xsl:template match=\"timesignature\" mode=\"inner-music\">\n    <xsl:text>\\begin{smallmatrix}</xsl:text>\n    <xsl:value-of select=\"@top\"/>\n    <xsl:text>\\\\</xsl:text>\n    <xsl:value-of select=\"@bottom\"/>\n    <xsl:text>\\end{smallmatrix}</xsl:text>\n</xsl:template>\n\n<!-- Chord -->\n<xsl:template match=\"chord\" mode=\"inner-music\">\n    <xsl:text>\\left.</xsl:text>\n    <!-- Root -->\n    <xsl:choose>\n        <!-- There is an accidental -->\n        <xsl:when test=\"contains(@root, ' ')\">\n            <!-- Pitch Class -->\n            <xsl:text>\\text{</xsl:text>\n            <xsl:value-of select=\"substring-before(@root, ' ')\"/>\n            <xsl:text>}</xsl:text>\n            <!-- Accidental -->\n            <xsl:text>^</xsl:text>\n            <xsl:call-template name=\"accidentals\">\n                <xsl:with-param name=\"accidental\"><xsl:value-of select=\"substring-after(@root, ' ')\"/></xsl:with-param>\n            </xsl:call-template>\n            <!-- prevent \"double superscript\" error -->\n            <xsl:text>{}</xsl:text>\n        </xsl:when>\n        <!-- There is not an accidental -->\n        <xsl:otherwise>\n            <xsl:text>\\text{</xsl:text>\n            <xsl:value-of select=\"@root\"/>\n            <xsl:text>}</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n    <!-- Mode (augmented, major, minor, half-diminished, diminished, etc.) -->\n    <xsl:if test=\"@mode\">\n        <xsl:choose>\n            <!-- There is a two part mode -->\n            <xsl:when test=\"contains(@mode, ' ')\">\n                <!-- Lower Mode -->\n                <xsl:call-template name=\"chordsymbols\">\n                    <xsl:with-param name=\"mode\"><xsl:value-of select=\"substring-before(@mode, ' ')\"/></xsl:with-param>\n                </xsl:call-template>\n                <!-- Raise to be in line with bps -->\n                <xsl:text>^</xsl:text>\n                <!-- Higher Mode -->\n                <xsl:call-template name=\"chordsymbols\">\n                    <xsl:with-param name=\"mode\"><xsl:value-of select=\"substring-after(@mode, ' ')\"/></xsl:with-param>\n                </xsl:call-template>\n                <!-- prevent \"double superscript\" error -->\n                <xsl:text>{}</xsl:text>\n            </xsl:when>\n            <!-- There is a single mode -->\n            <xsl:otherwise>\n                <xsl:call-template name=\"chordsymbols\">\n                    <xsl:with-param name=\"mode\"><xsl:value-of select=\"@mode\"/></xsl:with-param>\n                </xsl:call-template>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:if>\n    <!-- Bass Position Symbol -->\n    <xsl:if test=\"@bps\">\n        <!-- Consideration: Even if it is not standard practice, -->\n        <!-- will anyone ever want more than two bps numbers?    -->\n        <xsl:choose>\n            <!-- We use a space to delineate the breaking point of the bps -->\n            <!-- e.g. for 6/4 we write \"6 4\" -->\n            <xsl:when test=\"contains(@bps, ' ')\">\n                <xsl:text>^{</xsl:text>\n                <xsl:value-of select=\"substring-before(@bps, ' ')\"/>\n                <xsl:text>}</xsl:text>\n                <xsl:text>_{</xsl:text>\n                <xsl:value-of select=\"substring-after(@bps, ' ')\"/>\n                <xsl:text>}</xsl:text>\n            </xsl:when>\n            <!-- If there is no space, then we only need a superscript -->\n            <xsl:otherwise>\n                <xsl:text>^{</xsl:text>\n                <xsl:value-of select=\"@bps\"/>\n                <xsl:text>}</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:if>\n    <!-- Suspended -->\n    <xsl:if test=\"@suspended = 'yes'\">\n        <!-- Consideration: should we make \"sus\" localized/customizable? -->\n        <xsl:text>\\text{sus}</xsl:text>\n    </xsl:if>\n    <!-- Chord Alterations -->\n    <xsl:if test=\"./*\">\n        <xsl:choose>\n            <!-- Turning off parentheses is usually for showing why parenthesization clarifies meaning. -->\n            <xsl:when test=\"@parentheses = 'no'\">\n                <xsl:text>\\left.</xsl:text>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>\\left(</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n        <!-- We only use a smallmatrix if we have more than one alteration         -->\n        <!-- Using smallmatrix with a single entry makes the alteration too small. -->\n        <xsl:if test=\"count(*) > 1\">\n            <xsl:text>\\begin{smallmatrix}</xsl:text>\n        </xsl:if>\n        <xsl:apply-templates select=\"*\"/>\n        <xsl:if test=\"count(*) > 1\">\n            <xsl:text>\\end{smallmatrix}</xsl:text>\n        </xsl:if>\n        <xsl:choose>\n            <xsl:when test=\"@parentheses = 'no'\">\n                <xsl:text>\\right.</xsl:text>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>\\right)</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:if>\n    <!-- Alternate Bass Note (e.g. C/G) -->\n    <xsl:if test=\"@bass\">\n        <!-- Resizes based on components of chord -->\n        <xsl:text>\\middle/</xsl:text>\n        <xsl:choose>\n            <!-- Bass note has an accidental -->\n            <xsl:when test=\"contains(@bass, ' ')\">\n                <!-- Pitch Class -->\n                <xsl:text>\\text{</xsl:text>\n                <xsl:value-of select=\"substring-before(@bass, ' ')\"/>\n                <xsl:text>}</xsl:text>\n                <!-- Accidental -->\n                <xsl:text>^{</xsl:text>\n                <xsl:call-template name=\"accidentals\">\n                    <xsl:with-param name=\"accidental\"><xsl:value-of select=\"substring-after(@bass, ' ')\"/></xsl:with-param>\n                </xsl:call-template>\n                <xsl:text>}</xsl:text>\n            </xsl:when>\n            <!-- Bass note does not have an accidental -->\n            <xsl:otherwise>\n                <!-- Pitch Class -->\n                <xsl:text>\\text{</xsl:text>\n                <xsl:value-of select=\"@bass\"/>\n                <xsl:text>}</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:if>\n    <xsl:text>\\right.</xsl:text>\n</xsl:template>\n\n<!-- Chord Alteration -->\n<!-- Put a break after each alteration that is not the last -->\n<xsl:template match=\"chord/alteration\">\n    <xsl:text>\\text{</xsl:text>\n    <xsl:apply-templates/>\n    <xsl:text>}</xsl:text>\n    <!-- Separate alterations -->\n    <xsl:if test=\"following-sibling::*\">\n        <xsl:text>\\\\</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<!--                 -->\n<!-- Musical Symbols -->\n<!--                 -->\n\n<!-- Accidentals -->\n\n<!-- TODO: If requested, add semi- and sesqui- versions of sharp and flat -->\n<!-- (Easy with LilyPond in LaTeX) -->\n<!-- (For HTML ,there are Unicode characters, though font support may be iffy) -->\n\n<!-- Double-Sharp -->\n<xsl:template match=\"doublesharp\">\n    <xsl:call-template name=\"doublesharp\"/>\n</xsl:template>\n\n<!-- Sharp -->\n<xsl:template match=\"sharp\">\n    <xsl:call-template name=\"sharp\"/>\n</xsl:template>\n\n<!-- Natural -->\n<xsl:template match=\"natural\">\n    <xsl:call-template name=\"natural\"/>\n</xsl:template>\n\n<!-- Flat -->\n<xsl:template match=\"flat\">\n    <xsl:call-template name=\"flat\"/>\n</xsl:template>\n\n<!-- Double-Flat -->\n<xsl:template match=\"doubleflat\">\n    <xsl:call-template name=\"doubleflat\"/>\n</xsl:template>\n\n<!-- Insert the correct accidental -->\n<!-- (For use in <n> and <chord>)  -->\n<xsl:template name=\"accidentals\">\n    <xsl:param name=\"accidental\"/>\n    <xsl:choose>\n        <xsl:when test=\"$accidental = 'doubleflat'\">\n            <xsl:call-template name=\"doubleflat\"/>\n        </xsl:when>\n        <xsl:when test=\"$accidental = 'flat'\">\n            <xsl:call-template name=\"flat\"/>\n        </xsl:when>\n        <xsl:when test=\"$accidental = 'natural'\">\n            <xsl:call-template name=\"natural\"/>\n        </xsl:when>\n        <xsl:when test=\"$accidental = 'sharp'\">\n            <xsl:call-template name=\"sharp\"/>\n        </xsl:when>\n        <xsl:when test=\"$accidental = 'doublesharp'\">\n            <xsl:call-template name=\"doublesharp\"/>\n        </xsl:when>\n        <!-- For unknown accidentals, use the given value wrapped in \\text{} -->\n        <xsl:otherwise>\n            <xsl:text>\\text{</xsl:text>\n            <xsl:value-of select=\"$accidental\"/>\n            <xsl:text>}</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Fall-Back values for Accidentals -->\n\n<!-- Double-Sharp -->\n<xsl:template name=\"doublesharp\">\n    <xsl:text>[DOUBLESHARP]</xsl:text>\n</xsl:template>\n\n<!-- Sharp -->\n<xsl:template name=\"sharp\">\n    <xsl:text>[SHARP]</xsl:text>\n</xsl:template>\n\n<!-- Natural -->\n<xsl:template name=\"natural\">\n    <xsl:text>[NATURAL]</xsl:text>\n</xsl:template>\n\n<!-- Flat -->\n<xsl:template name=\"flat\">\n    <xsl:text>[FLAT]</xsl:text>\n</xsl:template>\n\n<!-- Double-Flat -->\n<xsl:template name=\"doubleflat\">\n    <xsl:text>[DOUBLEFLAT]</xsl:text>\n</xsl:template>\n\n<!-- Insert the correct chord symbol -->\n<!-- (For use in <chord>)  -->\n<xsl:template name=\"chordsymbols\">\n    <xsl:param name=\"mode\"/>\n    <xsl:choose>\n        <xsl:when test=\"$mode = 'augmented'\">\n            <xsl:call-template name=\"augmentedchordsymbol\"/>\n        </xsl:when>\n        <xsl:when test=\"$mode = 'major'\">\n            <xsl:call-template name=\"majorchordsymbol\"/>\n        </xsl:when>\n        <xsl:when test=\"$mode = 'minor'\">\n            <xsl:call-template name=\"minorchordsymbol\"/>\n        </xsl:when>\n        <xsl:when test=\"$mode = 'halfdiminished'\">\n            <xsl:text>^</xsl:text>\n            <xsl:call-template name=\"halfdiminishedchordsymbol\"/>\n            <xsl:text>{}</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$mode = 'diminished'\">\n            <xsl:text>^</xsl:text>\n            <xsl:call-template name=\"diminishedchordsymbol\"/>\n            <xsl:text>{}</xsl:text>\n        </xsl:when>\n        <!-- For unknown chord symbols, use the given value wrapped in \\text{} -->\n        <!-- e.g. mode=\"maj\" will use \\text{maj}                               -->\n        <xsl:otherwise>\n            <xsl:text>\\text{</xsl:text>\n            <xsl:value-of select=\"$mode\"/>\n            <xsl:text>}</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Chord Symbols -->\n\n<!-- Augmented -->\n<xsl:template name=\"augmentedchordsymbol\">\n    <xsl:text>{+}</xsl:text>\n</xsl:template>\n\n<!-- Major -->\n<xsl:template name=\"majorchordsymbol\">\n    <xsl:text>{\\Delta}</xsl:text>\n</xsl:template>\n\n<!-- Minor -->\n<xsl:template name=\"minorchordsymbol\">\n    <xsl:text>{-}</xsl:text>\n</xsl:template>\n\n<!-- Half Diminished -->\n<xsl:template name=\"halfdiminishedchordsymbol\">\n    <xsl:text>\\text{\\o}</xsl:text>\n</xsl:template>\n\n<!-- Diminished -->\n<xsl:template name=\"diminishedchordsymbol\">\n    <xsl:text>{\\circ}</xsl:text>\n</xsl:template>\n\n<!-- ################ -->\n<!-- Cross-References -->\n<!-- ################ -->\n\n<!-- The logic of the visible text of a cross-reference is all  -->\n<!-- here in the common routines. That text and the target node -->\n<!-- is then sent to templates that are output-format-specific. -->\n\n<!-- The actual manufacture of a (active) link is delegated  -->\n<!-- to implementations, see abstract (null) implementations -->\n<!-- at the end of the \"utilities\" section below             -->\n\n<!-- Match on:                                       -->\n<!--     @ref, no list: the most frequent case       -->\n<!--     @ref, a list: mostly for bibliography lists -->\n<!--     @first, @last: a range                      -->\n<!--     @provisional: author convenience            -->\n<!--     remainder: error check                      -->\n\n<!-- Primary case, no separators in @ref -->\n<xsl:template match=\"xref[@ref and not(contains(normalize-space(@ref), ' ')) and  not(contains(normalize-space(@ref), ','))]\">\n    <xsl:variable name=\"error-message\">\n        <xsl:apply-templates select=\".\" mode=\"error-check-xref\"/>\n    </xsl:variable>\n    <xsl:variable name=\"b-custom-biblio-text\" select=\"@pi:custom-text = 'yes'\"/>\n\n    <xsl:choose>\n        <xsl:when test=\"not($error-message = '')\">\n            <xsl:variable name=\"warning-rtf\">\n                <c>\n                    <xsl:value-of select=\"$error-message\"/>\n                </c>\n            </xsl:variable>\n            <xsl:apply-templates select=\"exsl:node-set($warning-rtf)/c\"/>\n        </xsl:when>\n        <!-- clear of errors, so on to main event -->\n        <xsl:otherwise>\n            <xsl:variable name=\"target\" select=\"id(@ref)\"/>\n            <!-- Determine style of visible text in link -->\n            <xsl:variable name=\"text-style\">\n                <xsl:apply-templates select=\".\" mode=\"get-text-style\" />\n            </xsl:variable>\n            <!-- if target is a bibliography item, generic -->\n            <!-- text template only makes a number, we add -->\n            <!-- brackets before link manufacture          -->\n            <xsl:variable name=\"b-is-biblio-target\" select=\"boolean($target/self::biblio)\" />\n            <!-- form text of the clickable, wrap biblio target -->\n            <!-- since xref-text outputs just a number          -->\n            <xsl:variable name=\"text\">\n                <xsl:if test=\"parent::mrow\">\n                    <xsl:text>\\text{</xsl:text>\n                </xsl:if>\n                <xsl:if test=\"$b-is-biblio-target and not($b-custom-biblio-text)\">\n                    <xsl:text>[</xsl:text>\n                </xsl:if>\n                <xsl:apply-templates select=\".\" mode=\"xref-text\" >\n                    <xsl:with-param name=\"target\" select=\"$target\" />\n                    <xsl:with-param name=\"text-style\" select=\"$text-style\" />\n                    <!-- pass content as an RTF, test vs. empty string, use copy-of -->\n                    <xsl:with-param name=\"custom-text\">\n                        <xsl:apply-templates/>\n                    </xsl:with-param>\n                </xsl:apply-templates>\n                <!-- a bibliography citation (only) may have extra @detail          -->\n                <!-- maybe the detail should migrate to content of a xref to biblio -->\n                <xsl:if test=\"@detail\">\n                    <xsl:choose>\n                        <xsl:when test=\"$b-is-biblio-target\">\n                            <xsl:text>,</xsl:text>\n                            <xsl:call-template name=\"character\">\n                                <xsl:with-param name=\"name\" select=\"'nbsp'\"/>\n                            </xsl:call-template>\n                            <!-- this info should not be in an attribute! -->\n                            <xsl:apply-templates select=\"@detail\" />\n                        </xsl:when>\n                        <xsl:otherwise>\n                            <xsl:message>PTX:WARNING: &lt;xref @detail=\"<xsl:value-of select=\"@detail\" />\" /&gt; only implemented for single references to &lt;biblio&gt; elements</xsl:message>\n                            <xsl:apply-templates select=\".\" mode=\"location-report\" />\n                        </xsl:otherwise>\n                    </xsl:choose>\n                </xsl:if>\n                <xsl:if test=\"$b-is-biblio-target and not($b-custom-biblio-text)\">\n                    <xsl:text>]</xsl:text>\n                </xsl:if>\n                <xsl:if test=\"parent::mrow\">\n                    <xsl:text>}</xsl:text>\n                </xsl:if>\n            </xsl:variable>\n            <!-- Send the text representation for link and target to a    -->\n            <!-- format-specific and target-specific link manufacture.    -->\n            <!-- This depends primarly on the $target, but the context is -->\n            <!-- holds the location of the link.  Example: a link in      -->\n            <!-- display mathematics (rendered by MathJax for HTML)       -->\n            <!-- requires radically different constructions as a knowl,   -->\n            <!-- or as a hyperlink.  LaTeX barely cares.  We do wrap the  -->\n            <!-- xref-text in \\text{} for receipt in display mathematics. -->\n            <!-- NB: could a xref with title text have math in it and mess-up here? -->\n            <xsl:apply-templates select=\".\" mode=\"xref-link\">\n                <xsl:with-param name=\"target\" select=\"$target\" />\n                <xsl:with-param name=\"origin\" select=\"'xref'\" />\n                <xsl:with-param name=\"content\" select=\"$text\" />\n            </xsl:apply-templates>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- A range given by @first, @last            -->\n<!-- Makes one chunk of text, linked to @first -->\n<!-- Requires same type for targets, since     -->\n<!-- type only occurs once in text             -->\n<!-- Equations look like (4.2)-(4.8)           -->\n<!-- Bibliography looks like [6-14]            -->\n<xsl:template match=\"xref[@first and @last]\">\n    <xsl:variable name=\"error-message\">\n        <xsl:apply-templates select=\".\" mode=\"error-check-xref\"/>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"not($error-message = '')\">\n            <xsl:variable name=\"warning-rtf\">\n                <c>\n                    <xsl:value-of select=\"$error-message\"/>\n                </c>\n            </xsl:variable>\n            <xsl:apply-templates select=\"exsl:node-set($warning-rtf)/c\"/>\n        </xsl:when>\n        <!-- clear of errors, so on to main event -->\n        <xsl:otherwise>\n            <xsl:variable name=\"target-one\" select=\"id(@first)\"/>\n            <xsl:variable name=\"target-two\" select=\"id(@last)\" />\n            <!-- Determine style of visible text in link -->\n            <xsl:variable name=\"text-style-one\">\n                <xsl:apply-templates select=\".\" mode=\"get-text-style\" />\n            </xsl:variable>\n            <!-- Adjust/set style for end of range          -->\n            <!-- Basically supress text manufacture of type -->\n            <!-- Also, no content is passed with @last      -->\n            <xsl:variable name=\"text-style-two\">\n                <xsl:choose>\n                    <!-- do not replicate type name -->\n                    <xsl:when test=\"$text-style-one = 'type-global'\">\n                        <xsl:text>global</xsl:text>\n                    </xsl:when>\n                    <xsl:when test=\"$text-style-one = 'type-local'\">\n                        <xsl:text>local</xsl:text>\n                    </xsl:when>\n                    <!-- pass through 'global', 'local', 'title', 'phrase-global' -->\n                    <xsl:otherwise>\n                        <xsl:value-of select=\"$text-style-one\" />\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:variable>\n            <!-- enforce @first, @last point to same kind of element, -->\n            <!-- since we implicitly recycle the type-name of @first  -->\n            <!-- validation stylesheet: possible by inserting id() into XPath test? -->\n            <xsl:if test=\"not(local-name($target-one) = local-name($target-two))\">\n                <xsl:message>PTX:ERROR:   &lt;xref @first=\"<xsl:value-of select=\"@first\" />\" @last=\"<xsl:value-of select=\"@last\" />\" /&gt; references two elements with different tags (<xsl:value-of select=\"local-name($target-one)\" /> vs. <xsl:value-of select=\"local-name($target-two)\" />), so are incompatible as endpoints of a range.  Rewrite using two &lt;xref&gt; elements</xsl:message>\n            </xsl:if>\n            <!-- Once there was a courtesy check here that range  -->\n            <!-- is not out-of-order. It was very inefficient due -->\n            <!-- to two uses of the \"preceeding::\" axis. Seven    -->\n            <!-- instances in the sample article accounted for    -->\n            <!-- ~6% of processing time.                          -->\n            <!-- For the old code, see commit                     -->\n            <!--     05c88bb632e1d232a46955f4e3552494c3219cdc     -->\n            <!-- Testing @last target in the nodes preceeding the -->\n            <!-- first target might cut the time in half, which   -->\n            <!-- is still not great.                              -->\n            <!--  -->\n            <!-- Biblio check assumes targets are equal       -->\n            <!-- If target is a bibliography item, generic    -->\n            <!-- text template only makes numbers, we add     -->\n            <!-- brackets and detail before link manufacture  -->\n            <!-- Content passes with @first, not with @second -->\n            <xsl:variable name=\"b-is-biblio-target\" select=\"boolean($target-one/self::biblio)\" />\n            <!-- Compose two text parts with an ndash, perhaps wrapped. -->\n            <!-- But custom text replaces the entire composition, so no -->\n            <!-- endpoint texts, no ndash, and no bibliography brackets -->\n            <!-- (matching their suppression for a single citation with -->\n            <!-- custom text).                                          -->\n            <xsl:variable name=\"text\">\n                <xsl:if test=\"parent::mrow\">\n                    <xsl:text>\\text{</xsl:text>\n                </xsl:if>\n                <xsl:choose>\n                    <xsl:when test=\"$text-style-one = 'custom'\">\n                        <xsl:apply-templates select=\".\" mode=\"xref-text\" >\n                            <xsl:with-param name=\"target\" select=\"$target-one\" />\n                            <xsl:with-param name=\"text-style\" select=\"$text-style-one\" />\n                            <!-- pass content as an RTF, test vs. empty string, use copy-of -->\n                            <xsl:with-param name=\"custom-text\">\n                                <xsl:apply-templates/>\n                            </xsl:with-param>\n                        </xsl:apply-templates>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:if test=\"$b-is-biblio-target\">\n                            <xsl:text>[</xsl:text>\n                        </xsl:if>\n                        <xsl:apply-templates select=\".\" mode=\"xref-text\" >\n                            <xsl:with-param name=\"target\" select=\"$target-one\" />\n                            <xsl:with-param name=\"text-style\" select=\"$text-style-one\" />\n                            <!-- pass content as an RTF, test vs. empty string, use copy-of -->\n                            <xsl:with-param name=\"custom-text\">\n                                <xsl:apply-templates/>\n                            </xsl:with-param>\n                        </xsl:apply-templates>\n                        <xsl:call-template name=\"character\">\n                            <xsl:with-param name=\"name\" select=\"'ndash'\"/>\n                        </xsl:call-template>\n                        <xsl:apply-templates select=\".\" mode=\"xref-text\" >\n                            <xsl:with-param name=\"target\" select=\"$target-two\" />\n                            <xsl:with-param name=\"text-style\" select=\"$text-style-two\" />\n                        </xsl:apply-templates>\n                        <xsl:if test=\"$b-is-biblio-target\">\n                            <xsl:text>]</xsl:text>\n                        </xsl:if>\n                    </xsl:otherwise>\n                </xsl:choose>\n                <xsl:if test=\"parent::mrow\">\n                    <xsl:text>}</xsl:text>\n                </xsl:if>\n            </xsl:variable>\n            <!-- Send the text representation for link and target to a    -->\n            <!-- format-specific and target-specific link manufacture.    -->\n            <!-- This depends primarly on the $target, but the context is -->\n            <!-- holds the location of the link.  Example: a link in      -->\n            <!-- display mathematics (rendered by MathJax for HTML)       -->\n            <!-- requires radically different constructions as a knowl,   -->\n            <!-- or as a hyperlink.  LaTeX barely cares.  We do wrap the  -->\n            <!-- xref-text in \\text{} for receipt in display mathematics. -->\n            <!-- NB: could a xref with title text have math in it and mess-up here? -->\n            <xsl:apply-templates select=\".\" mode=\"xref-link\">\n                <xsl:with-param name=\"target\" select=\"$target-one\" />\n                <xsl:with-param name=\"origin\" select=\"'xref'\" />\n                <xsl:with-param name=\"content\" select=\"$text\" />\n            </xsl:apply-templates>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- A comma-, or space-separated list is unusual, -->\n<!-- outside of a list of bibliography items.  For -->\n<!-- other items we just mimic this case.          -->\n<xsl:template match=\"xref[@ref and (contains(normalize-space(@ref), ' ') or contains(normalize-space(@ref), ','))]\">\n    <xsl:variable name=\"error-message\">\n        <xsl:apply-templates select=\".\" mode=\"error-check-xref\"/>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"not($error-message = '')\">\n            <xsl:variable name=\"warning-rtf\">\n                <c>\n                    <xsl:value-of select=\"$error-message\"/>\n                </c>\n            </xsl:variable>\n            <xsl:apply-templates select=\"exsl:node-set($warning-rtf)/c\"/>\n        </xsl:when>\n        <!-- clear of errors, so on to main event -->\n        <xsl:otherwise>\n            <!-- Determine style of visible text in link -->\n            <xsl:variable name=\"text-style\">\n                <xsl:apply-templates select=\".\" mode=\"get-text-style\" />\n            </xsl:variable>\n            <!-- commas to blanks, normalize, add trailing blank for parsing   -->\n            <!-- initialize with empty previous node, recurse through the list -->\n            <xsl:variable name=\"normalized-ref-list\"\n                select=\"concat(normalize-space(str:replace(@ref,',', ' ')), ' ')\" />\n            <xsl:apply-templates select=\".\" mode=\"process-ref-list\">\n                <xsl:with-param name=\"previous-target\" select=\"/..\" />\n                <xsl:with-param name=\"ref-list\" select=\"$normalized-ref-list\" />\n                <xsl:with-param name=\"text-style\" select=\"$text-style\" />\n            </xsl:apply-templates>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- $ref-list must always have a trailing blank, if non-empty      -->\n<!-- $previous-target serves two purposes:                          -->\n<!--     empty signals start of the list, so no separator           -->\n<!--     type-checking to preserve a consistent list (unimplmented) -->\n<!-- $text-style is set on first call, then just pass-through       -->\n<!-- Wrapping for bibiography list is based on first, last element  -->\n<!-- No content overrides are allowed, since unclear jut how        -->\n<!-- TODO: improve checking to avoid goofy results -->\n<xsl:template match=\"xref\" mode=\"process-ref-list\">\n    <xsl:param name=\"previous-target\" select=\"/..\" />\n    <xsl:param name=\"ref-list\" select=\"' '\" />\n    <xsl:param name=\"text-style\" select=\"''\" />\n    <!-- split list at first blank, later recurse on $trailing -->\n    <xsl:variable name=\"ref\" select=\"substring-before($ref-list, ' ')\" />\n    <xsl:variable name=\"trailing\" select=\"substring-after($ref-list, ' ')\" />\n    <!-- now work with one $ref and the configured $text-style -->\n    <!-- get the target as a node -->\n    <xsl:variable name=\"target\" select=\"id($ref)\" />\n    <!-- bibiographic targets are special -->\n    <xsl:variable name=\"b-is-biblio-target\" select=\"$target/self::biblio\" />\n    <!-- if starting, begin bibliography list wrapping -->\n    <xsl:if test=\"not($previous-target) and $b-is-biblio-target\">\n        <xsl:text>[</xsl:text>\n    </xsl:if>\n    <!-- output a seperator, if not just starting -->\n    <!-- protect text in a math display           -->\n    <xsl:if test=\"$previous-target\">\n        <xsl:if test=\"parent::mrow\">\n            <xsl:text>\\text{</xsl:text>\n        </xsl:if>\n        <xsl:text>, </xsl:text>\n        <xsl:if test=\"parent::mrow\">\n            <xsl:text>}</xsl:text>\n        </xsl:if>\n    </xsl:if>\n    <!-- create the visual/clickable/readable text      -->\n    <!-- no content is passed, so no override in effect -->\n    <xsl:variable name=\"text\">\n        <xsl:if test=\"parent::mrow\">\n            <xsl:text>\\text{</xsl:text>\n        </xsl:if>\n        <xsl:apply-templates select=\".\" mode=\"xref-text\">\n            <xsl:with-param name=\"target\" select=\"$target\" />\n            <xsl:with-param name=\"text-style\" select=\"$text-style\" />\n        </xsl:apply-templates>\n        <xsl:if test=\"parent::mrow\">\n            <xsl:text>}</xsl:text>\n        </xsl:if>\n    </xsl:variable>\n    <!-- Send the text representation for link and target to a    -->\n    <!-- format-specific and target-specific link manufacture.    -->\n    <!-- This depends primarly on the $target, but the context is -->\n    <!-- holds the location of the link.  Example: a link in      -->\n    <!-- display mathematics (rendered by MathJax for HTML)       -->\n    <!-- requires radically different constructions as a knowl,   -->\n    <!-- or as a hyperlink.  LaTeX barely cares.  We do wrap the  -->\n    <!-- xref-text in \\text{} for receipt in display mathematics. -->\n    <!-- NB: could a xref with title text have math in it and mess-up here? -->\n    <xsl:apply-templates select=\".\" mode=\"xref-link\">\n        <xsl:with-param name=\"target\" select=\"$target\" />\n        <xsl:with-param name=\"origin\" select=\"'xref'\" />\n        <xsl:with-param name=\"content\" select=\"$text\" />\n    </xsl:apply-templates>\n    <!-- check if we have exhausted the list, -->\n    <!-- so check bibliography wrapping       -->\n    <xsl:if test=\"not($trailing) and $b-is-biblio-target\">\n        <xsl:text>]</xsl:text>\n    </xsl:if>\n    <!-- recurse into next reference in the list -->\n    <xsl:if test=\"$trailing\">\n        <xsl:apply-templates select=\".\" mode=\"process-ref-list\">\n            <xsl:with-param name=\"previous-target\" select=\"$target\" />\n            <xsl:with-param name=\"ref-list\" select=\"$trailing\" />\n            <xsl:with-param name=\"text-style\" select=\"$text-style\" />\n        </xsl:apply-templates>\n    </xsl:if>\n</xsl:template>\n\n<!-- Provisional cross-references -->\n<!-- A convenience for authors in early stages of writing -->\n<!-- Just drop a reminder in text                         -->\n<xsl:template match=\"xref[@provisional]\">\n    <xsl:variable name=\"warning-rtf\">\n        <c>\n            <xsl:text>[provisional cross-reference: </xsl:text>\n            <xsl:value-of select=\"@provisional\"/>\n            <xsl:text>]</xsl:text>\n        </c>\n    </xsl:variable>\n    <xsl:variable name=\"warning\" select=\"exsl:node-set($warning-rtf)\"/>\n    <xsl:apply-templates select=\"$warning/c\"/>\n</xsl:template>\n\n<!-- Warnings for a high-frequency mistake -->\n<xsl:template match=\"xref[not(@ref) and not(@first and @last) and not(@provisional)]\">\n    <xsl:message>PTX:ERROR:   A cross-reference (&lt;xref&gt;) must have a @ref attribute, a @first/@last attribute pair, or a @provisional attribute</xsl:message>\n    <xsl:apply-templates select=\".\" mode=\"location-report\" />\n    <xsl:call-template name=\"inline-warning\">\n        <xsl:with-param name=\"warning\">\n            <xsl:text>xref without ref, first/last, or provisional attribute (check spelling)</xsl:text>\n        </xsl:with-param>\n    </xsl:call-template>\n    <xsl:call-template name=\"margin-warning\">\n        <xsl:with-param name=\"warning\">\n            <xsl:text>xref, no recognized attribute</xsl:text>\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- ######################### -->\n<!-- Cross-Reference Utilities -->\n<!-- ######################### -->\n\n<!-- Error-checking first, an \"xref\" in, a placeholder message back -->\n<!-- to insert into text that screams there is a problem.  Routine  -->\n<!-- also scribbles on the console.  To use, capture the output in  -->\n<!--  avariable, if non-empty then use text as result, if empty     -->\n<!-- then do the work.                                              -->\n\n<xsl:template match=\"xref\" mode=\"error-check-xref\">\n    <!-- A @ref attribute can be a list (e.g. of biblio) and the   -->\n    <!-- @first/@last construction is really two @ref.  We package -->\n    <!-- up a list as a string no matter what.  No commas, plus a  -->\n    <!-- trailing space added so we can chop up the list reliably. -->\n    <!-- commas to blanks, normalize spaces, -->\n    <!-- add trailing space for final split  -->\n    <xsl:variable name=\"normalized-ref-list\">\n        <xsl:choose>\n            <xsl:when test=\"@ref\">\n                <xsl:value-of select=\"concat(normalize-space(str:replace(@ref,',', ' ')), ' ')\"/>\n            </xsl:when>\n            <!-- put @first and @last into a normalized two-part list -->\n            <xsl:when test=\"@first and @last\">\n                <xsl:value-of select=\"concat(normalize-space(@first), ' ', normalize-space(@last), ' ')\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:message>PTX:ERROR:   an \"xref\" lacks a @ref, @first/@last, or @provisional; check your source</xsl:message>\n                <xsl:apply-templates select=\".\" mode=\"location-report\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- Variable will have a list of bad cross-reference -->\n    <!-- labels (no target located!) in a comma-separated -->\n    <!-- list.  Empty is success and we then do nothing.  -->\n    <xsl:variable name=\"bad-xrefs-in-list\">\n        <!-- recursive, start with full list -->\n        <xsl:apply-templates select=\".\" mode=\"check-ref-list\">\n            <xsl:with-param name=\"ref-list\" select=\"$normalized-ref-list\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <xsl:if test=\"not($bad-xrefs-in-list = '')\">\n        <!-- error condition, so warn and return  -->\n        <!-- placeholder text as template result  -->\n        <xsl:variable name=\"error-list\" select=\"substring($bad-xrefs-in-list, 1, string-length($bad-xrefs-in-list) - 2)\"/>\n        <xsl:message>PTX:ERROR:   a cross-reference (\"xref\") uses references [<xsl:value-of select=\"$error-list\"/>] that do not point to any target, or perhaps point to multiple targets.  Maybe you typed an @xml:id value wrong, maybe the target of the @xml:id is nonexistent, or maybe you temporarily removed the target from your source, or maybe an auxiliary file contains a duplicate.  Your output will contain some placeholder text that you will not want to distribute to your readers.</xsl:message>\n        <xsl:apply-templates select=\".\" mode=\"location-report\"/>\n        <!-- placeholder text -->\n        <xsl:text>[cross-reference to target(s) \"</xsl:text>\n        <xsl:value-of select=\"$error-list\"/>\n        <xsl:text>\" missing or not unique]</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<!-- yes/no boolean for valid targets of an \"xref\"         -->\n<!-- Initial list from entities file as of 2021-02-10      -->\n<!-- Others from test docs, public testing via pretext-dev -->\n<xsl:template match=\"&STRUCTURAL;|&DEFINITION-LIKE;|&THEOREM-LIKE;|&PROOF-LIKE;|&AXIOM-LIKE;|&REMARK-LIKE;|&COMPUTATION-LIKE;|&ASIDE-LIKE;|&OPENPROBLEM-LIKE;|&EXAMPLE-LIKE;|&PROJECT-LIKE;|&GOAL-LIKE;|&FIGURE-LIKE;|&SOLUTION-LIKE;|&DISCUSSION-LIKE;|exercise|task|subexercises|exercisegroup|poem|assemblage|paragraphs|li|fn|md|mrow|biblio|interactive/instructions|case|contributor|gi\" mode=\"is-xref-target\">\n    <xsl:value-of select=\"'yes'\"/>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"is-xref-target\">\n    <xsl:value-of select=\"'no'\"/>\n</xsl:template>\n\n<xsl:template match=\"xref\" mode=\"check-ref-list\">\n    <xsl:param name=\"ref-list\"/>\n    <xsl:choose>\n        <!-- no more to test, stop recursing -->\n        <xsl:when test=\"$ref-list = ''\"/>\n        <!-- test/check initial ref of the list -->\n        <xsl:otherwise>\n            <xsl:variable name=\"initial\" select=\"substring-before($ref-list, ' ')\" />\n            <!-- Look up the ref in the assembled tree: private        -->\n            <!-- solutions are merged and versions are resolved, so    -->\n            <!-- this is the truthful universe of targets — a ref to   -->\n            <!-- content excluded by the version in play is a genuine  -->\n            <!-- failure here, and the lookup never needs to survey    -->\n            <!-- more than one document.                               -->\n            <xsl:variable name=\"hits\">\n                <!-- a context shift, so id() searches the assembled tree -->\n                <xsl:for-each select=\"$root\">\n                    <xsl:if test=\"id($initial)\">\n                        <xsl:text>X</xsl:text>\n                        <xsl:variable name=\"target\" select=\"id($initial)\"/>\n                        <xsl:variable name=\"is-a-target\">\n                            <xsl:apply-templates select=\"$target\" mode=\"is-xref-target\"/>\n                        </xsl:variable>\n                        <xsl:if test=\"$is-a-target = 'no'\">\n                            <xsl:message>PTX:DEBUG: xref/@ref \"<xsl:value-of select=\"$initial\"/>\" points to a \"<xsl:value-of select=\"local-name($target)\"/>\" element.  (1) we made a mistake, and we need to add this element to a list of potential targets of a cross-reference, or (2) you made a mistake and really did not mean this particular construction, or (3) we need to have a discussion about the advisability of this element being a target.   (4) If you are trying to cross-reference a \"p\" element, perhaps using a \"paragraphs\" element is a good alternative.  If (1) or (3) could you please report me!</xsl:message>\n                        </xsl:if>\n                    </xsl:if>\n                </xsl:for-each>\n            </xsl:variable>\n            <xsl:if test=\"not($hits = 'X')\">\n                <!-- drop the failed lookup, plus a separator.  A nonempty -->\n                <!-- result for this template is indicative of a failure   -->\n                <!-- and the list can be reported in the error message     -->\n                <xsl:value-of select=\"$initial\"/>\n                <xsl:text>, </xsl:text>\n            </xsl:if>\n            <!-- recurse to next label -->\n            <xsl:apply-templates select=\".\" mode=\"check-ref-list\">\n                <xsl:with-param name=\"ref-list\" select=\"substring-after($ref-list, ' ')\"/>\n            </xsl:apply-templates>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Parse, analyze switches, attributes -->\n<!--   global:      5.2                  -->\n<!--   type-global: Theorem 5.2          -->\n<!--   title:       Smith's Theorem      -->\n<xsl:template match=\"xref|&PROOF-LIKE;\" mode=\"get-text-style\">\n    <xsl:choose>\n        <!-- local specification is override of global  -->\n        <!-- new @text attribute first, and if so, bail -->\n        <xsl:when test=\"@text='global'\">\n            <xsl:text>global</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"@text='local'\">\n            <xsl:text>local</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"@text='hybrid'\">\n            <xsl:text>hybrid</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"@text='type-global'\">\n            <xsl:text>type-global</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"@text='type-local'\">\n            <xsl:text>type-local</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"@text='type-hybrid'\">\n            <xsl:text>type-hybrid</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"@text='type-global-title'\">\n            <xsl:text>type-global-title</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"@text='type-local-title'\">\n            <xsl:text>type-local-title</xsl:text>\n        </xsl:when>\n        <!-- no 'type-hybrid-title' yet -->\n        <xsl:when test=\"@text='phrase-global'\">\n            <xsl:text>phrase-global</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"@text='phrase-hybrid'\">\n            <xsl:text>phrase-hybrid</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"@text='title'\">\n            <xsl:text>title</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"@text='custom'\">\n            <xsl:text>custom</xsl:text>\n        </xsl:when>\n        <!-- NB: the legacy \"xref/@autoname\" attribute is upgraded to  -->\n        <!-- the equivalent \"@text\" in the \"repair\" pass of assembly,  -->\n        <!-- so it never reaches here.                                 -->\n        <!-- otherwise, global setting via attribute/switch  -->\n        <!-- New scheme is set from docinfo attribute        -->\n        <!-- No setting in docinfo yields empty string for   -->\n        <!-- $xref-text-style, so we drop into legacy scheme -->\n        <!-- for the default, which is 'yes'/'type-global'   -->\n        <xsl:when test=\"$xref-text-style='global'\">\n            <xsl:text>global</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$xref-text-style='local'\">\n            <xsl:text>local</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$xref-text-style='hybrid'\">\n            <xsl:text>hybrid</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$xref-text-style='type-global'\">\n            <xsl:text>type-global</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$xref-text-style='type-local'\">\n            <xsl:text>type-local</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$xref-text-style='type-hybrid'\">\n            <xsl:text>type-hybrid</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$xref-text-style='type-global-title'\">\n            <xsl:text>type-global-title</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$xref-text-style='type-local-title'\">\n            <xsl:text>type-local-title</xsl:text>\n        </xsl:when>\n        <!-- no 'type-hybrid-title' yet -->\n        <xsl:when test=\"$xref-text-style='phrase-global'\">\n            <xsl:text>phrase-global</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$xref-text-style='phrase-hybrid'\">\n            <xsl:text>phrase-hybrid</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$xref-text-style='title'\">\n            <xsl:text>title</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$xref-text-style='custom'\">\n            <xsl:text>custom</xsl:text>\n        </xsl:when>\n        <!-- use this when choose goes away\n        <xsl:if test=\"not($xref-text-style = '')\">\n            <xsl:value-of select=\"$xref-text-style\" />\n        </xsl:if>\n        -->\n        <!-- legacy-autoname is a pass-thru of old autoname  -->\n        <!-- except with no command-line, no docinfo, then   -->\n        <!-- a 'unset' will appear here to activate new      -->\n        <!-- default this could move later to the \"otherwise\"-->\n        <xsl:when test=\"$legacy-autoname='unset'\">\n            <xsl:text>type-global</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$legacy-autoname='no'\">\n            <xsl:text>global</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$legacy-autoname='yes'\">\n            <xsl:text>type-global</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$legacy-autoname='title'\">\n            <xsl:text>title</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message>PTX:BUG:    NO TEXT STYLE DETERMINED</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- The text that will be visible and clickable    -->\n<!-- Bibliography items return a naked number,      -->\n<!-- caller is responsible for adjusting text with  -->\n<!-- brackets prior to shipping to link manufacture -->\n<xsl:template match=\"xref|&PROOF-LIKE;\" mode=\"xref-text\">\n    <xsl:param name=\"target\" />\n    <xsl:param name=\"text-style\" />\n    <xsl:param name=\"custom-text\" select=\"''\" />\n    <!-- an equation target is exceptional -->\n    <!-- Targets are \"mrow\" or bare \"md\" -->\n    <xsl:variable name=\"b-is-equation-target\" select=\"$target/self::mrow or $target/self::md[@pi:authored-one-line]\" />\n    <!-- a bibliography target is exceptional -->\n    <xsl:variable name=\"b-is-biblio-target\" select=\"boolean($target/self::biblio)\" />\n    <!-- a contributor target is exceptional -->\n    <xsl:variable name=\"b-is-contributor-target\" select=\"boolean($target/self::contributor)\"/>\n    <!-- recognize content s potential override -->\n    <xsl:variable name=\"b-has-content\" select=\"not($custom-text = '')\" />\n    <!-- check some situations that would lead to ineffective -->\n    <!-- cross-references due to empty text                   -->\n    <xsl:choose>\n        <xsl:when test=\"$text-style = 'title'\">\n            <xsl:variable name=\"the-title\">\n                <xsl:apply-templates select=\"$target\" mode=\"title-xref\"/>\n            </xsl:variable>\n            <xsl:if test=\"$the-title = ''\">\n                <xsl:message>\n                    <xsl:text>PTX:ERROR:      </xsl:text>\n                    <xsl:text>An &lt;xref&gt; wants to build text using a title to identify the target, but the target (which has @xml:id \"</xsl:text>\n                    <xsl:value-of select=\"@ref\"/>\n                    <xsl:text>\") has no title, not even a default title.</xsl:text>\n                </xsl:message>\n                <xsl:apply-templates select=\".\" mode=\"location-report\"/>\n            </xsl:if>\n        </xsl:when>\n        <xsl:when test=\"$text-style = 'custom'\">\n            <xsl:if test=\"not($b-has-content)\">\n                <xsl:message>\n                    <xsl:text>PTX:ERROR:      </xsl:text>\n                    <xsl:text>An &lt;xref&gt; wants to use custom text to describe the target, but no custom text was provided as the content of the \"xref\".</xsl:text>\n                </xsl:message>\n                <xsl:apply-templates select=\".\" mode=\"location-report\" />\n            </xsl:if>\n        </xsl:when>\n        <!-- Any other case of a cross-reference employs a number, or parts -->\n        <!-- of a number for the target.  The signal of being numberless is -->\n        <!-- an empty result for the modal \"number\" template.  But it is    -->\n        <!-- subtler than that, especially for equations that can have      -->\n        <!-- \"symbolic\" tags via @tag, and the number/no-number dichotomy   -->\n        <!-- is complicated by element names and attributes.                -->\n        <!-- A cross-reference to a contributor is an exception.            -->\n        <xsl:otherwise>\n            <xsl:variable name=\"the-number\">\n                <xsl:apply-templates select=\"$target\" mode=\"xref-number\">\n                    <xsl:with-param name=\"xref\" select=\".\" />\n                </xsl:apply-templates>\n            </xsl:variable>\n            <xsl:if test=\"($the-number = '') and not($b-is-contributor-target)\">\n                <xsl:message>\n                    <xsl:text>PTX:ERROR:      </xsl:text>\n                    <xsl:text>An &lt;xref&gt; wants to build text using a number to identify the target, but the target (which has @xml:id \"</xsl:text>\n                    <xsl:value-of select=\"@ref\"/>\n                    <xsl:text>\") does not have a number. You could try 'text=\"title\"' or 'text=\"custom\"' on the \"xref\".</xsl:text>\n                </xsl:message>\n                <xsl:apply-templates select=\".\" mode=\"location-report\"/>\n            </xsl:if>\n        </xsl:otherwise>\n    </xsl:choose>\n    <!-- Start massive \"choose\" for exceptions and twelve general styles -->\n    <xsl:choose>\n        <xsl:when test=\"$b-is-contributor-target\">\n            <xsl:apply-templates select=\"$target/personname\" />\n        </xsl:when>\n        <!-- equations are different -->\n        <!-- custom or full number   -->\n        <xsl:when test=\"$b-is-equation-target\">\n            <!-- \"custom\" style replaces the number -->\n            <xsl:choose>\n                <xsl:when test=\"$text-style = 'custom'\">\n                    <xsl:copy-of select=\"$custom-text\"/>\n                </xsl:when>\n                <!-- prefixing with content is anomalous -->\n                <xsl:otherwise>\n                    <xsl:if test=\"$b-has-content\">\n                        <xsl:copy-of select=\"$custom-text\"/>\n                        <xsl:apply-templates select=\".\" mode=\"xref-text-separator\"/>\n                    </xsl:if>\n                    <xsl:text>(</xsl:text>\n                    <xsl:apply-templates select=\"$target\" mode=\"xref-number\">\n                        <xsl:with-param name=\"xref\" select=\".\" />\n                    </xsl:apply-templates>\n                    <xsl:text>)</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- bibliography override       -->\n        <!-- number only, consumer wraps -->\n        <!-- warn about useless content override (use as @detail?) -->\n        <xsl:when test=\"$b-is-biblio-target\">\n            <xsl:choose>\n                <xsl:when test=\"$custom-text = ''\">\n                    <xsl:apply-templates select=\"$target\" mode=\"xref-number\">\n                        <xsl:with-param name=\"xref\" select=\".\" />\n                    </xsl:apply-templates>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:value-of select=\"$custom-text\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- now not an equation or bibliography target -->\n        <!-- custom text is additional, as prefix, with no type -->\n        <xsl:when test=\"$text-style = 'global'\">\n            <xsl:if test=\"$b-has-content\">\n                <xsl:copy-of select=\"$custom-text\" />\n                <xsl:apply-templates select=\".\" mode=\"xref-text-separator\"/>\n            </xsl:if>\n            <xsl:apply-templates select=\"$target\" mode=\"xref-number\">\n                <xsl:with-param name=\"xref\" select=\".\" />\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- custom text is additional, as prefix, with no type -->\n        <xsl:when test=\"$text-style = 'local'\">\n            <xsl:if test=\"$b-has-content\">\n                <xsl:copy-of select=\"$custom-text\" />\n                <xsl:apply-templates select=\".\" mode=\"xref-text-separator\"/>\n            </xsl:if>\n            <xsl:apply-templates select=\"$target\" mode=\"serial-number\" />\n        </xsl:when>\n        <xsl:when test=\"$text-style = 'type-global'\">\n            <xsl:choose>\n                <!-- content override of type-prefix -->\n                <xsl:when test=\"$b-has-content\">\n                    <xsl:copy-of select=\"$custom-text\" />\n                    <xsl:variable name=\"the-number\">\n                        <xsl:apply-templates select=\"$target\" mode=\"xref-number\">\n                            <xsl:with-param name=\"xref\" select=\".\" />\n                        </xsl:apply-templates>\n                    </xsl:variable>\n                    <!-- an unnumbered target (\"paragraphs\", squelched  -->\n                    <!-- numbering) contributes no separator, either    -->\n                    <xsl:if test=\"not($the-number = '')\">\n                        <xsl:apply-templates select=\".\" mode=\"xref-text-separator\"/>\n                    </xsl:if>\n                    <xsl:copy-of select=\"$the-number\"/>\n                </xsl:when>\n                <!-- usual, default case -->\n                <xsl:otherwise>\n                    <xsl:apply-templates select=\"$target\" mode=\"type-name\" />\n                    <xsl:variable name=\"the-number\">\n                        <xsl:apply-templates select=\"$target\" mode=\"xref-number\">\n                            <xsl:with-param name=\"xref\" select=\".\" />\n                        </xsl:apply-templates>\n                    </xsl:variable>\n                    <!-- an unnumbered target (\"paragraphs\", squelched  -->\n                    <!-- numbering) contributes no separator, either    -->\n                    <xsl:if test=\"not($the-number = '')\">\n                        <xsl:apply-templates select=\".\" mode=\"xref-text-separator\"/>\n                    </xsl:if>\n                    <xsl:copy-of select=\"$the-number\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <xsl:when test=\"$text-style = 'type-local'\">\n            <xsl:choose>\n                <!-- content override of type-prefix -->\n                <xsl:when test=\"$b-has-content\">\n                    <xsl:copy-of select=\"$custom-text\" />\n                    <xsl:variable name=\"the-number\">\n                        <xsl:apply-templates select=\"$target\" mode=\"serial-number\" />\n                    </xsl:variable>\n                    <!-- an unnumbered target (\"paragraphs\", squelched  -->\n                    <!-- numbering) contributes no separator, either    -->\n                    <xsl:if test=\"not($the-number = '')\">\n                        <xsl:apply-templates select=\".\" mode=\"xref-text-separator\"/>\n                    </xsl:if>\n                    <!-- a task's local serial reads as its rendered  -->\n                    <!-- label: \"Task (a)\", not \"Task a\"              -->\n                    <xsl:choose>\n                        <xsl:when test=\"$target/self::task\">\n                            <xsl:text>(</xsl:text>\n                            <xsl:copy-of select=\"$the-number\"/>\n                            <xsl:text>)</xsl:text>\n                        </xsl:when>\n                        <xsl:otherwise>\n                            <xsl:copy-of select=\"$the-number\"/>\n                        </xsl:otherwise>\n                    </xsl:choose>\n                </xsl:when>\n                <!-- usual, default case -->\n                <xsl:otherwise>\n                    <xsl:apply-templates select=\"$target\" mode=\"type-name\" />\n                    <xsl:variable name=\"the-number\">\n                        <xsl:apply-templates select=\"$target\" mode=\"serial-number\" />\n                    </xsl:variable>\n                    <!-- an unnumbered target (\"paragraphs\", squelched  -->\n                    <!-- numbering) contributes no separator, either    -->\n                    <xsl:if test=\"not($the-number = '')\">\n                        <xsl:apply-templates select=\".\" mode=\"xref-text-separator\"/>\n                    </xsl:if>\n                    <!-- a task's local serial reads as its rendered  -->\n                    <!-- label: \"Task (a)\", not \"Task a\"              -->\n                    <xsl:choose>\n                        <xsl:when test=\"$target/self::task\">\n                            <xsl:text>(</xsl:text>\n                            <xsl:copy-of select=\"$the-number\"/>\n                            <xsl:text>)</xsl:text>\n                        </xsl:when>\n                        <xsl:otherwise>\n                            <xsl:copy-of select=\"$the-number\"/>\n                        </xsl:otherwise>\n                    </xsl:choose>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <xsl:when test=\"($text-style = 'type-global-title') or ($text-style = 'type-local-title')\">\n            <xsl:choose>\n                <!-- content override of type-prefix -->\n                <xsl:when test=\"$b-has-content\">\n                    <xsl:copy-of select=\"$custom-text\" />\n                </xsl:when>\n                <!-- usual, default case -->\n                <xsl:otherwise>\n                    <xsl:apply-templates select=\"$target\" mode=\"type-name\" />\n                </xsl:otherwise>\n            </xsl:choose>\n            <!-- only difference in behavior is global/local number -->\n            <xsl:variable name=\"the-number\">\n                <xsl:choose>\n                    <xsl:when test=\"$text-style = 'type-global-title'\">\n                        <xsl:apply-templates select=\"$target\" mode=\"xref-number\">\n                            <xsl:with-param name=\"xref\" select=\".\" />\n                        </xsl:apply-templates>\n                    </xsl:when>\n                    <xsl:when test=\"$text-style = 'type-local-title'\">\n                        <xsl:apply-templates select=\"$target\" mode=\"serial-number\"/>\n                    </xsl:when>\n                    <xsl:otherwise/>\n                </xsl:choose>\n            </xsl:variable>\n            <!-- an unnumbered target (\"paragraphs\", squelched  -->\n            <!-- numbering) contributes no separator, either    -->\n            <xsl:if test=\"not($the-number = '')\">\n                <xsl:apply-templates select=\".\" mode=\"xref-text-separator\"/>\n            </xsl:if>\n            <xsl:copy-of select=\"$the-number\"/>\n            <xsl:variable name=\"the-title\">\n                <xsl:apply-templates select=\"$target\" mode=\"title-xref\"/>\n            </xsl:variable>\n            <!-- no title, no problem -->\n            <xsl:if test=\"not($the-title = '')\">\n                <xsl:apply-templates select=\".\" mode=\"xref-text-separator\"/>\n                <!-- title might have markup (eg math in HTML), so copy -->\n                <xsl:copy-of select=\"$the-title\"/>\n            </xsl:if>\n        </xsl:when>\n        <!-- special case for phrase options and list items of anonymous lists        -->\n        <!-- catch this first and provide no text at all (could provide busted text?) -->\n        <!-- anonymous lists live in \"p\", but this is an unreliable indication        -->\n        <xsl:when test=\"($text-style = 'phrase-global' or $text-style = 'phrase-hybrid') and ($target/self::li and not($target/ancestor::list or $target/ancestor::objectives or $target/ancestor::outcomes or $target/ancestor::exercise))\">\n            <xsl:message>PTX:ERROR:   a cross-reference to a list item of an anonymous list (\"<xsl:apply-templates select=\"$target\" mode=\"serial-number\" />\") with 'phrase-global' and 'phrase-hybrid' styles for the xref text will yield no text at all, and possibly create unpredictable results in output</xsl:message>\n        </xsl:when>\n        <xsl:when test=\"$text-style = 'phrase-global' or $text-style = 'phrase-hybrid'\">\n            <!-- no content override in this case -->\n            <!-- maybe we can relax this somehow? -->\n            <xsl:if test=\"$b-has-content\">\n                <xsl:message>PTX:FALLBACK: providing content (\"<xsl:value-of select=\".\" />\") for an \"xref\" element is ignored for 'phrase-global' and 'phrase-hybrid' styles for xref text</xsl:message>\n                <xsl:apply-templates select=\".\" mode=\"location-report\" />\n            </xsl:if>\n            <!-- type-local first, no matter what    -->\n            <!-- for each of the two phrase styles   -->\n            <xsl:apply-templates select=\"$target\" mode=\"type-name\" />\n            <xsl:apply-templates select=\".\" mode=\"xref-text-separator\"/>\n            <xsl:apply-templates select=\"$target\" mode=\"serial-number\" />\n            <!-- climb up tree to find highest matching structure numbers -->\n            <!-- we pass through the two styles so reaction can occur     -->\n            <!-- For example for the target Theorem 37.8 of an article,   -->\n            <!-- phrase-global: \"of Section 37\" always                    -->\n            <!-- phrase-hybrid: \"of Section 37\" only if necessary         -->\n            <xsl:apply-templates select=\"$target\" mode=\"smart-xref-text\">\n                <xsl:with-param name=\"text-style\" select=\"$text-style\" />\n                <xsl:with-param name=\"xref\" select=\".\" />\n                <xsl:with-param name=\"target\" select=\"$target\"/>\n                <xsl:with-param name=\"highest-match\" select=\"/..\" />\n                <xsl:with-param name=\"target-structure-number\">\n                    <xsl:apply-templates select=\"$target\" mode=\"structure-number\" />\n                </xsl:with-param>\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:when test=\"($text-style = 'hybrid') or ($text-style = 'type-hybrid')\">\n            <xsl:choose>\n                <!-- content override of type-prefix -->\n                <!-- or addtion to plain number      -->\n                <xsl:when test=\"$b-has-content\">\n                    <xsl:copy-of select=\"$custom-text\" />\n                    <xsl:apply-templates select=\".\" mode=\"xref-text-separator\"/>\n                </xsl:when>\n                <!-- no override, use type as prefix -->\n                <xsl:when test=\"$text-style = 'type-hybrid'\">\n                    <xsl:apply-templates select=\"$target\" mode=\"type-name\" />\n                    <xsl:apply-templates select=\".\" mode=\"xref-text-separator\"/>\n                </xsl:when>\n                <!-- just a plain number, do nothing at all -->\n                <xsl:otherwise />\n            </xsl:choose>\n            <!-- For example for the target Theorem 37.8 of an article, -->\n            <!-- hybrid: 8 or if necessary, 37.8                        -->\n            <!-- type-hybrid: Theorem 8 or if necessary, Theorem 37.8   -->\n            <xsl:apply-templates select=\"$target\" mode=\"smart-xref-text\">\n                <xsl:with-param name=\"text-style\" select=\"$text-style\" />\n                <xsl:with-param name=\"xref\" select=\".\" />\n                <xsl:with-param name=\"target\" select=\"$target\"/>\n                <xsl:with-param name=\"highest-match\" select=\"/..\" />\n                <xsl:with-param name=\"target-structure-number\">\n                    <xsl:apply-templates select=\"$target\" mode=\"structure-number\" />\n                </xsl:with-param>\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:when test=\"$text-style = 'title'\">\n            <xsl:choose>\n                <!-- 2020-02-18: a content override of a title is now  -->\n                <!-- deprecated (since there is now a \"custom\" option  -->\n                <!-- for text).  But it still \"works\", with warnings   -->\n                <!-- here.  Clean this up to complete the deprecation. -->\n                <!-- (We don't do this with other deprecations since   -->\n                <!-- we can get here by a variety of routes.)          -->\n                <xsl:when test=\"$b-has-content\">\n                    <xsl:message>\n                        <xsl:text>PTX:DEPRECATE:  </xsl:text>\n                        <xsl:text>An &lt;xref&gt; requests a 'title' as its text but also provides alternate content.  The construction is deprecated as of 2020-02-18.  Instead, specify that xref/@text should be 'custom', either globally or on a per-xref basis.</xsl:text>\n                    </xsl:message>\n                    <xsl:apply-templates select=\".\" mode=\"location-report\" />\n                    <xsl:copy-of select=\"$custom-text\" />\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:apply-templates select=\"$target\" mode=\"title-xref\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <xsl:when test=\"$text-style = 'custom'\">\n            <!-- use the content, do not include a number, a warning -->\n            <!-- if the content is empty is provided elsewhere       -->\n            <xsl:copy-of select=\"$custom-text\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message>PTX:BUG:  NO XREF TEXT GENERATED</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n    <xsl:apply-templates select=\".\" mode=\"latex-page-number\">\n        <xsl:with-param name=\"target\" select=\"$target\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- \"xref text\" like \"Theorem 4.5\" benefits from a non-breaking   -->\n<!-- space to keep the pieces together and discourage line-breaks  -->\n<!-- in the middle.  This is less relevant when used as a \"reason\" -->\n<!-- inside of display mathematics *and* it does not play nicely   -->\n<!-- with WeBWorK's PGML, so this template handles the necessary   -->\n<!-- exception for \"xref\" immediately inside of an \"mrow\".         -->\n<xsl:template match=\"xref|&PROOF-LIKE;\" mode=\"xref-text-separator\">\n    <xsl:choose>\n        <xsl:when test=\"parent::mrow\">\n            <xsl:text> </xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:call-template name=\"character\">\n                <xsl:with-param name=\"name\" select=\"'nbsp'\"/>\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- This is a hook to add page numbers to the end of the    -->\n<!-- xref text in LaTeX output via a \\pageref{}, optionally. -->\n<!-- Default for this hook is to do nothing.                 -->\n<xsl:template match=\"xref|&PROOF-LIKE;\" mode=\"latex-page-number\"/>\n\n<!-- A THEOREM-LIKE can have a *detached* PROOF-LIKE (which is not \"inner\" nor  -->\n<!-- \"solution\") that has @ref attribute which points to the THEOREM-LIKE being -->\n<!-- proved.  This abstract template will provide the link/knowl/whatever.      -->\n<!-- It is up to the employing conversion to place and format the result.       -->\n<xsl:template match=\"&PROOF-LIKE;\" mode=\"proof-xref-theorem\">\n    <xsl:choose>\n        <!-- produce nothing when there is not even a @ref -->\n        <xsl:when test=\"not(@ref)\"/>\n        <!-- only for \"detached\" proofs -->\n        <xsl:when test=\"&INNER-PROOF-FILTER;\"/>\n        <xsl:when test=\"&SOLUTION-PROOF-FILTER;\"/>\n        <!-- now really get into it analyzing target -->\n        <xsl:otherwise>\n            <xsl:variable name=\"target\" select=\"id(@ref)\"/>\n            <xsl:choose>\n                <xsl:when test=\"not($target)\">\n                    <xsl:message>PTX:ERROR:   a cross-reference (\"ref\") from a \"<xsl:value-of select=\"local-name()\"/>\" uses a reference [<xsl:value-of select=\"@ref\"/>] that does not point to any target.  Maybe the @ref and @xml:id values do not match?</xsl:message>\n                    <xsl:apply-templates select=\".\" mode=\"location-report\"/>\n                </xsl:when>\n                <xsl:when test=\"not($target[&THEOREM-FILTER;])\">\n                    <xsl:message>PTX:ERROR:   a cross-reference (\"ref\") from a \"<xsl:value-of select=\"local-name()\"/>\" uses a reference [<xsl:value-of select=\"@ref\"/>] that does not point to an element that is THEOREM-LIKE (target is a \"<xsl:value-of select=\"local-name($target)\"/>\" element).</xsl:message>\n                    <xsl:apply-templates select=\".\" mode=\"location-report\"/>\n                </xsl:when>\n                <!-- have a good target finally, do it -->\n                <xsl:otherwise>\n                    <xsl:variable name=\"text-style\">\n                        <xsl:apply-templates select=\".\" mode=\"get-text-style\" />\n                    </xsl:variable>\n                    <xsl:apply-templates select=\".\" mode=\"xref-link\">\n                        <xsl:with-param name=\"target\" select=\"$target\" />\n                        <xsl:with-param name=\"origin\" select=\"'xref'\" />\n                        <xsl:with-param name=\"content\">\n                            <xsl:apply-templates select=\".\" mode=\"xref-text\" >\n                                <xsl:with-param name=\"target\" select=\"$target\" />\n                                <xsl:with-param name=\"text-style\" select=\"$text-style\" />\n                                <!-- $custom-text is not an option -->\n                            </xsl:apply-templates>\n                        </xsl:with-param>\n                    </xsl:apply-templates>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- ###################### -->\n<!-- Smart Cross-References -->\n<!-- ###################### -->\n\n<!-- We climb the tree upward (ancestors) until we hit    -->\n<!-- the \"mathbook\" element, and then quit and assess.    -->\n<!-- The \"xref\" that started all this is used for the     -->\n<!-- eventual \"hybrid\" schemes, to see how close it is.   -->\n<!-- We record the oldest ancestor (highest) with a       -->\n<!-- *number* that is the *structure number* of the       -->\n<!-- target of the cross-reference.  So we know the       -->\n<!-- element (and its type) that originates the bulk      -->\n<!-- of the target's number.                              -->\n<!--                                                      -->\n<!-- There is one subtlety.  Usually one, and only one,   -->\n<!-- ancestor has the matching number, so we could halt   -->\n<!-- once found.  However, the immediately older ancestor -->\n<!-- can have the same number.  The \"objective\" element   -->\n<!-- is this way, it shares numbering with its containing -->\n<!-- division.  So we track through all the ancestors.    -->\n<!--                                                      -->\n<!-- To see if a xref is close to its target, we add the  -->\n<!-- *single* xref node to the subtree of the (highest)   -->\n<!-- node that provides the target's structure number.    -->\n<!-- By comparing the sizes of these node-sets, we can    -->\n<!-- determine if the xref lies outside the subtree and   -->\n<!-- then stick with global numbers.                      -->\n<!--                                                      -->\n<!-- $text-style                                          -->\n<!--   gets passed through, in order to consolidate       -->\n<!-- $xref                                                -->\n<!--   gets passed through for eventual membership test   -->\n<!-- $target                                              -->\n<!--   gets passed through for producing hybrid numbers   -->\n<!-- $highest-match                                       -->\n<!--   starts empty and is updated, if it finishes        -->\n<!--   empty then the target is high in the tree          -->\n<!--   or a match is a root for the structure number      -->\n<!-- $target-structure-number                             -->\n<!--   is produced once as a string, and passed through   -->\n<!--                                                      -->\n<!-- Result is a string that completes the xref text      -->\n<!--                                                      -->\n<xsl:template match=\"*\" mode=\"smart-xref-text\">\n    <xsl:param name=\"text-style\" />\n    <xsl:param name=\"xref\" />\n    <xsl:param name=\"target\" />\n    <xsl:param name=\"highest-match\" select=\"/..\" />\n    <xsl:param name=\"target-structure-number\" />\n    <!-- step up immediately, else test on  -->\n    <!-- structure numbers is vacuous       -->\n    <xsl:variable name=\"parent\" select=\"parent::*\" />\n    <xsl:variable name=\"parent-number\">\n        <xsl:apply-templates select=\"$parent\" mode=\"number\" />\n    </xsl:variable>\n    <xsl:choose>\n        <!-- quit at the top, and examine highest-match,    -->\n        <!-- and for phrase-hybrid, we do a membership test -->\n        <xsl:when test=\"$parent/self::mathbook|$parent/self::pretext\">\n            <xsl:variable name=\"requires-global\">\n                <xsl:choose>\n                    <!-- no match, already high up tree, so no  -->\n                    <!-- qualification is needed in either case -->\n                    <xsl:when test=\"not($highest-match)\">\n                        <xsl:text>false</xsl:text>\n                    </xsl:when>\n                    <!-- now have a match, so for phrase-global -->\n                    <!-- we will always print the global info   -->\n                    <xsl:when test=\"$text-style='phrase-global'\">\n                        <xsl:text>true</xsl:text>\n                    </xsl:when>\n                    <!-- now have a match, so for all other styles -->\n                    <!-- we check to see if xref is in subtree     -->\n                    <xsl:otherwise>\n                        <xsl:variable name=\"target-tree-size\" select=\"count($highest-match/descendant-or-self::*)\" />\n                        <xsl:variable name=\"xref-union-tree-size\" select=\"count(($xref | $highest-match/descendant-or-self::*))\" />\n                        <xsl:value-of select=\"$xref-union-tree-size = $target-tree-size + 1\" />\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:variable>\n            <!-- now know local/global, write trailing portion of text -->\n            <!-- here based on the style and the global requirement    -->\n            <!-- NB: the \"choose\" is mirrored in the more specific template, next -->\n            <!-- Question:  why does \"phrase-global\" come through here?           -->\n            <xsl:choose>\n                <!-- phrase styles may need remainder of phrase -->\n                <xsl:when test=\"(($text-style='phrase-global') or ($text-style='phrase-hybrid')) and ($requires-global = 'true')\">\n                    <!-- connector, internationalize -->\n                    <xsl:text> of </xsl:text>\n                    <xsl:apply-templates select=\"$highest-match\" mode=\"type-name\" />\n                    <xsl:call-template name=\"character\">\n                        <xsl:with-param name=\"name\" select=\"'nbsp'\"/>\n                    </xsl:call-template>\n                    <xsl:apply-templates select=\"$highest-match\" mode=\"xref-number\">\n                        <xsl:with-param name=\"xref\" select=\".\" />\n                    </xsl:apply-templates>\n                </xsl:when>\n                <!-- hybrid styles need number for remainder -->\n                <xsl:when test=\"($text-style='hybrid') or ($text-style='type-hybrid')\">\n                    <xsl:choose>\n                        <xsl:when test=\"$requires-global = 'true'\">\n                            <xsl:apply-templates select=\"$target\" mode=\"xref-number\">\n                                <xsl:with-param name=\"xref\" select=\".\" />\n                            </xsl:apply-templates>\n                        </xsl:when>\n                        <xsl:otherwise>\n                            <xsl:apply-templates select=\"$target\" mode=\"serial-number\" />\n                        </xsl:otherwise>\n                    </xsl:choose>\n                </xsl:when>\n            </xsl:choose>\n        </xsl:when>\n        <!-- possible missing implementation bug in numbering -->\n        <xsl:when test=\"$parent-number = '[NUM]'\">\n            <xsl:message>PTX:BUG:     Looks like a [<xsl:value-of select=\"local-name($parent)\" />] element has an ambiguous number, found while making cross-reference text</xsl:message>\n        </xsl:when>\n        <!-- no match, just recurse, and preserve $highest-match -->\n        <xsl:when test=\"not($parent-number = $target-structure-number)\">\n            <xsl:apply-templates select=\"$parent\" mode=\"smart-xref-text\">\n                <xsl:with-param name=\"text-style\" select=\"$text-style\" />\n                <xsl:with-param name=\"xref\" select=\"$xref\" />\n                <xsl:with-param name=\"target\" select=\"$target\"/>\n                <xsl:with-param name=\"highest-match\" select=\"$highest-match\" />\n                <xsl:with-param name=\"target-structure-number\" select=\"$target-structure-number\" />\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- a match, record in updated $highest-match -->\n        <xsl:when test=\"$parent-number = $target-structure-number\">\n            <xsl:apply-templates select=\"$parent\" mode=\"smart-xref-text\">\n                <xsl:with-param name=\"text-style\" select=\"$text-style\" />\n                <xsl:with-param name=\"xref\" select=\"$xref\" />\n                <xsl:with-param name=\"target\" select=\"$target\"/>\n                <xsl:with-param name=\"highest-match\" select=\"$parent\" />\n                <xsl:with-param name=\"target-structure-number\" select=\"$target-structure-number\" />\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- impossible to get here -->\n    </xsl:choose>\n</xsl:template>\n\n<!-- A hybrid scheme for a list item is only for list items         -->\n<!-- of an ordered list, we drop the list number (structure number) -->\n<!-- when xref and target are both inside the same list.            -->\n<!-- No need to recurse.  $target is context, allowing a match.     -->\n\n<xsl:template match=\"list//li\" mode=\"smart-xref-text\">\n    <xsl:param name=\"text-style\" />\n    <xsl:param name=\"xref\" />\n    <xsl:param name=\"target\" />\n\n    <xsl:variable name=\"targets-list\" select=\"$target/ancestor::list\" />\n    <xsl:variable name=\"xrefs-list\"   select=\"$xref/ancestor::list\" />\n\n    <!-- To be a local xref, the \"xref\" must live in some \"list\", and -->\n    <!-- it must be the same \"list\" as the \"li\" (which is in a list   -->\n    <!-- due to the match).  We use the negation to keep the logic    -->\n    <!-- the same as in the more general template, above              -->\n    <xsl:variable name=\"requires-global\" select=\"not((count($xrefs-list) = 1) and (count($targets-list|$xrefs-list) = 1))\" />\n\n    <!-- This \"choose\" largely matches above, and so maybe  -->\n    <!-- could be consolidated into a parameterized template -->\n    <xsl:choose>\n        <!-- phrase styles may need remainder of phrase -->\n        <xsl:when test=\"(($text-style='phrase-global') or ($text-style='phrase-hybrid')) and ($requires-global = 'true')\">\n            <!-- connector, internationalize -->\n            <xsl:text> of </xsl:text>\n            <xsl:apply-templates select=\"$targets-list\" mode=\"type-name\" />\n            <xsl:call-template name=\"character\">\n                <xsl:with-param name=\"name\" select=\"'nbsp'\"/>\n            </xsl:call-template>\n            <xsl:apply-templates select=\"$targets-list\" mode=\"xref-number\">\n                <xsl:with-param name=\"xref\" select=\".\" />\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- hybrid styles need number for remainder -->\n        <xsl:when test=\"($text-style='hybrid') or ($text-style='type-hybrid')\">\n            <xsl:choose>\n                <xsl:when test=\"$requires-global = 'true'\">\n                    <xsl:apply-templates select=\"$target\" mode=\"xref-number\">\n                        <xsl:with-param name=\"xref\" select=\".\" />\n                    </xsl:apply-templates>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:apply-templates select=\"$target\" mode=\"serial-number\" />\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n\n\n<!-- This is a base implementation for the xref-link -->\n<!-- template, which just repeats the content, with  -->\n<!-- an indication that this needs to be overridden  -->\n<!--   context -                                     -->\n<!--      an xref usually, typically its parent      -->\n<!--      is inspected to vary link style            -->\n<!--   content -                                     -->\n<!--     an RTF of the visual text,                  -->\n<!--     suitable for location of the link           -->\n<!--   target -                                      -->\n<!--     the target of the link, so the right        -->\n<!--     identification can be produced              -->\n<!--  implementation is based on location            -->\n<!-- This is an abstract template, to accomodate -->\n<!-- hard-coded HTML numbers and for LaTeX the   -->\n<!-- \\ref and \\label mechanism                   -->\n<xsl:template match=\"*\" mode=\"xref-number\">\n    <xsl:text>[XREFNUM]</xsl:text>\n</xsl:template>\n<xsl:template match=\"*\" mode=\"xref-link\">\n    <xsl:param name=\"target\" />\n    <xsl:param name=\"origin\"/>\n    <xsl:param name=\"content\" />\n\n    <xsl:message>PTX:BUG:     a new conversion needs an implementation of the modal \"xref-link\" template.  Search your output for \"[LINK:\"</xsl:message>\n    <xsl:text>[LINK: </xsl:text>\n    <xsl:copy-of select=\"$content\" />\n    <xsl:text>]</xsl:text>\n</xsl:template>\n\n<!-- For cross-references in books with parts, we only     -->\n<!-- want a part number in the cross-reference when the    -->\n<!-- \"xref\" and the \"$target\" are \"far apart,\" so the part -->\n<!-- number is necessary to disambiguate the result.  This -->\n<!-- utility uses the target as context and the xref as a  -->\n<!-- parameter.  It evaluates to 'true' if and only if the -->\n<!-- two nodes cross a part boundary *and* the target lies -->\n<!-- inside a part.                                        -->\n<!-- NB: \"ancestor-or-self\" is not used here               -->\n<!--   (a) the $xref is not a part                         -->\n<!--   (b) if the target is a part, its number will be     -->\n<!--       its serial number, and will not need a prefix,  -->\n<!--       so this will return false                       -->\n<xsl:template match=\"*\" mode=\"crosses-part-boundary\">\n    <xsl:param name=\"xref\" select=\"/..\" />\n    <xsl:choose>\n        <!-- if parts are not structural, no need -->\n        <xsl:when test=\"$parts='absent' or $parts='decorative'\">\n            <xsl:value-of select=\"false()\" />\n        </xsl:when>\n        <!-- if target is not in a part, no need -->\n        <xsl:when test=\"not(ancestor::part)\">\n            <xsl:value-of select=\"false()\" />\n        </xsl:when>\n        <!-- xref can't be in target's part, so necessary -->\n        <xsl:when test=\"not($xref/ancestor::part)\">\n            <xsl:value-of select=\"true()\" />\n        </xsl:when>\n        <!-- target and xref both in parts.  Same one? -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"count(ancestor::part|$xref/ancestor::part) = 2\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- #################### -->\n<!-- Common Constructions -->\n<!-- #################### -->\n\n<!-- With no special formatting, \"PreTeXt\" can be in -common -->\n<!-- Ditto PreFigure, a great companion project.             -->\n<!-- Use of \"pretext\" as a root container should get higher  -->\n<!-- priority when used with /, or as a variable             -->\n<!-- NB: there is a \\XeTeX macro which renders the first \"E\" -->\n<!-- backwards, but it is only defined when actually using   -->\n<!-- xelatex (not pdflatex).  The LaTeX/PDF conversion could -->\n<!-- conditionally define an internal macro based on the     -->\n<!-- engine.  But we do not talk about XeTeX as much as      -->\n<!-- XeLaTeX.                                                -->\n<!-- NB: We have not attempted to make the \"xe-\" variants    -->\n<!-- with fancy typography for HTML output, but one could    -->\n<!-- mimic the HTML/CSS used for TeX and LaTeX in that       -->\n<!-- conversion.                                             -->\n<xsl:template match=\"pretext\">\n    <xsl:text>PreTeXt</xsl:text>\n</xsl:template>\n<!-- NB: when PreFigure has a namespace then the empty  -->\n<!-- element text generator can be a simpler match here -->\n<xsl:template match=\"prefigure[not(node())]\">\n    <xsl:text>PreFigure</xsl:text>\n</xsl:template>\n<xsl:template match=\"xetex\">\n    <xsl:text>XeTeX</xsl:text>\n</xsl:template>\n<xsl:template match=\"xelatex\">\n    <xsl:text>XeLaTeX</xsl:text>\n</xsl:template>\n\n\n<!-- We place the 13 Latin abbreviations here since they -->\n<!-- are fairly basic.  The final period is implemented  -->\n<!-- as a named template, so we can override it in the   -->\n<!-- LaTeX conversion and get reasonable behavior (i.e.  -->\n<!-- not confused as the end of a sentence).             -->\n\n<!-- See: Chicago Manual of Style, 15e, 15.44, 15.55     -->\n<!-- See: Bringhurst, 4e, 5.4.4                          -->\n\n<xsl:template name=\"abbreviation-period\">\n    <xsl:text>.</xsl:text>\n</xsl:template>\n\n<!-- anno Domini, in the year of the Lord -->\n<!-- CMOS, Bringurst 5.4.4, no periods    -->\n<xsl:template match=\"ad\">\n    <xsl:text>AD</xsl:text>\n</xsl:template>\n<!-- ante meridiem, before midday      -->\n<!-- CMOS, Bringurst 5.4.4, no periods -->\n<xsl:template match=\"am\">\n    <xsl:text>AM</xsl:text>\n</xsl:template>\n<!-- before Christ                     -->\n<!-- CMOS, Bringurst 5.4.4, no periods -->\n<xsl:template match=\"bc\">\n    <xsl:text>BC</xsl:text>\n</xsl:template>\n<!-- circa, about                         -->\n<!-- CMOS, ca. preferable (c. is century) -->\n<!-- \"circa\" deprecated 2018-12-30        -->\n<xsl:template match=\"ca\">\n    <xsl:text>ca</xsl:text>\n    <xsl:call-template name=\"abbreviation-period\"/>\n</xsl:template>\n<!-- exempli gratia, for example -->\n<xsl:template match=\"eg\">\n    <xsl:text>e.g</xsl:text>\n    <xsl:call-template name=\"abbreviation-period\"/>\n</xsl:template>\n<!-- et alia, and others -->\n<xsl:template match=\"etal\">\n    <xsl:text>et al</xsl:text>\n    <xsl:call-template name=\"abbreviation-period\"/>\n</xsl:template>\n<!-- et caetera, and the rest -->\n<xsl:template match=\"etc\">\n    <xsl:text>etc</xsl:text>\n    <xsl:call-template name=\"abbreviation-period\"/>\n</xsl:template>\n<!-- id est, in other words -->\n<xsl:template match=\"ie\">\n    <xsl:text>i.e</xsl:text>\n    <xsl:call-template name=\"abbreviation-period\"/>\n</xsl:template>\n<!-- nota bene, note well -->\n<!-- CMOS, no periods     -->\n<xsl:template match=\"nb\">\n    <xsl:text>NB</xsl:text>\n</xsl:template>\n<!-- post meridiem, after midday       -->\n<!-- CMOS, Bringurst 5.4.4, no periods -->\n<xsl:template match=\"pm\">\n    <xsl:text>PM</xsl:text>\n</xsl:template>\n<!-- post scriptum, after what has been written -->\n<!-- CMOS, no periods                           -->\n<xsl:template match=\"ps\">\n    <xsl:text>PS</xsl:text>\n</xsl:template>\n<!-- versus, against                 -->\n<!-- CMOS, v. only in legal contexts -->\n<xsl:template match=\"vs\">\n    <xsl:text>vs</xsl:text>\n    <xsl:call-template name=\"abbreviation-period\"/>\n</xsl:template>\n<!-- videlicet, namely -->\n<xsl:template match=\"viz\">\n    <xsl:text>viz</xsl:text>\n    <xsl:call-template name=\"abbreviation-period\"/>\n</xsl:template>\n\n<!-- ################## -->\n<!-- Special Characters -->\n<!-- ################## -->\n\n<!-- Dashes and hyphens - worth reviewing       -->\n<!-- https://jkorpela.fi/dashes.html -->\n\n<!-- An mdash may have thin space around it, otherwise it        -->\n<!-- should have none.  It might be difficult to enforce this    -->\n<!-- (we could!), but we don't.  Instead, we make the thin-space -->\n<!-- version a publisher option.  So the \"thin-space\" character  -->\n<!-- joins the representation table for that purpose, and the    -->\n<!-- assembly of the pieces happens here.                        -->\n\n<!-- The variable, surrounding space. This approach is   -->\n<!-- executed once, so not local to template for \"mdash\" -->\n<xsl:variable name=\"emdash-space-char\">\n    <xsl:choose>\n        <xsl:when test=\"$emdash-space='none'\">\n            <xsl:text />\n        </xsl:when>\n        <xsl:when test=\"$emdash-space='thin'\">\n            <xsl:call-template name=\"character\">\n                <xsl:with-param name=\"name\" select=\"'thin-space'\"/>\n            </xsl:call-template>\n        </xsl:when>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:template match=\"mdash\">\n    <xsl:value-of select=\"$emdash-space-char\"/>\n    <xsl:call-template name=\"character\">\n        <xsl:with-param name=\"name\" select=\"'mdash'\"/>\n    </xsl:call-template>\n    <xsl:value-of select=\"$emdash-space-char\"/>\n</xsl:template>\n\n\n<!-- These are characters which may look really bad                 -->\n<!-- if faked from a keyboard (double brackets),                    -->\n<!-- or lack an ASCII equivalent (like per-mille).  So we leave     -->\n<!-- them undefined here as named templates with warnings and       -->\n<!-- alarm bells, so that if a new conversion does not have an      -->\n<!-- implementation, that will be discovered early in development.  -->\n\n<xsl:template name=\"warn-unimplemented-character\">\n    <xsl:param name=\"char-name\"/>\n     <xsl:message>PTX:BUG:   the character named \"<xsl:value-of select=\"$char-name\"/>\" needs an implementation in the current conversion</xsl:message>\n     <xsl:text>[[[</xsl:text>\n     <xsl:value-of select=\"$char-name\"/>\n     <xsl:text>]]]</xsl:text>\n</xsl:template>\n\n<!-- The table of character representations: one row per character, -->\n<!-- one column per representation, each read by a conversion's     -->\n<!-- modal \"character\" template; a character whose rendering needs  -->\n<!-- more than a column value (fonts, wrapper markup) gets a        -->\n<!-- per-character template overriding that mode.  Column notes:    -->\n<!--   \"unicode\"  the bare code point                               -->\n<!--   \"latex\"    macro or construction; the reader appends an      -->\n<!--              empty group ({}) unless  latex-ending=\"no\"        -->\n<!--   \"ascii\"    7-bit stand-in for text's ascii election;         -->\n<!--              absent = unimplemented, warns                     -->\n<!--   \"webwork\"  PGML form for WeBWorK problem extraction;         -->\n<!--              absent = unimplemented, warns                     -->\n<!--   \"braille\"  absent = liblouis uses the \"unicode\" value;       -->\n<!--              a value = a substitute character, since liblouis  -->\n<!--              cannot use the true one; \"none\" = no rendering    -->\n<!--              at all, warns                                     -->\n\n<xsl:variable name=\"character-rtf\">\n    <!-- U+00A0: NO-BREAK SPACE -->\n    <!-- (the \"&nbsp;\" entity is undefined in XSL; always the numeric reference) -->\n    <char name=\"nbsp\"          unicode=\"&#x00a0;\"   latex=\"~\" latex-ending=\"no\"               ascii=\" \"          webwork=\"[$NBSP]*\"/>\n    <!-- U+2013: EN DASH -->\n    <char name=\"ndash\"         unicode=\"&#x2013;\"   latex=\"\\textendash\"                       ascii=\"-\"          webwork=\"[$NDASH]*\"/>\n    <!-- U+2014: EM DASH -->\n    <char name=\"mdash\"         unicode=\"&#x2014;\"   latex=\"\\textemdash\"                       ascii=\"--\"         webwork=\"[$MDASH]*\"/>\n    <!-- U+2009: THIN SPACE -->\n    <char name=\"thin-space\"    unicode=\"&#x2009;\"   latex=\"\\,\" latex-ending=\"no\"              ascii=\" \"          webwork=\" \"/>\n    <!-- U+27E6: MATHEMATICAL LEFT WHITE SQUARE BRACKET -->\n    <char name=\"ldblbracket\"   unicode=\"&#x27e6;\"   latex=\"\\textlbrackdbl\"                    braille=\"none\"/>\n    <!-- U+27E7: MATHEMATICAL RIGHT WHITE SQUARE BRACKET -->\n    <char name=\"rdblbracket\"   unicode=\"&#x27e7;\"   latex=\"\\textrbrackdbl\"                    braille=\"none\"/>\n    <!-- U+27E8: MATHEMATICAL LEFT ANGLE BRACKET -->\n    <char name=\"langle\"        unicode=\"&#x27e8;\"   latex=\"\\textlangle\"                       ascii=\"&lt;\"/>\n    <!-- U+27E9: MATHEMATICAL RIGHT ANGLE BRACKET -->\n    <char name=\"rangle\"        unicode=\"&#x27e9;\"   latex=\"\\textrangle\"                       ascii=\"&gt;\"/>\n    <!-- U+2026: HORIZONTAL ELLIPSIS -->\n    <char name=\"ellipsis\"      unicode=\"&#x2026;\"   latex=\"\\textellipsis\"                     ascii=\"...\"        webwork=\"...\"/>\n    <!-- U+00B7: MIDDLE DOT -->\n    <!-- (sometimes like a decorative dash; tex.stackexchange.com/questions/19180) -->\n    <char name=\"midpoint\"      unicode=\"&#x00b7;\"   latex=\"\\textperiodcentered\"               ascii=\"*\"/>\n    <!-- U+2053: SWUNG DASH -->\n    <char name=\"swungdash\"     unicode=\"&#x2053;\"   latex=\"\\ptxswungdash\"                     ascii=\"~\"          braille=\"~\"/>\n    <!-- U+2030: PER MILLE SIGN -->\n    <char name=\"permille\"      unicode=\"&#x2030;\"   latex=\"\\textperthousand\"                  ascii=\"o/oo\"       braille=\"none\"/>\n    <!-- U+00B6: PILCROW SIGN -->\n    <char name=\"pilcrow\"       unicode=\"&#x00b6;\"   latex=\"\\textpilcrow\"                      ascii=\"[pilcrow]\"/>\n    <!-- U+00A7: SECTION SIGN -->\n    <char name=\"section-mark\"  unicode=\"&#x00a7;\"   latex=\"\\textsection\"                      ascii=\"[section]\"/>\n    <!-- U+2212: MINUS SIGN -->\n    <char name=\"minus\"         unicode=\"&#x2212;\"   latex=\"\\textminus\"                        ascii=\"-\"/>\n    <!-- U+00D7: MULTIPLICATION SIGN -->\n    <char name=\"times\"         unicode=\"&#x00d7;\"   latex=\"\\texttimes\"                        ascii=\"x\"/>\n    <!-- U+2044: FRACTION SLASH -->\n    <!-- (the LaTeX form should not allow a linebreak; not tested) -->\n    <char name=\"solidus\"       unicode=\"&#x2044;\"   latex=\"\\textfractionsolidus\"              ascii=\"/\"          braille=\"/\"/>\n    <!-- U+00F7: DIVISION SIGN -->\n    <char name=\"obelus\"        unicode=\"&#x00f7;\"   latex=\"\\textdiv\"                          ascii=\"/\"/>\n    <!-- U+00B1: PLUS-MINUS SIGN -->\n    <char name=\"plusminus\"     unicode=\"&#x00b1;\"   latex=\"\\textpm\"                           ascii=\"+/-\"/>\n    <!-- U+00A9: COPYRIGHT SIGN -->\n    <!-- (LaTeX form: tex.stackexchange.com/questions/1676) -->\n    <char name=\"copyright\"     unicode=\"&#x00a9;\"   latex=\"\\textcopyright\"                    ascii=\"(c)\"/>\n    <!-- U+2117: SOUND RECORDING COPYRIGHT -->\n    <char name=\"phonomark\"     unicode=\"&#x2117;\"   latex=\"\\textcircledP\"                     braille=\"none\"/>\n    <!-- U+1F12F: COPYLEFT SYMBOL -->\n    <!-- (may not be universally available in fonts; Open C (U+0254) -->\n    <!-- plus Combining Circle (U+20DD) can imitate)                 -->\n    <char name=\"copyleft\"      unicode=\"&#x1f12f;\"  latex=\"\\textcopyleft\"                     braille=\"none\"/>\n    <!-- U+00AE: REGISTERED SIGN -->\n    <!-- (Bringhurst: should be superscript; not so in a font is a   -->\n    <!-- font mistake, but a \"sup\" wrapper renders way too small in  -->\n    <!-- a correct font)                                             -->\n    <char name=\"registered\"    unicode=\"&#x00ae;\"   latex=\"\\textregistered\"                   ascii=\"(R)\"/>\n    <!-- U+2122: TRADE MARK SIGN -->\n    <char name=\"trademark\"     unicode=\"&#x2122;\"   latex=\"\\texttrademark\"                    ascii=\"(TM)\"/>\n    <!-- U+2120: SERVICE MARK -->\n    <char name=\"servicemark\"   unicode=\"&#x2120;\"   latex=\"\\textservicemark\"                  braille=\"none\"/>\n    <!-- U+00B0: DEGREE SIGN -->\n    <char name=\"degree\"        unicode=\"&#x00b0;\"   latex=\"\\textdegree\"                       ascii=\"deg\"/>\n    <!-- U+2032: PRIME -->\n    <!-- (a LaTeX math construction looks better, but needs protection    -->\n    <!-- during text-processing; Bringhurst: many text fonts lack a prime -->\n    <!-- and/or double-prime glyph)                                       -->\n    <char name=\"prime\"         unicode=\"&#x2032;\"   latex=\"\\textquotesingle\"                  ascii=\"'\"/>\n    <!-- U+2033: DOUBLE PRIME -->\n    <char name=\"dblprime\"      unicode=\"&#x2033;\"   latex=\"\\textquotesingle\\textquotesingle\"  ascii=\"''\"/>\n</xsl:variable>\n\n<xsl:variable name=\"character-table\"\n    select=\"exsl:node-set($character-rtf)\"/>\n\n<xsl:key name=\"character-key\" match=\"char\" use=\"@name\"/>\n\n<!-- Look up a character by name, then render it with the modal  -->\n<!-- \"character\" implementation in effect.  An unknown name is a -->\n<!-- defect in a calling template, not an authoring error.       -->\n<xsl:template name=\"character\">\n    <xsl:param name=\"name\"/>\n    <!-- a key resolves within the document holding the context -->\n    <!-- node, so step inside the table, a node-set of one node -->\n    <xsl:for-each select=\"$character-table\">\n        <xsl:variable name=\"the-row\" select=\"key('character-key', $name)\"/>\n        <xsl:choose>\n            <xsl:when test=\"$the-row\">\n                <xsl:apply-templates select=\"$the-row\" mode=\"character\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:message>PTX:BUG:   the character named \"<xsl:value-of select=\"$name\"/>\" is not in the character table</xsl:message>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:for-each>\n</xsl:template>\n\n<!-- A conversion without a modal \"character\" implementation gets -->\n<!-- a warning for every character in the table                   -->\n<xsl:template match=\"char\" mode=\"character\">\n    <xsl:call-template name=\"warn-unimplemented-character\">\n        <xsl:with-param name=\"char-name\" select=\"@name\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- The empty source elements share one dispatcher; \"mdash\" is an  -->\n<!-- exception (publisher-elected surrounding space), and the       -->\n<!-- \"thin-space\" row has no element of its own (it exists for the  -->\n<!-- \"mdash\" machinery and internal use)                            -->\n<xsl:template match=\"nbsp|ndash|ldblbracket|rdblbracket|langle|rangle|ellipsis|midpoint|swungdash|permille|pilcrow|section-mark|minus|times|solidus|obelus|plusminus|copyright|phonomark|copyleft|registered|trademark|servicemark|degree|prime|dblprime\">\n    <xsl:call-template name=\"character\">\n        <xsl:with-param name=\"name\" select=\"local-name()\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- A given document may use for different characters for quotations:         -->\n<!--                                                                           -->\n<!--     left/right (open/close)  by  primary/secondary                        -->\n<!--                                                                           -->\n<!-- We then define elements for these characters (should be rarely used)      -->\n<!-- and elements for groupings that will atart with a \"left\" character        -->\n<!-- and end with a \"right\" character.  Some conversions define these four     -->\n<!-- characters outright and universally (e.g. braille), some have more        -->\n<!-- involved processes that react to the ambient language (e.g. HTML). So     -->\n<!-- the follwing for templates are an interface of sorts for implementations. -->\n\n<!-- Left Single Quote -->\n<xsl:template match=\"*\" mode=\"lsq-character\">\n    <xsl:call-template name=\"warn-unimplemented-character\">\n        <xsl:with-param name=\"char-name\" select=\"'lsq'\"/>\n    </xsl:call-template>\n</xsl:template>\n<xsl:template match=\"lsq\">\n    <xsl:apply-templates select=\".\" mode=\"lsq-character\"/>\n</xsl:template>\n\n<!-- Right Single Quote -->\n<xsl:template match=\"*\" mode=\"rsq-character\">\n    <xsl:call-template name=\"warn-unimplemented-character\">\n        <xsl:with-param name=\"char-name\" select=\"'rsq'\"/>\n    </xsl:call-template>\n</xsl:template>\n<xsl:template match=\"rsq\">\n    <xsl:apply-templates select=\".\" mode=\"rsq-character\"/>\n</xsl:template>\n\n<!-- Left (Double) Quote -->\n<xsl:template match=\"*\" mode=\"lq-character\">\n    <xsl:call-template name=\"warn-unimplemented-character\">\n        <xsl:with-param name=\"char-name\" select=\"'lq'\"/>\n    </xsl:call-template>\n</xsl:template>\n<xsl:template match=\"lq\">\n    <xsl:apply-templates select=\".\" mode=\"lq-character\"/>\n</xsl:template>\n\n<!-- Right (Double) Quote -->\n<xsl:template match=\"*\" mode=\"rq-character\">\n    <xsl:call-template name=\"warn-unimplemented-character\">\n        <xsl:with-param name=\"char-name\" select=\"'rq'\"/>\n    </xsl:call-template>\n</xsl:template>\n<xsl:template match=\"rq\">\n    <xsl:apply-templates select=\".\" mode=\"rq-character\"/>\n</xsl:template>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<!-- Coordinates, Temperature, English distance -->\n<!-- Intended for simple non-technical uses, without too -->\n<!-- much overhead.  The SI unit markup would be better  -->\n<!-- suited for scientific or technical work.            -->\n\n\n\n\n<!-- Characters for Tagging Equations -->\n\n<xsl:template name=\"tag-star\">\n    <xsl:call-template name=\"warn-unimplemented-character\">\n        <xsl:with-param name=\"char-name\" select=\"'tag-star'\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<xsl:template name=\"tag-dagger\">\n    <xsl:call-template name=\"warn-unimplemented-character\">\n        <xsl:with-param name=\"char-name\" select=\"'tag-dagger'\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<xsl:template name=\"tag-daggerdbl\">\n    <xsl:call-template name=\"warn-unimplemented-character\">\n        <xsl:with-param name=\"char-name\" select=\"'tag-daggerdbl'\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<xsl:template name=\"tag-hash\">\n    <xsl:call-template name=\"warn-unimplemented-character\">\n        <xsl:with-param name=\"char-name\" select=\"'tag-hash'\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- AMS symbol designed for both text and math modes -->\n<xsl:template name=\"tag-maltese\">\n    <xsl:call-template name=\"warn-unimplemented-character\">\n        <xsl:with-param name=\"char-name\" select=\"'tag-maltese'\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- Dots\nhttp://tex.stackexchange.com/questions/19180/which-dot-character-to-use-in-which-context\n\nSwung Dash\nhttp://andrewmccarthy.ie/2014/11/06/swung-dash-in-latex/\n -->\n<!-- ######### -->\n<!-- Groupings -->\n<!-- ######## -->\n\n<!-- Characters with left and right variants naturally       -->\n<!-- give rise to tags with begin and end variants           -->\n\n<xsl:template match=\"q\">\n    <xsl:apply-templates select=\".\" mode=\"lq-character\"/>\n    <xsl:apply-templates/>\n    <xsl:apply-templates select=\".\" mode=\"rq-character\"/>\n</xsl:template>\n\n<xsl:template match=\"sq\">\n    <xsl:apply-templates select=\".\" mode=\"lsq-character\"/>\n    <xsl:apply-templates/>\n    <xsl:apply-templates select=\".\" mode=\"rsq-character\"/>\n</xsl:template>\n\n<xsl:template match=\"dblbrackets\">\n    <xsl:call-template name=\"character\">\n        <xsl:with-param name=\"name\" select=\"'ldblbracket'\"/>\n    </xsl:call-template>\n    <xsl:apply-templates/>\n    <xsl:call-template name=\"character\">\n        <xsl:with-param name=\"name\" select=\"'rdblbracket'\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<xsl:template match=\"angles\">\n    <xsl:call-template name=\"character\">\n        <xsl:with-param name=\"name\" select=\"'langle'\"/>\n    </xsl:call-template>\n    <xsl:apply-templates/>\n    <xsl:call-template name=\"character\">\n        <xsl:with-param name=\"name\" select=\"'rangle'\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- ########## -->\n<!-- XML Syntax -->\n<!-- ########## -->\n\n<!-- So we can write knowledgeably about XML in documentation -->\n<!-- NB: we can use RTFs to keep this in -common since the    -->\n<!-- content of each element is so simple                     -->\n\n<!-- A tag, with angle brackets and monospace font -->\n<xsl:template match=\"tag\">\n    <xsl:call-template name=\"code-wrapper\">\n        <xsl:with-param name=\"content\">\n            <xsl:text>&lt;</xsl:text>\n            <xsl:value-of select=\".\"/>\n            <xsl:text>&gt;</xsl:text>\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- An empty tag, with angle brackets and monospace font -->\n<xsl:template match=\"tage\">\n    <xsl:call-template name=\"code-wrapper\">\n        <xsl:with-param name=\"content\">\n            <xsl:text>&lt;</xsl:text>\n            <xsl:value-of select=\".\"/>\n            <xsl:text>/&gt;</xsl:text>\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- An attribute, with @ and monospace font -->\n<xsl:template match=\"attr\">\n    <xsl:call-template name=\"code-wrapper\">\n        <xsl:with-param name=\"content\">\n            <xsl:text>@</xsl:text>\n            <xsl:value-of select=\".\"/>\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- ################### -->\n<!-- Non-Semantic Markup -->\n<!-- ################### -->\n\n<!-- It is useful, initially for bibliographies to be able    -->\n<!-- to render some chunks of text as simply bold or italic.  -->\n<!--                                                          -->\n<!-- So we make an abstract modal templates for this purpose, -->\n<!-- with implementations in derived stylesheets.  We are     -->\n<!-- also able to employ these to define \"internal\" markup,   -->\n<!-- which we use on externally produced source.              -->\n\n<!-- These stubs alert a developer to the need for      -->\n<!-- implementation in a derived stylesheet.  These     -->\n<!-- allow us to define our own bibliography management -->\n<!-- here, not repeatedly in derived stylesheets.       -->\n\n<xsl:template match=\"*\" mode=\"italic\">\n    <xsl:message>PTX:BUG:  current conversion needs an implementation of the italic font</xsl:message>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"bold\">\n    <xsl:message>PTX:BUG:  current conversion needs an implementation of the bold font</xsl:message>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"monospace\">\n    <xsl:message>PTX:BUG:  current conversion needs an implementation of the monospace font</xsl:message>\n</xsl:template>\n\n<xsl:template name=\"biblio-period\">\n    <xsl:message>PTX:BUG:  current conversion needs an implementation of a bibliographic period</xsl:message>\n</xsl:template>\n\n<!-- Single implementations of highly non-semantic elements    -->\n<!-- which trade on the modal templates.  We can use these in  -->\n<!-- manufactured text which is not authored, nor rarely seen. -->\n\n<xsl:template match=\"pi:italic\">\n    <xsl:apply-templates select=\".\" mode=\"italic\"/>\n</xsl:template>\n\n<xsl:template match=\"pi:bold\">\n    <xsl:apply-templates select=\".\" mode=\"bold\"/>\n</xsl:template>\n\n<!-- ############## -->\n<!-- Bibliographies -->\n<!-- ############## -->\n\n<!-- Note: this general approach to \"biblio\" entries is by-passed     -->\n<!-- in the HTML conversion, due to larger architectural limitations. -->\n\n<!-- Historical: first pass, mixed content, with a  -->\n<!-- few elements implemented for visual appearance -->\n<xsl:template match=\"biblio[@type = 'raw']\">\n    <xsl:apply-templates select=\".\" mode=\"bibentry-wrapper\">\n        <xsl:with-param name=\"content\">\n            <!-- mixed-content, text is relevant -->\n            <xsl:apply-templates select=\"text()|*\"/>\n        </xsl:with-param>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- \"BibTeX style\": initiated by David Farmer  -->\n<!-- December 2021, see commit 44c9f8e00d525796 -->\n<!-- Structured, but rendered in document order -->\n<xsl:template match=\"biblio[@type = 'bibtex']\">\n    <xsl:apply-templates select=\".\" mode=\"bibentry-wrapper\">\n        <xsl:with-param name=\"content\">\n            <!-- structured, elements only, document order -->\n            <xsl:apply-templates select=\"*\"/>\n        </xsl:with-param>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- If a plain \"biblio\" survives pre-processing, it means there -->\n<!-- is no CSL stylesheet specified and we just do our best to   -->\n<!-- make something reasonable.  We do assume the author knows   -->\n<!-- this, and has authored the elements in the desired order    -->\n<!-- (processing is in \"document order\").                        -->\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]\">\n    <xsl:apply-templates select=\".\" mode=\"bibentry-wrapper\">\n        <xsl:with-param name=\"content\">\n            <!-- structured, elements only, document order -->\n            <xsl:apply-templates select=\"*\"/>\n        </xsl:with-param>\n    </xsl:apply-templates>\n</xsl:template>\n\n<xsl:template match=\"biblio\" mode=\"bibentry-wrapper\">\n    <xsl:message>PTX:BUG:  current conversion needs an implementation of the \"bibentry-wrapper\" template</xsl:message>\n</xsl:template>\n\n\n<!-- Raw Bibliographic Entry Formatting              -->\n<!-- Markup really, not full-blown data preservation -->\n\n<xsl:template match=\"pi:csl-citation\">\n    <!-- Some citations have titles, some titles have  -->\n    <!-- math, and so cannot just select \"text + xref\" -->\n    <xsl:apply-templates select=\"node()\"/>\n</xsl:template>\n\n<!-- Title in italics -->\n<xsl:template match=\"biblio[@type='raw']/title\">\n    <xsl:apply-templates select=\".\" mode=\"italic\"/>\n</xsl:template>\n\n<!-- No treatment for journal -->\n<xsl:template match=\"biblio[@type='raw']/journal\">\n    <xsl:apply-templates/>\n</xsl:template>\n\n<!-- Volume in bold -->\n<xsl:template match=\"biblio[@type='raw']/volume\">\n    <xsl:apply-templates select=\".\" mode=\"bold\"/>\n</xsl:template>\n\n<!-- Year in parentheses -->\n<xsl:template match=\"biblio[@type='raw']/year\">\n    <xsl:text>(</xsl:text>\n    <xsl:apply-templates/>\n    <xsl:text>)</xsl:text>\n</xsl:template>\n\n<!-- Number -->\n<xsl:template match=\"biblio[@type='raw']/number\">\n    <xsl:text>no</xsl:text>\n    <xsl:call-template name=\"biblio-period\"/>\n    <xsl:call-template name=\"character\">\n        <xsl:with-param name=\"name\" select=\"'thin-space'\"/>\n    </xsl:call-template>\n    <xsl:apply-templates/>\n</xsl:template>\n\n<!-- Ibid, nee ibidem, empty element -->\n<xsl:template match=\"biblio[@type='raw']/ibid\">\n    <xsl:text>Ibid</xsl:text>\n    <xsl:call-template name=\"biblio-period\"/>\n    <!-- Generally has a trailing comma, so no thin space -->\n</xsl:template>\n\n\n<!-- Fully marked-up bibtex-style bibliographic entry formatting.    -->\n<!-- Current treatment assumes elements are in the correct order.    -->\n<!-- Each field is followed by its own separator, except the last,   -->\n<!-- which is finished with a period (see \"bibtex-separator\").       -->\n\n<!-- Trailing punctuation for a BibTeX field: the given separator   -->\n<!-- when another field follows, otherwise a period.  An annotation -->\n<!-- \"note\" is not an inline field, so it does not count here.       -->\n<xsl:template match=\"*\" mode=\"bibtex-separator\">\n    <xsl:param name=\"separator\"/>\n    <xsl:choose>\n        <xsl:when test=\"following-sibling::*[not(self::note)]\">\n            <xsl:value-of select=\"$separator\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>.</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Author, comma after -->\n<xsl:template match=\"biblio[@type='bibtex']/author\">\n    <xsl:apply-templates select=\"text()\"/>\n    <xsl:apply-templates select=\".\" mode=\"bibtex-separator\">\n        <xsl:with-param name=\"separator\" select=\"', '\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Editor, labelled, comma after -->\n<xsl:template match=\"biblio[@type='bibtex']/editor\">\n    <xsl:apply-templates select=\"text()\"/>\n    <xsl:text> (ed.)</xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"bibtex-separator\">\n        <xsl:with-param name=\"separator\" select=\"', '\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Title in italics, comma after -->\n<xsl:template match=\"biblio[@type='bibtex']/title\">\n    <xsl:apply-templates select=\".\" mode=\"italic\"/>\n    <xsl:apply-templates select=\".\" mode=\"bibtex-separator\">\n        <xsl:with-param name=\"separator\" select=\"', '\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Journal, space after -->\n<xsl:template match=\"biblio[@type='bibtex']/journal\">\n    <xsl:apply-templates select=\"text()|m\"/>\n    <xsl:apply-templates select=\".\" mode=\"bibtex-separator\">\n        <xsl:with-param name=\"separator\" select=\"' '\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Volume in bold, space after -->\n<xsl:template match=\"biblio[@type='bibtex']/volume\">\n    <xsl:apply-templates select=\".\" mode=\"bold\"/>\n    <xsl:apply-templates select=\".\" mode=\"bibtex-separator\">\n        <xsl:with-param name=\"separator\" select=\"' '\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Series, comma after (so it separates from a following publisher) -->\n<xsl:template match=\"biblio[@type='bibtex']/series\">\n    <xsl:apply-templates select=\"text()\"/>\n    <xsl:apply-templates select=\".\" mode=\"bibtex-separator\">\n        <xsl:with-param name=\"separator\" select=\"', '\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Publisher, comma after -->\n<xsl:template match=\"biblio[@type='bibtex']/publisher\">\n    <xsl:apply-templates select=\"text()\"/>\n    <xsl:apply-templates select=\".\" mode=\"bibtex-separator\">\n        <xsl:with-param name=\"separator\" select=\"', '\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Year in parentheses, space after -->\n<xsl:template match=\"biblio[@type='bibtex']/year\">\n    <xsl:text>(</xsl:text>\n    <xsl:apply-templates select=\"text()\"/>\n    <xsl:text>)</xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"bibtex-separator\">\n        <xsl:with-param name=\"separator\" select=\"' '\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Number, as \"no. N\", space after -->\n<xsl:template match=\"biblio[@type='bibtex']/number\">\n    <xsl:text>no</xsl:text>\n    <xsl:call-template name=\"biblio-period\"/>\n    <xsl:call-template name=\"character\">\n        <xsl:with-param name=\"name\" select=\"'thin-space'\"/>\n    </xsl:call-template>\n    <xsl:apply-templates select=\"text()\"/>\n    <xsl:apply-templates select=\".\" mode=\"bibtex-separator\">\n        <xsl:with-param name=\"separator\" select=\"' '\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- A \"pubnote\" holds free-form publication information.  Render all -->\n<!-- content (not just \"text()\") so inline markup such as an \"ndash\"  -->\n<!-- is not dropped; comma after.                                     -->\n<xsl:template match=\"biblio[@type='bibtex']/pubnote\">\n    <xsl:apply-templates/>\n    <xsl:apply-templates select=\".\" mode=\"bibtex-separator\">\n        <xsl:with-param name=\"separator\" select=\"', '\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Pages, two forms: a total count (a book), or a @start/@end       -->\n<!-- range.  Comma after, unless last, when \"bibtex-separator\" ends   -->\n<!-- the entry with a period.                                         -->\n<xsl:template match=\"biblio[@type='bibtex']/pages[not(@start)]\">\n    <xsl:apply-templates select=\"text()\"/>\n    <xsl:apply-templates select=\".\" mode=\"bibtex-separator\">\n        <xsl:with-param name=\"separator\" select=\"', '\"/>\n    </xsl:apply-templates>\n</xsl:template>\n<xsl:template match=\"biblio[@type='bibtex']/pages[@start]\">\n    <xsl:text>pp</xsl:text>\n    <xsl:call-template name=\"biblio-period\"/>\n    <xsl:call-template name=\"character\">\n        <xsl:with-param name=\"name\" select=\"'thin-space'\"/>\n    </xsl:call-template>\n    <xsl:value-of select=\"@start\"/><xsl:text>-</xsl:text><xsl:value-of select=\"@end\"/>\n    <xsl:apply-templates select=\".\" mode=\"bibtex-separator\">\n        <xsl:with-param name=\"separator\" select=\"', '\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Always: authors first, no leading separator -->\n<!-- Others: leading separators                  -->\n<!-- Document order                              -->\n<!-- Final period when no following-siblings     -->\n\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/*\">\n    <xsl:message>PTX:BUG:      a child of \"biblio\" (<xsl:value-of select=\"local-name()\"/>) is not being processed.  Please report me so this can be fixed.</xsl:message>\n</xsl:template>\n\n<!-- Authors: no lead-in, names via the shared \"contributor-names\" -->\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/author\">\n    <xsl:apply-templates select=\".\" mode=\"contributor-names\"/>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n\n<!-- Editors and translators: a leading separator, the names, then a -->\n<!-- parenthetical role label (pluralized by the count of \"name\").   -->\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/editor\">\n    <xsl:text>, </xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"contributor-names\"/>\n    <xsl:choose>\n        <xsl:when test=\"count(name) &gt; 1\">\n            <xsl:text> (eds.)</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text> (ed.)</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/translator\">\n    <xsl:text>, </xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"contributor-names\"/>\n    <xsl:text> (trans.)</xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n\n<!-- Private mode: format the \"name\" list of a CSL contributor.      -->\n<!-- The first name is family-first, the rest given-first, with      -->\n<!-- \"and\"/\";\" separators; a \"literal\" name is printed verbatim.     -->\n<xsl:template match=\"*\" mode=\"contributor-names\">\n    <xsl:for-each select=\"name\">\n        <xsl:choose>\n            <!-- An organizational or otherwise literal name -->\n            <xsl:when test=\"literal\">\n                <xsl:apply-templates select=\"literal\"/>\n            </xsl:when>\n            <!-- First, name with family name first -->\n            <xsl:when test=\"not(preceding-sibling::name)\">\n                <xsl:apply-templates select=\"family\"/>\n                <xsl:text>, </xsl:text>\n                <xsl:apply-templates select=\"given\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:apply-templates select=\"given\"/>\n                <xsl:text> </xsl:text>\n                <xsl:apply-templates select=\"family\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n        <xsl:choose>\n            <!-- separators come before subsequent items -->\n            <xsl:when test=\"count(following-sibling::name) = 0\"/>\n            <!-- one more left, use \"and\" -->\n            <xsl:when test=\"count(following-sibling::name) = 1\">\n                <xsl:text> and </xsl:text>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>; </xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:for-each>\n</xsl:template>\n\n<!-- Title, in italics -->\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/title\">\n    <xsl:text>, </xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"italic\"/>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n\n<!-- Collection title -->\n<!-- Once had \"lq-character\" and \"rq-character\", but -->\n<!-- removed for consistency with other formats      -->\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/collection-title\">\n    <xsl:text>, </xsl:text>\n    <xsl:apply-templates/>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n\n<!-- Publisher -->\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/publisher\">\n    <xsl:text>, </xsl:text>\n    <xsl:apply-templates/>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n\n<!-- Publisher place-->\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/publisher-place\">\n    <xsl:text>, </xsl:text>\n    <xsl:apply-templates/>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n\n<!-- Container title (a journal, proceedings, or the book of a -->\n<!-- chapter); rendered plain, like a collection title         -->\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/container-title\">\n    <xsl:text>, </xsl:text>\n    <xsl:apply-templates/>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n\n<!-- Genre, a sub-type such as \"Ph.D. thesis\" -->\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/genre\">\n    <xsl:text>, </xsl:text>\n    <xsl:apply-templates/>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n\n<!-- Edition, with the word spelled out (so the abbreviation's -->\n<!-- period does not collide with a final period)             -->\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/edition\">\n    <xsl:text>, </xsl:text>\n    <xsl:apply-templates/>\n    <xsl:text> edition</xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n\n<!-- Volume in bold -->\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/volume\">\n    <xsl:text> </xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"bold\"/>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n\n<!-- Number, presumes it follows volume -->\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/number\">\n    <xsl:text> no. </xsl:text>\n    <xsl:apply-templates/>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n\n<!-- Date as a year, in parentheses -->\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/issued\">\n    <xsl:text> </xsl:text>\n    <xsl:text>(</xsl:text>\n    <xsl:value-of select=\"date/@year\"/>\n    <xsl:text>)</xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n\n<!-- Access date, for online material; month and day are padded to -->\n<!-- two digits, for an ISO 8601 (YYYY-MM-DD) appearance           -->\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/accessed\">\n    <xsl:text>, accessed </xsl:text>\n    <xsl:value-of select=\"date/@year\"/>\n    <xsl:if test=\"date/@month\">\n        <xsl:text>-</xsl:text>\n        <xsl:value-of select=\"format-number(date/@month, '00')\"/>\n    </xsl:if>\n    <xsl:if test=\"date/@day\">\n        <xsl:text>-</xsl:text>\n        <xsl:value-of select=\"format-number(date/@day, '00')\"/>\n    </xsl:if>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n\n<!-- Pages as a range             -->\n<!-- Differs from \"bibtex\" format -->\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/page\">\n    <xsl:text> </xsl:text>\n    <xsl:apply-templates/>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n\n<!-- URL (upper-case?) -->\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/URL\">\n    <xsl:text> </xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"monospace\"/>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n\n<!-- Issue, parenthesized, directly following the volume -->\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/issue\">\n    <xsl:text>(</xsl:text>\n    <xsl:apply-templates/>\n    <xsl:text>)</xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n\n<!-- First page, when no range is recorded -->\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/page-first\">\n    <xsl:text> </xsl:text>\n    <xsl:apply-templates/>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n\n<!-- Total page count, as for a book -->\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/number-of-pages\">\n    <xsl:text>, </xsl:text>\n    <xsl:apply-templates/>\n    <xsl:text> pages</xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n\n<!-- Identifiers: a DOI in monospace, an ISBN or ISSN labelled -->\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/DOI\">\n    <xsl:text>, doi:</xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"monospace\"/>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/ISBN\">\n    <xsl:text>, ISBN </xsl:text>\n    <xsl:apply-templates/>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n<xsl:template match=\"biblio[not(@type = 'raw') and not(@type = 'bibtex')]/ISSN\">\n    <xsl:text>, ISSN </xsl:text>\n    <xsl:apply-templates/>\n    <xsl:apply-templates select=\".\" mode=\"plain-biblio-period\"/>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"plain-biblio-period\">\n    <xsl:if test=\"not(following-sibling::*)\">\n        <xsl:text>.</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- ############ -->\n<!-- Conveniences -->\n<!-- ############ -->\n\n<!-- Conveniences, possibly overridden in format-specific conversions -->\n<!-- NB: we need to distinguish empty elements in some cases.  Since  -->\n<!-- pre-processing is likely to add some attributes, and perhaps an  -->\n<!-- element could have an opening and ending tag split across lines, -->\n<!-- we just presume the non-empty case is indicated by elements as   -->\n<!-- children.  Also, the schema should indicate that there are       -->\n<!-- extraneous authored elements, so the less-severe testing is not  -->\n<!-- a contract.                                                      -->\n<!-- TODO: kern, etc. into LaTeX, HTML versions -->\n<xsl:template match=\"webwork[not(* or @copy or @source)]\">\n    <xsl:text>WeBWorK</xsl:text>\n</xsl:template>\n\n<!-- ##############-->\n<!-- Prophylactics -->\n<!-- ############# -->\n\n<!-- We nullify certain elements here that should only be active -->\n<!-- in some formats, and templates there can override these     -->\n\n<xsl:template match=\"instruction\" />\n\n<!-- ################### -->\n<!-- Errors and Warnings -->\n<!-- ################### -->\n\n<!-- Sometimes we want a big warning as part of  -->\n<!-- every use of some conversion.  This is it.  -->\n<!-- Feed a linefeed in if you want line breaks. -->\n<!-- Designed for an 80 column terminal.         -->\n<xsl:template name=\"banner-warning\">\n    <xsl:param name=\"warning\" />\n    <xsl:message>********************************************************************************</xsl:message>\n    <xsl:call-template name=\"warning-line-by-line\">\n        <xsl:with-param name=\"warning\" select=\"$warning\" />\n    </xsl:call-template>\n    <xsl:message>********************************************************************************</xsl:message>\n</xsl:template>\n\n<xsl:template name=\"warning-line-by-line\">\n    <xsl:param name=\"warning\" />\n    <!-- the first line, which may be all of the text -->\n    <xsl:variable name=\"first-line\">\n        <xsl:choose>\n            <xsl:when test=\"contains($warning, '&#xa;')\">\n                <xsl:value-of select=\"substring-before($warning, '&#xa;')\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$warning\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:choose>\n        <!-- a message with no content is reported strangely  -->\n        <!-- by the processing library, a space displays well -->\n        <xsl:when test=\"$first-line = ''\">\n            <xsl:message><xsl:text> </xsl:text></xsl:message>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message><xsl:value-of select=\"$first-line\"/></xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n    <!-- and the lines after the first, if any -->\n    <xsl:if test=\"contains($warning, '&#xa;')\">\n        <xsl:call-template name=\"warning-line-by-line\">\n            <xsl:with-param name=\"warning\" select=\"substring-after($warning, '&#xa;')\"/>\n        </xsl:call-template>\n    </xsl:if>\n</xsl:template>\n\n<!-- Report the location of an element or attribute, for use after a   -->\n<!-- warning that does not itself contain identifying information.     -->\n<!-- Prints two lines: a structural path of element local-names from   -->\n<!-- the root, useful for diagnosing structural problems; then the     -->\n<!-- nearest @xml:id or \"title\" up the ancestor chain, useful for the  -->\n<!-- author to locate the issue in their source.                       -->\n<xsl:template match=\"*|@*\" mode=\"location-report\">\n    <!-- structural path: \"pretext/book/chapter/.../element\" -->\n    <!-- attributes display as a trailing \"@name\" step       -->\n    <xsl:message>\n        <xsl:text>             located at: </xsl:text>\n        <xsl:for-each select=\"ancestor::*\">\n            <xsl:value-of select=\"local-name(.)\"/>\n            <xsl:text>/</xsl:text>\n        </xsl:for-each>\n        <xsl:if test=\"not(self::*)\">\n            <xsl:text>@</xsl:text>\n        </xsl:if>\n        <xsl:value-of select=\"local-name(.)\"/>\n    </xsl:message>\n    <!-- nearest @xml:id or \"title\" for author orientation -->\n    <xsl:apply-templates select=\".\" mode=\"named-ancestor-report\"/>\n</xsl:template>\n\n<!-- Walk up the ancestor chain, looking for the first element with     -->\n<!-- @xml:id or \"title\", and report it.  Companion to \"location-report\" -->\n<!-- so the structural path is printed once while this walk continues.  -->\n<xsl:template match=\"*|@*\" mode=\"named-ancestor-report\">\n    <xsl:choose>\n        <xsl:when test=\"@xml:id or title\">\n            <!-- print information about location -->\n            <xsl:message>\n                <xsl:text>             located within: </xsl:text>\n                <xsl:if test=\"@xml:id\">\n                    <xsl:text>\"</xsl:text>\n                    <xsl:value-of select=\"@xml:id\" />\n                    <xsl:text>\" (xml:id)</xsl:text>\n                </xsl:if>\n                <xsl:if test=\"@xml:id and title\">\n                    <xsl:text>, </xsl:text>\n                </xsl:if>\n                <xsl:if test=\"title\">\n                    <xsl:text>\"</xsl:text>\n                    <xsl:value-of select=\"title\" />\n                    <xsl:text>\" (title)</xsl:text>\n                </xsl:if>\n            </xsl:message>\n        </xsl:when>\n        <xsl:when test=\"self::mathbook or self::pretext\">\n            <!-- at the document root, fail with no action.  Earlier  -->\n            <!-- this test used \"mathbook|pretext\", which matched any -->\n            <!-- ancestor that happened to *contain* a \"pretext/\" or  -->\n            <!-- \"mathbook/\" empty element (the project-name marker)  -->\n            <!-- and halted the walk prematurely.                     -->\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- pop up a level and try again -->\n            <xsl:apply-templates select=\"parent::*[1]\" mode=\"named-ancestor-report\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Debugging info -->\n<!-- @xml:base attribute of xinclude scheme -->\n<!-- @xml:id - self-explanatory             -->\n<!-- title - if there is one                -->\n<xsl:template match=\"*\" mode=\"debug-location\">\n    <xsl:if test=\"$b-debug\">\n        <xsl:message>\n            <xsl:text>PTX:DEBUG:   </xsl:text>\n            <xsl:text>f: </xsl:text>\n            <!-- On assembled source the version pass has stripped @xml:base,  -->\n            <!-- so this yields nothing; to restore the originating file URI,  -->\n            <!-- mint a @pi:source-uri there (with the other \"pi:\" provenance) -->\n            <!-- and consume it here.                                          -->\n            <xsl:choose>\n                <xsl:when test=\"@xml:base\">\n                    <xsl:value-of select=\"@xml:base\" />\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:text></xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n            <xsl:text>|e: </xsl:text>\n            <xsl:value-of select=\"local-name(.)\" />\n            <xsl:text>|i: </xsl:text>\n            <xsl:value-of select=\"@xml:id\" />\n            <xsl:text>|t: </xsl:text>\n            <xsl:apply-templates select=\".\" mode=\"title-simple\" />\n        </xsl:message>\n    </xsl:if>\n</xsl:template>\n\n<!-- ############### -->\n<!-- Global Warnings -->\n<!-- ############### -->\n\n<!-- Checks for errors that would be time-consuming -->\n<!-- if done repeatedly, so a pre-processing step   -->\n<!-- Calling context could be \"mathbook\" element    -->\n<!-- NB: this is called early by any author-facing  -->\n<!-- \"mainline\" conversion (and not by some         -->\n<!-- utilities) where the select attribute is the   -->\n<!-- \"$original\" tree defined as the author's       -->\n<!-- actual source file.                            -->\n<xsl:template match=\"mathbook|pretext\" mode=\"generic-warnings\">\n    <xsl:apply-templates select=\".\" mode=\"literate-programming-warning\" />\n    <xsl:apply-templates select=\".\" mode=\"xinclude-warnings\" />\n    <xsl:apply-templates select=\".\" mode=\"identifier-warning\"/>\n    <xsl:apply-templates select=\".\" mode=\"text-element-warning\" />\n    <xsl:apply-templates select=\".\" mode=\"subdivision-structure-warning\" />\n    <xsl:apply-templates select=\".\" mode=\"table-paragraph-cells-warning\" />\n</xsl:template>\n\n<!-- Literate Programming support is half-baked, 2017-07-21 -->\n<xsl:template match=\"mathbook|pretext\" mode=\"literate-programming-warning\">\n    <xsl:if test=\".//fragment\">\n        <xsl:call-template name=\"banner-warning\">\n            <xsl:with-param name=\"warning\">\n                <xsl:text>  Literate Programming support is incomplete&#xa;</xsl:text>\n                <xsl:text>&#xa;</xsl:text>\n                <xsl:text>    1.  Code generation is functional, but does not respect indentation&#xa;</xsl:text>\n                <xsl:text>    2.  LaTeX generation is functional, could be improved, 2020-11-11&#xa;</xsl:text>\n                <xsl:text>    3.  HTML generation is functional, could be improved, 2020-11-11&#xa;</xsl:text>\n            </xsl:with-param>\n        </xsl:call-template>\n    </xsl:if>\n</xsl:template>\n\n<!-- Using the modular  xinclude  scheme at the top level,      -->\n<!-- and forgetting the command-line switch is a common mistake -->\n<!-- The following is not perfect, but reasonably effective     -->\n<xsl:template match=\"mathbook|pretext\" mode=\"xinclude-warnings\">\n    <xsl:if test=\"book and not(book/chapter or book/part/chapter)\">\n        <xsl:message>\n            <xsl:text>PTX:WARNING:    </xsl:text>\n            <xsl:text>Your &lt;book&gt; does not have any chapters.  Maybe you forgot the '--xinclude' switch on your 'xsltproc' command line?</xsl:text>\n        </xsl:message>\n    </xsl:if>\n    <xsl:if test=\"article and not(article/p) and not(article/section) and not(article/worksheet) and not(article/handout)\">\n        <xsl:message>\n            <xsl:text>PTX:WARNING:    </xsl:text>\n            <xsl:text>Your &lt;article&gt; does not have any sections, worksheets, or handouts, nor any top-level paragraphs.  Maybe you forgot the '--xinclude' switch on your 'xsltproc' command line?</xsl:text>\n        </xsl:message>\n    </xsl:if>\n</xsl:template>\n\n<!-- We warn about a bad @xml:id or @label.  Both can become an element's -->\n<!-- HTML @id, so both are checked here.  Allowed characters: 26 Latin    -->\n<!-- letters (upper and lower case), 10 digits, hyphen/dash, underscore.  -->\n<!-- TODO: Added 2016-10-29, make into a fatal error later                -->\n<!-- Unique UI id's added 2017-09-25 as fatal error                       -->\n<xsl:template match=\"mathbook|pretext\" mode=\"identifier-warning\">\n    <xsl:variable name=\"identifier-characters\" select=\"concat('-_', &SIMPLECHAR;)\" />\n    <!-- Fixed HTML id values that PreTeXt's CSS/JS require; an authored  -->\n    <!-- identifier equal to one of these would collide and break the UI. -->\n    <!-- Audited against the HTML output, 2026-06-04.                     -->\n    <xsl:variable name=\"reserved-html-ids\">\n        <xsl:text>mainmatter logo-link latex-macros </xsl:text>\n        <xsl:text>papersize-select highlight-workspace-checkbox </xsl:text>\n        <xsl:text>hide-hint-checkbox hide-answer-checkbox hide-solution-checkbox </xsl:text>\n        <xsl:text>print-first-page-header-checkbox print-running-header-checkbox </xsl:text>\n        <xsl:text>print-first-page-footer-checkbox print-running-footer-checkbox </xsl:text>\n        <!-- Runestone Services ids, banned always: these components can appear -->\n        <!-- even on a non-hosted build.  (When actually hosted on Runestone the -->\n        <!-- HTML ids are mangled, so the collision risk there is small.)        -->\n        <xsl:text>inst_peer_link ip_dropdown_link subchapterprogress </xsl:text>\n        <xsl:text>scprogresscontainer scprogressposs scprogresstotal</xsl:text>\n    </xsl:variable>\n    <!-- tokenize the reserved-id list once, for the membership test in the loop -->\n    <xsl:variable name=\"reserved-html-id-tokens\" select=\"str:tokenize($reserved-html-ids)\" />\n    <!-- Both @xml:id and @label are checked: each can become the HTML @id, and a   -->\n    <!-- reserved id must not be duplicated no matter which attribute supplies it.  -->\n    <!-- Mildly over-aggressive: when an element has a good @label, that becomes    -->\n    <!-- the HTML @id while the @xml:id is only an internal reference, never in the -->\n    <!-- output (the @label-precedence backward-compatibility enacted later, in     -->\n    <!-- assembly), so a reserved @xml:id shadowed by a @label could not really     -->\n    <!-- collide - yet we flag it anyway.                                           -->\n    <xsl:for-each select=\".//@xml:id | .//@label\">\n        <!-- the limited character set -->\n        <xsl:if test=\"not(translate(., $identifier-characters, '') = '')\">\n            <xsl:message>\n                <xsl:text>PTX:ERROR:      </xsl:text>\n                <xsl:text>The @</xsl:text>\n                <xsl:value-of select=\"name()\" />\n                <xsl:text> \"</xsl:text>\n                <xsl:value-of select=\".\" />\n                <xsl:text>\" is invalid.  Use only the 26 Latin letters (7-bit ASCII, no accents), numbers, hyphens and underscores.</xsl:text>\n            </xsl:message>\n        </xsl:if>\n        <!-- a reserved UI id: \"=\" against the token node-set is true if this -->\n        <!-- identifier equals at least one token of the list                 -->\n        <xsl:if test=\". = $reserved-html-id-tokens\">\n            <xsl:message terminate=\"yes\">\n                <xsl:text>PTX:FATAL:   </xsl:text>\n                <xsl:text>The @</xsl:text>\n                <xsl:value-of select=\"name()\" />\n                <xsl:text> \"</xsl:text>\n                <xsl:value-of select=\".\" />\n                <xsl:text>\" is invalid since it will conflict with a unique HTML id in use by the user interface.  Please use a different string.  Quitting...</xsl:text>\n            </xsl:message>\n        </xsl:if>\n        <!-- reserve all ptx-* ids for internal use -->\n        <xsl:if test=\"starts-with(., 'ptx-')\">\n            <xsl:message terminate=\"yes\">\n                <xsl:text>PTX:FATAL:   </xsl:text>\n                <xsl:text>The @</xsl:text>\n                <xsl:value-of select=\"name()\" />\n                <xsl:text> \"</xsl:text>\n                <xsl:value-of select=\".\" />\n                <xsl:text>\" is invalid because PreTeXt reserves all ptx-* ids for internal use.  Quitting...</xsl:text>\n            </xsl:message>\n        </xsl:if>\n        <!-- index.html is built automatically, so preclude a clash -->\n        <!-- Not terminating until 2019-07-10 deprecation expires   -->\n        <xsl:if test=\". = 'index'\">\n            <xsl:message terminate=\"no\">\n                <xsl:text>PTX:ERROR:   </xsl:text>\n                <xsl:text>The @</xsl:text>\n                <xsl:value-of select=\"name()\" />\n                <xsl:text> \"</xsl:text>\n                <xsl:value-of select=\".\" />\n                <xsl:text>\" is invalid since it will conflict with the construction of an automatic HTML \"index.html\" page.  Use some alternative for the real index - sorry.</xsl:text>\n            </xsl:message>\n        </xsl:if>\n    </xsl:for-each>\n</xsl:template>\n\n\n<!-- Elements should never happen like this, so we     -->\n<!-- can match on them and offer pretty good advice    -->\n<!-- Last: since both summary and specifics.  We       -->\n<!-- can't catch with a template, since we don't apply -->\n<!-- templates in the places where elements are banned -->\n<!-- c, cline; unstructured cd, pre                    -->\n<!-- prompt, input, output for sage, console, program  -->\n<!-- NB: cline/area is used in Clickable Area problems -->\n<xsl:template match=\"mathbook|pretext\" mode=\"text-element-warning\">\n    <xsl:variable name=\"bad-elements\" select=\".//c/*|.//cline/*[not(self::area)]|.//cd[not(cline)]/*|.//pre[not(cline)]/*|.//prompt[not(parent::checkpoint)]/*|.//input/*|.//output/*\" />\n    <xsl:if test=\"$bad-elements\">\n        <xsl:message>\n            <xsl:text>PTX:WARNING: </xsl:text>\n            <xsl:text>There are apparent XML elements in locations that should be text only (</xsl:text>\n            <xsl:value-of select=\"count($bad-elements)\" />\n            <xsl:text> times).</xsl:text>\n        </xsl:message>\n    </xsl:if>\n    <xsl:for-each select=\"$bad-elements\">\n        <xsl:message>\n            <xsl:text>PTX:WARNING: </xsl:text>\n            <xsl:text>There is an apparent XML element (&lt;</xsl:text>\n            <xsl:value-of select=\"local-name(.)\" />\n            <xsl:text>&gt;) inside an &lt;</xsl:text>\n            <xsl:value-of select=\"local-name(parent::*)\" />\n            <xsl:text>&gt; element, which should only contain text.  Using an escaped \"less than\" ('&amp;lt;') might be the solution, or using a CDATA section.</xsl:text>\n        </xsl:message>\n        <xsl:apply-templates select=\".\" mode=\"location-report\" />\n    </xsl:for-each>\n</xsl:template>\n\n<!-- New authors often begin a subdivision with some material,     -->\n<!-- then begin a run of further subdivisions.  This preliminary   -->\n<!-- material belongs in an introduction (or is for a conclusion). -->\n<!-- This test is not exhaustive, but will catch most cases.       -->\n<xsl:template match=\"mathbook|pretext\" mode=\"subdivision-structure-warning\">\n    <xsl:for-each select=\"./book/chapter\">\n        <xsl:if test=\"p and section\">\n            <xsl:message>\n                <xsl:text>PTX:WARNING: </xsl:text>\n                <xsl:text>In a chapter containing sections, any content that is not inside a section needs to be inside an &lt;introduction&gt; and/or  &lt;conclusion&gt;.</xsl:text>\n            </xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\" />\n        </xsl:if>\n    </xsl:for-each>\n    <xsl:for-each select=\"./article/section|./book/chapter/section\">\n        <xsl:if test=\"p and subsection\">\n            <xsl:message>\n                <xsl:text>PTX:WARNING: </xsl:text>\n                <xsl:text>In a section containing subsections, any content that is not inside a subsection needs to be inside an &lt;introduction&gt; and/or  &lt;conclusion&gt;.</xsl:text>\n            </xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\" />\n        </xsl:if>\n    </xsl:for-each>\n    <xsl:for-each select=\"./article/section/subsection|./book/chapter/section/subsection\">\n        <xsl:if test=\"p and subsubsection\">\n            <xsl:message>\n                <xsl:text>PTX:WARNING: </xsl:text>\n                <xsl:text>In a subsection containing subsubsections, any content that is not inside a subsubsection needs to be inside an &lt;introduction&gt; and/or  &lt;conclusion&gt;.</xsl:text>\n            </xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\" />\n        </xsl:if>\n    </xsl:for-each>\n</xsl:template>\n\n<xsl:template match=\"mathbook|pretext\" mode=\"table-paragraph-cells-warning\">\n    <xsl:for-each select=\".//tabular\">\n        <xsl:if test=\"row/cell/p and not(col/@width)\">\n            <xsl:message>PTX:WARNING:   a &lt;tabular&gt; has at least one paragraph (&lt;p&gt;) inside a &lt;cell&gt;, yet there are no &lt;col&gt; elements with a @width attribute.  Default widths will be supplied.</xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\" />\n        </xsl:if>\n    </xsl:for-each>\n</xsl:template>\n\n\n\n<!-- ############ -->\n<!-- Deprecations -->\n<!-- ############ -->\n\n<!-- Locating all instances of a deprecated element looks  -->\n<!-- expensive. (Turns out it might be less than 1% of the -->\n<!-- time to build a full book.) But we have a scheme to   -->\n<!-- only look back a limited time period (four years),    -->\n<!-- controlled by a string parameter (not a publisher     -->\n<!-- switch).  The default is to perform a full search     -->\n<!-- of all such deprecations.                             -->\n<xsl:param name=\"author.deprecations.all\" select=\"''\" />\n<xsl:variable name=\"deprecation-max-age\">\n    <xsl:choose>\n        <xsl:when test=\"($author.deprecations.all = 'yes') or ($author.deprecations.all = '')\">\n            <xsl:text>P100Y</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$author.deprecations.all = 'no'\">\n            <xsl:text>P4Y</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>P100Y</xsl:text>\n            <xsl:message>PTX:FALLBACK:   \"author.deprecations.all\" should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$author.deprecations.all\"/>\", using the default value of \"yes\"</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- Generic deprecation message for uniformity    -->\n<!-- \"occurrences\" is a quote-protected expression -->\n<!-- that evaluates to node-set of \"problem\" nodes -->\n<!-- A message string like \"'foo'\" cannot contain  -->\n<!-- a single quote, even if entered as &apos;.    -->\n<!-- If despearate, concatentate with $apos.       -->\n<!-- A &#xa; can be used if necessary, but only    -->\n<!-- rarely do we bother.                          -->\n<!-- NB: this is called early by any author-facing -->\n<!-- \"mainline\" conversion (and not by some        -->\n<!-- utilities) where the select attribute is the  -->\n<!-- \"$original\" tree defined as the author's      -->\n<!-- actual source file.                           -->\n<xsl:template name=\"deprecation-message\">\n    <xsl:param name=\"occurrences\" />\n    <xsl:param name=\"date-string\" />\n    <xsl:param name=\"message\" />\n    <!-- \"max-reports\" caps the per-occurrence location reports.    -->\n    <!-- An empty string (the default) imposes no cap; \"0\" silences -->\n    <!-- the per-location reports entirely (the count line still    -->\n    <!-- appears); a positive integer caps the number of reports.   -->\n    <xsl:param name=\"max-reports\" select=\"''\"/>\n\n    <!-- These apparent re-definitions are local to this template -->\n    <!-- Reasons are historical, so to be a convenience           -->\n    <xsl:variable name=\"docinfo\" select=\"./docinfo\"/>\n    <xsl:variable name=\"document-root\" select=\"./*[not(self::docinfo)]\"/>\n\n    <xsl:variable name=\"expire-date\" select=\"date:seconds(date:add($date-string, $deprecation-max-age))\"/>\n    <xsl:variable name=\"today\" select=\"date:seconds(date:date-time())\"/>\n\n    <!-- Document-wide searches for deprecated constructions are expensive. -->\n    <!-- So we provide for automatic filtering by age.  (We limit this to   -->\n    <!-- \"current\" versus \"all\" as an author/publisher choice.)  So this    -->\n    <!-- templates receives a *string* version of an APath expression,      -->\n    <!-- not the actual *node-set*.  Then the \"dyn:evaluate()\" function     -->\n    <!-- constructs the node-set, but after it survives the date filter.    -->\n    <xsl:if test=\"$expire-date > $today\">\n        <xsl:variable name=\"occurrences-rtf\" select=\"dyn:evaluate($occurrences)\" />\n        <xsl:if test=\"$occurrences-rtf\">\n            <xsl:message>\n                <xsl:text>PTX:DEPRECATE: (</xsl:text>\n                <xsl:value-of select=\"$date-string\" />\n                <xsl:text>) </xsl:text>\n                <xsl:value-of select=\"$message\" />\n                <xsl:text> (</xsl:text>\n                <xsl:value-of select=\"count($occurrences-rtf)\" />\n                <xsl:text> time</xsl:text>\n                <xsl:if test=\"count($occurrences-rtf) > 1\">\n                    <xsl:text>s</xsl:text>\n                </xsl:if>\n                <xsl:text>)</xsl:text>\n                <!-- once verbosity is implemented -->\n                <!-- <xsl:text>, set log.level to see more details</xsl:text> -->\n            </xsl:message>\n            <xsl:for-each select=\"$occurrences-rtf\">\n                <xsl:if test=\"($max-reports = '') or (position() &lt;= number($max-reports))\">\n                    <xsl:apply-templates select=\".\" mode=\"location-report\" />\n                </xsl:if>\n            </xsl:for-each>\n            <xsl:message>\n                <xsl:text>--------------</xsl:text>\n            </xsl:message>\n        </xsl:if>\n    </xsl:if>\n</xsl:template>\n\n<!-- On the suspicion that the next template frequently \"scans\" the entire   -->\n<!-- document tree, we attempted to add a developer-only \"debug\" switch      -->\n<!-- that would bypass the tests here, and in \"generic-warnings\" and         -->\n<!-- \"parameter-deprecation-warnings\". For the sample article the speed-up   -->\n<!-- was about 1%, and for AATA the speed-up was apparently less.  Which was -->\n<!-- all not worth the danger that authors and publishers could \"turn off\"   -->\n<!-- deprecation warnings. (2023-05-11)                                      -->\n<xsl:template match=\"mathbook|pretext\" mode=\"element-deprecation-warnings\">\n\n    <!-- Element deprecation checks can be limited by time   -->\n    <!-- and we want to issue an informational warning about -->\n    <!-- the (possibly limited) time coverage:               -->\n    <!--   * once only, per output build                     -->\n    <!--   * only if a stylesheet actually does the checks   -->\n    <!-- So this is the spot, right before launcing into     -->\n    <!-- the actual checks.                                  -->\n    <xsl:choose>\n        <xsl:when test=\"$deprecation-max-age = 'P100Y'\">\n            <xsl:message>PTX:INFO:   checking all deprecated elements.</xsl:message>\n        </xsl:when>\n        <xsl:when test=\"$deprecation-max-age = 'P4Y'\">\n            <xsl:message>PTX:INFO:   checking ONLY the last FOUR YEARS of element deprecations.&#xa;Rerun with the string parameter \"author.deprecations.all\" set to \"yes\" to check your source against all deprecations.</xsl:message>\n        </xsl:when>\n        <xsl:otherwise/>\n    </xsl:choose>\n\n    <!-- Older deprecations at the top of this list, -->\n    <!-- so author will see new at the tail end.     -->\n    <!-- NB: XPath expressions to select \"problem\"   -->\n    <!-- nodes must be given as strings, to allow    -->\n    <!-- for delayed evaluation, only if the warning -->\n    <!-- survives a date filter.                     -->\n    <!-- Comments without implementations have moved -->\n    <!-- to validation rules after residing here for -->\n    <!-- at least 16 months (one year plus grace)    -->\n    <!--  -->\n    <!-- 2014-05-04  @filebase has been replaced in function by @xml:id -->\n    <!-- 2014-06-25  xref once had cite as a variant -->\n    <!-- 2015-01-28  once both circum and circumflex existed, circumflex won -->\n    <!--  -->\n    <!-- These have been outright removed since they simply became confusing -->\n    <!-- 2017-07-05  top-level items that should have captions, but don't -->\n    <!-- 2017-07-05  sidebyside items that do not have captions, so ineffective -->\n    <!--  -->\n    <!-- 2015-02-08  naked tikz, asymptote, sageplot are no longer accomodated -->\n    <!-- 2015-02-20  tikz element is entirely abandoned -->\n    <!-- 2017-12-22  latex-image-code element is entirely abandoned -->\n    <!--  -->\n    <!-- Active deprecations follow -->\n    <!--  -->\n    <!-- 2015-03-13  paragraph is renamed more accurately to paragraphs           -->\n    <!-- 2017-07-16  removed all backwards compatibility and added empty template -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//paragraph&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2015-03-13'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;paragraph&quot; element is deprecated and any contained content will silently not appear, replaced by functional equivalent &quot;paragraphs&quot;'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2015-03-17  various indicators of table rearrangement -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//tgroup&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2015-03-17'\" />\n        <xsl:with-param name=\"message\" select=\"'tables are done quite differently, the &quot;tgroup&quot; element is indicative'\" />\n    </xsl:call-template>\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//tgroup/thead/row/entry|$document-root//tgroup/tbody/row/entry&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2015-03-17'\" />\n            <xsl:with-param name=\"message\" select=\"'tables are done quite differently, the &quot;entry&quot; element should be replaced by the &quot;cell&quot; element'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2015-12-12  empty labels on an ordered list was a bad idea -->\n     <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//ol[@label='']&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2015-12-12'\" />\n        <xsl:with-param name=\"message\" select=\"'an ordered list (&lt;ol&gt;) may not have empty labels, and numbering will be unpredictable.  Switch to an unordered list  (&lt;ul&gt;)'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2016-04-07  'plural' option for @autoname discarded -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//xref[@autoname='plural']&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2016-04-07'\" />\n        <xsl:with-param name=\"message\" select=\"'a &lt;xref&gt; element may not have an @autoname attribute set to plural.  There is no replacement, perhaps use content in the &lt;xref&gt;.'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2016-05-23  Require parts of a letter to be structured (could be relaxed) -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//letter/frontmatter/from[not(line)] | $document-root//letter/frontmatter/to[not(line)] | $document-root//letter/backmatter/signature[not(line)]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2016-05-23'\" />\n        <xsl:with-param name=\"message\" select=\"'&lt;to&gt;, &lt;from&gt;, and &lt;signature&gt; of a letter must be structured as a sequence of &lt;line&gt;'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2016-05-23  line breaks are not XML-ish, some places allow \"line\" -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//br&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2016-05-23'\" />\n        <xsl:with-param name=\"message\" select=\"'&lt;br&gt; can no longer be used to create multiline output; you may use &lt;line&gt; elements in select situations'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2016-07-31  ban @height attribute, except within webwork problems -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//image[@height and not(ancestor::*[self::webwork])]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2016-07-31'\" />\n        <xsl:with-param name=\"message\" select=\"'@height attribute on &lt;image&gt; is no longer effective and will be ignored, except within a WeBWorK exercise'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2016-07-31  widths of images must be expressed as percentages -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//image[@width and not(contains(@width, '%'))]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2016-07-31'\" />\n        <xsl:with-param name=\"message\" select=\"'@width attribute on &lt;image&gt; must be expressed as a percentage'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2017-02-05  hyphen-minus replaces hyphen; 2018-12-01 use keyboard hyphen -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//hyphen&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2017-02-05'\" />\n        <xsl:with-param name=\"message\" select=\"'use the keyboard hyphen character as a direct replacement for &lt;hyphen/&gt;'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2017-07-05  a sidebyside cannot have a caption -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//sidebyside[caption]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2017-07-05'\" />\n        <xsl:with-param name=\"message\" select=\"'a &lt;sidebyside&gt; cannot have a &lt;caption&gt;.  Place the &lt;sidebyside&gt; inside a &lt;figure&gt;, employing the &lt;caption&gt;, which will be the functional equivalent.'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2017-07-14  index specification and production reworked -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//index-part&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2017-07-14'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;index-part&quot; element is deprecated, replaced by functional equivalent &quot;index&quot;'\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//index[not(main) and not(index-list)]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2017-07-14'\" />\n        <xsl:with-param name=\"message\" select=\"'a &quot;index&quot; element is deprecated, replaced by functional equivalent &quot;idx&quot;'\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//index[main]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2017-07-14'\" />\n        <xsl:with-param name=\"message\" select=\"'a &quot;index&quot; element with &quot;main&quot; and &quot;sub&quot; headings is deprecated, replaced by functional equivalent &quot;idx&quot; with &quot;h&quot; headings'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2017-07-14  cosmetic replacement of WW image/@tex_size by image/@tex-size -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//@tex_size&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2017-07-18'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;tex_size&quot; attribute is deprecated, replaced by functional equivalent &quot;tex-size&quot;'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2017-07-25  replacement of three xref/@autoname attributes by @text -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//xref[@autoname='no']&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2017-07-25'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;xref/autoname&quot; attribute is deprecated, replace  autoname=&quot;no&quot;  by functional equivalent  text=&quot;global&quot;'\" />\n    </xsl:call-template>\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//xref[@autoname='yes']&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2017-07-25'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;xref/autoname&quot; attribute is deprecated, replace  autoname=&quot;yes&quot;  by functional equivalent  text=&quot;type-global&quot;'\" />\n    </xsl:call-template>\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//xref[@autoname='title']&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2017-07-25'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;xref/autoname&quot; attribute is deprecated, replace  autoname=&quot;title&quot;  by functional equivalent  text=&quot;title&quot;'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2017-08-04  repurpose task block for division of project-like -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//task[parent::chapter or parent::appendix or parent::section or parent::subsection or parent::subsubsection or parent::paragraphs or parent::introduction or parent::conclusion]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2017-08-04'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;task&quot; element is no longer used as a child of a top-level division, but is instead being used to divide the other &quot;project-like&quot; elements.  It can be replaced by a functional equivalent: &quot;project&quot;, &quot;activity&quot;, &quot;exploration&quot;, or &quot;investigation&quot;'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2017-09-10  deprecate title-less paragraphs, outside of sidebyside -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//paragraphs[not(title) and not(parent::sidebyside)]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2017-09-10'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;paragraphs&quot; element (outside of a &quot;sidebyside&quot;) now requires a &quot;title&quot;'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2017-11-09  WeBWorK images now with widths as percentages, only on an enclosing sidebyside -->\n    <!-- 2020-11-04  One-panel sidebysides not necessary, so now only warn about old attributes     -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//webwork//image[@height or @tex-size]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2017-11-09'\" />\n        <xsl:with-param name=\"message\" select=\"'an &quot;image&quot; within a &quot;webwork&quot; now has its size given by just a &quot;width&quot; attribute expressed as a percentage, including the percent sign (so in particular do not use &quot;height&quot; or &quot;tex-size&quot;)'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2017-11-09  Assemblages have been rationalized, warn about captioned items -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//assemblage//*[caption]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2017-11-09'\" />\n        <xsl:with-param name=\"message\" select=\"'an &quot;assemblage&quot; should not contain any items with a &quot;caption&quot;.  You can instead place the content in a bare &quot;sidebyside&quot;'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2017-12-07  \"c\" content totally escaped for LaTeX -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//c/@latexsep|$document-root//cd/@latexsep&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2017-12-07'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;@latexsep&quot; attribute on the &quot;c&quot; and &quot;cd&quot; elements is no longer necessary.  It is being ignored, and can be removed'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2018-02-04  geogebra-applet gone -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//geogebra-applet&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2018-02-04'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;geogebra-applet&quot; element has been removed, investigate newer &quot;interactive&quot; element'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2018-02-05  booktitle becomes pubtitle -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//booktitle&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2018-02-05'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;booktitle&quot; element has been replaced by the functionally equivalent &quot;pubtitle&quot;'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2018-04-06  jsxgraph absorbed into interactive -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//jsxgraph&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2018-04-06'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;jsxgraph&quot; element has been deprecated, but remains functional, rework with the &quot;interactive&quot; element'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2018-04-06  jsxgraph no longer a panel of a sidebyside -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//sidebyside/jsxgraph&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2018-04-06'\" />\n        <xsl:with-param name=\"message\" select=\"'a &quot;jsxgraph&quot; can no longer appear within a &quot;sidebyside&quot;, rework with the &quot;interactive&quot; element; as of 2026-07-22 the &quot;jsxgraph&quot; will be silently ignored'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2018-05-02  paragraphs purely as a lightweight division -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//sidebyside/paragraphs&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2018-04-06'\" />\n        <xsl:with-param name=\"message\" select=\"'a &quot;paragraphs&quot; can no longer appear within a &quot;sidebyside&quot;, replace with a &quot;stack&quot; containing multiple elements, such as &quot;p&quot;; as of 2026-07-22 the &quot;paragraphs&quot; and its content will be silently ignored'\" />\n    </xsl:call-template>\n    <!-- 2018-05-18  WeBWorK refactor no longer needs setup/var elements for static representations-->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//webwork/setup/var&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2018-05-18'\" />\n        <xsl:with-param name=\"message\" select=\"'&quot;var&quot; elements in a &quot;webwork/setup&quot; no longer do anything; you may delete them from source'\" />\n    </xsl:call-template>\n    <!-- 2018-07-04  \"solution-list\" generator element replaced by \"solutions\" division -->\n    <!-- 2020-08-31  element, controlling switches, supporting templates, removed/deactivated -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//solution-list&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2020-08-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;solution-list&quot; element has been removed (deprecated since 2018-07-04), please switch to using the improved &quot;solutions&quot; division in your back matter (and elsewhere)'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2018-09-26  appendix subdivision confusion resolved -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$root/article/backmatter/appendix/section&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2018-09-26'\" />\n        <xsl:with-param name=\"message\" select=\"'the first division of an &quot;appendix&quot; of an &quot;article&quot; should be a &quot;subsection&quot;'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2018-12-30  circa shortened to ca -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//circa&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2018-12-30'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;circa&quot; element has been replaced by the functionally equivalent &quot;ca&quot;'\" />\n    </xsl:call-template>\n    <!--                                                     -->\n    <!-- LaTeX's 10 reserved characters: # $ % ^ & _ { } ~ \\ -->\n    <!--                                                     -->\n    <!--  -->\n    <!-- 2019-02-06  hash gone -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//hash&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-06'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;hash&quot; element is no longer necessary, simply replace with a bare &quot;#&quot; character'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-06  dollar gone -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//dollar&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-06'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;dollar&quot; element is no longer necessary, simply replace with a bare &quot;$&quot; character'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-06  percent gone -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//percent&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-06'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;percent&quot; element is no longer necessary, simply replace with a bare &quot;%&quot; character'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-06  circumflex gone -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//circumflex&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-06'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;circumflex&quot; element is no longer necessary, simply replace with a bare &quot;^&quot; character'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-06  ampersand gone -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//ampersand&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-06'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;ampersand&quot; element is no longer necessary, simply replace with a bare &quot;&amp;&quot; character (properly escaped, i.e. &quot;&amp;amp;&quot;)'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-06  underscore gone -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//underscore&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-06'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;underscore&quot; element is no longer necessary, simply replace with a bare &quot;_&quot; character'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-06  lbrace gone -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//lbrace&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-06'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;lbrace&quot; element is no longer necessary, simply replace with a bare &quot;{&quot; character'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-06  rbrace gone -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//rbrace&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-06'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;rbrace&quot; element is no longer necessary, simply replace with a bare &quot;}&quot; character'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-06  tilde gone -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//tilde&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-06'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;tilde&quot; element is no longer necessary, simply replace with a bare &quot;~&quot; character'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-06  backslash gone -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//backslash&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-06'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;backslash&quot; element is no longer necessary, simply replace with a bare &quot;\\&quot; character'\"/>\n    </xsl:call-template>\n    <!--                           -->\n    <!-- Nine unnecessary elements -->\n    <!--                           -->\n    <!--  -->\n    <!-- 2019-02-06  less gone -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//less&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-06'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;less&quot; element is no longer necessary, simply replace with a bare &quot;&lt;&quot; character (properly escaped, i.e. &quot;&amp;lt;&quot;)'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-06  greater gone -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//greater&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-06'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;greater&quot; element is no longer necessary, simply replace with a bare &quot;&gt;&quot; character (possibly escaped, i.e. &quot;&amp;gt;&quot;)'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-06  lbracket gone -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//lbracket&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-06'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;lbracket&quot; element is no longer necessary, simply replace with a bare &quot;[&quot; character'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-06  rbracket gone -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//rbracket&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-06'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;rbracket&quot; element is no longer necessary, simply replace with a bare &quot;]&quot; character'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-06  asterisk gone -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//asterisk&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-06'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;asterisk&quot; element is no longer necessary, simply replace with a bare &quot;*&quot; character'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-06  slash gone -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//slash&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-06'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;slash&quot; element is no longer necessary, simply replace with a bare &quot;/&quot; character'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-06  backtick gone -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//backtick&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-06'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;backtick&quot; element is no longer necessary, simply replace with a bare &quot;`&quot; character'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-06  braces gone -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//braces&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-06'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;braces&quot; element is no longer necessary, simply replace with bare &quot;{&quot; and &quot;}&quot; characters'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-06  brackets gone -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//brackets&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-06'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;brackets&quot; element is no longer necessary, simply replace with bare &quot;[&quot; and &quot;]&quot; characters'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-20  \"todo\" items now in comments -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//todo&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-20'\" />\n        <xsl:with-param name=\"message\" select=\"'a &quot;todo&quot; element is no longer effective.  Replace with an XML comment whose first four non-whitespace characters spell &quot;todo&quot; (with no spaces)'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-23  \"rename/@lang\" replaced by (optional) rename/@xml:lang -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo//rename[@lang]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-20'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;@lang&quot; attribute of &quot;rename&quot; has been replaced by &quot;@xml:lang&quot;, and is now optional if your document only uses one language'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-04-02  \"mathbook\" replaced by \"pretext\" -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;/mathbook&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-04-02'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;mathbook&quot; top-level element has been replaced by the functionally equivalent &quot;pretext&quot;'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-04-14  analytics ID are now a publisher option -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/analytics&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-04-14'\" />\n        <xsl:with-param name=\"message\" select=\"'site-specific ID for HTML analytics services (Statcounter, Google) provided within &quot;docinfo/analytics&quot; are now options supplied by publishers as command-line options.  See the Publishers Guide for specifics.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-04-14  Google search ID is now a publisher option -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/search&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-04-14'\" />\n        <xsl:with-param name=\"message\" select=\"'site-specific ID for HTML search services (Google) is no longer provided within &quot;docinfo/search&quot;.  Please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2026-06-07  distinct block numbering moved to the publisher file -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/numbering/figures | $docinfo/numbering/exercises&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2026-06-07'\" />\n        <xsl:with-param name=\"message\" select=\"'distinct numbering of figure-like and inline exercise blocks has been replaced by the &quot;numbering/figures&quot; and &quot;numbering/exercises&quot; entries in the publisher file, and the &quot;docinfo&quot; form is now ignored.  Please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2017-08-25  once deprecated named lists to be captioned lists -->\n    <!-- 2019-06-28  deprecated captioned lists to be titled lists     -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//list[caption]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2017-06-28'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;list&quot; element requires a &quot;title&quot;, an existing &quot;caption&quot; is being ignored'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!--  -->\n    <!-- 2019-06-28  deprecated captioned tables to be titled tables  -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//table[caption]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-06-28'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;table&quot; element requires a &quot;title&quot;, an existing &quot;caption&quot; is being ignored'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-07-10  @xml:id = 'index' deprecated in favor of publisher's @ref  -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//*[@xml:id = 'index']&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-07-10'\" />\n        <xsl:with-param name=\"message\" select=\"'an element should no longer have an @xml:id equal to &quot;index&quot; as a way to create an HTML index.html page.  See the Publishers Guides chapter on the HTML conversion for instructions.'\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-11-28  deprecated docinfo analytics in favor of publisher's file  -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/analytics&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2019-11-28'\" />\n        <xsl:with-param name=\"message\" select=\"'use of the docinfo/analytics element has been deprecated.  Existing elements are being respected, but please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.&#xa;  * For StatCounter this is a cosmetic change.&#xa;  * Google Classic has been deprecated by Google and will not be supported.&#xa;  * Google Universal has been replaced, your ID may continue to work.&#xa;  * Google Global Site Tag is fully supported, try your Universal ID.&#xa;'\" />\n    </xsl:call-template>\n\n    <!-- 2020-03-13  deprecated setup element in a webwork -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//webwork/setup&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2020-03-13'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;setup&quot; element in a &quot;webwork&quot; is no longer necessary, simply use &quot;pg-code&quot;'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2020-11-22  deprecate HTML base URL in docinfo -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/html/baseurl/@href&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2020-11-22'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;baseurl/@href&quot; element in the &quot;docinfo&quot; has been replaced and is now specified in the publisher file with &quot;html/baseurl/@href&quot;, as documented in the PreTeXt Guide.  If you have multiple values due to multiple &quot;docinfo&quot; controlled by versions, then results will be very unpredictable.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2021-01-07  deprecate sidebyside within a webwork -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//webwork//sidebyside&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2021-01-07'\" />\n        <xsl:with-param name=\"message\" select=\"'a &quot;sidebyside&quot; as a descendant of a &quot;webwork&quot; has been replaced and now &quot;image&quot; and &quot;tabular&quot; elements should be used directly.'\"/>\n    </xsl:call-template>\n\n    <!-- 2021-02-14  deprecate using docinfo for part structure -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/numbering/division/@part&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2021-02-14'\" />\n        <xsl:with-param name=\"message\" select=\"'docinfo/numbering/division/@part has been replaced by the  numbering/divisions/@part-structure  entry in the publisher file, and is now ignored.  Please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2021-03-17  deprecate worksheet/pagebreak in favor of worksheet/page -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//worksheet/pagebreak&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2021-03-17'\" />\n        <xsl:with-param name=\"message\" select=\"'use of the empty &quot;pagebreak&quot; element has been deprecated in favor of a &quot;page&quot; element.  We will attempt to honor the empty element, but new features may only be available with the new element.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2021-06-24  deprecate @source to specify media on network -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//video[substring(@source,1,4) = 'http']|$document-root//audio[substring(@source,1,4) = 'http']&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2021-06-24'\" />\n        <xsl:with-param name=\"message\" select=\"'use of a &quot;@source&quot; attribute on a &quot;video&quot; or &quot;audio&quot; element to specify a network location (leading with &quot;http&quot;) has been deprecated, but will still be effective.  Replace with a &quot;@href&quot; attribute.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2021-07-02  deprecate notation/usage as bare LaTeX, needs exactly 1 \"m\"       -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//notation/usage[not(m)]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2021-07-02'\" />\n        <xsl:with-param name=\"message\" select=\"'a &quot;notation/usage&quot; element should contain *exactly* one &quot;m&quot;.  There is none, but we will attempt to honor your intent'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2021-09-19  obsolete Reveal.js slideshow @minified option -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$publication/revealjs/resources/@minified&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2021-09-19'\" />\n        <xsl:with-param name=\"message\" select=\"'the Reveal.js publisher option for minified resources (revealjs/resources/@minified) is obsolete and is being ignored.  Removing it will stop this message'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2021-10-04  glossary \"introduction\" is now a \"headnote\" -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//glossary/introduction&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2021-10-04'\" />\n        <xsl:with-param name=\"message\" select=\"'a &quot;glossary&quot; &quot;introduction&quot; is now a &quot;headnote&quot;.  We will attempt to fix your source.  See the documentation for this, and other changes for &quot;glossary&quot;'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2021-10-04  \"terms\" was necessary to structure a \"glossary\", now obsolete -->\n    <!-- Never in the schema, but a warning here as a public service -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//glossary/terms&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2021-10-04'\" />\n        <xsl:with-param name=\"message\" select=\"'a &quot;glossary&quot; no longer needs &quot;terms&quot; to structure its items.  We will attempt to fix your source.  See the documentation for this, and other changes for &quot;glossary&quot;'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2021-10-04  \"defined-term\" has been replaced by \"gi\" -->\n    <!-- Never in the schema, but a warning here as a public service -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//glossary/terms/defined-term&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2021-10-04'\" />\n        <xsl:with-param name=\"message\" select=\"'a &quot;glossary&quot; no longer has &quot;defined-term&quot; but instead has glossary items (&quot;gi&quot;).  We will attempt to fix your source.  See the documentation for this, and other changes for &quot;glossary&quot;'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2021-10-04  glossary \"conclusion\" is obsolete -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//glossary/conclusion&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2021-10-04'\" />\n        <xsl:with-param name=\"message\" select=\"'a &quot;glossary&quot; no longer has a &quot;conclusion&quot;.  It is being ignored, so you will need to design an alternative.  See the documentation for this, and other changes for &quot;glossary&quot;'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-04-22  Python Tutor via @interactive=\"pythontutor\" replaced by Runestone CodeLens-->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//program[@interactive = 'pythontutor']&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2022-04-22'\" />\n        <xsl:with-param name=\"message\" select=\"'a Python &quot;program&quot; with the attribute &quot;@interactive&quot; set to &quot;pythontutor&quot; is deprecated, but we will attempt to honor your intent.  Change the attribute value to &quot;codelens&quot; instead, and be certain to manufacture trace data using allied PreTeXt tools'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-04-25  \"label\" (typically on a list) is deprecated for renewal -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//ul/@label|$document-root//ol/@label&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2022-04-25'\" />\n        <xsl:with-param name=\"message\" select=\"'a &quot;@label&quot; attribute (on a &quot;ul&quot; or &quot;ol&quot; element) has been deprecated and should be replaced by the functionally equivalent &quot;@marker&quot;.  We will attempt to honor your request'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-04-25  \"label\" (typically on a list) is deprecated for renewal -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//video/track/@label&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2022-04-25'\" />\n        <xsl:with-param name=\"message\" select=\"'a &quot;@label&quot; attribute (on a &quot;video/track&quot; element) has been deprecated and should be replaced by the functionally equivalent &quot;@listing&quot;.  We will attempt to honor your request'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-06-09  replace a WebWorK \"stage\" by a standard \"task\" -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//webwork/stage&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2022-06-09'\" />\n        <xsl:with-param name=\"message\" select=\"'an ad-hoc &quot;stage&quot; element in a scaffolded WeBWorK problem has been replaced by a standard PreTeXt &quot;task&quot; element, so make simple subsitutions.  We will attempt to honor your request'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-07-10  deprecate latex-image with @syntax=\"PGtikz\" -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//latex-image[@syntax='PGtikz']&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2022-07-10'\" />\n        <xsl:with-param name=\"message\" select=\"'a &quot;latex-image&quot; with &quot;@syntax&quot; attribute set to &quot;PGtikz&quot; is deprecated in favor of a plain &quot;latex-image&quot;.  After removing the attribute, the &quot;latex-image&quot; code needs to be placed inside a &quot;tikzpicture&quot; environment. Until you make such changes to your source, we will attempt to honor your request'\"/>\n    </xsl:call-template>\n    <!-- 2022-07-25  warn of impending Wolfram CDF deprecation -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//interactive[@wolfram-cdf]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2022-07-25'\" />\n        <xsl:with-param name=\"message\" select=\"'support for Wolfram CDF &quot;interactive&quot; is slated to be removed soon.  Post on the &quot;pretext-support&quot; Google Group if this is an issue for your project'\"/>\n    </xsl:call-template>\n    <!-- 2022-08-07  Wolfram CDF deprecation -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//interactive[@wolfram-cdf]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2022-08-07'\" />\n        <xsl:with-param name=\"message\" select=\"'support for Wolfram CDF &quot;interactive&quot; has been removed'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2023-01-07  feedback button deprecation -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/feedback&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2023-01-07'\" />\n        <xsl:with-param name=\"message\" select=\"'election and configuration of a feedback button via a &quot;docinfo/feedback&quot; element has moved to the publication file with some small changes.  We will try to honor your intent, but results could be unpredictable'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2023-01-10  LaTeX front cover and back cover to publication file -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/covers&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2023-01-10'\" />\n        <xsl:with-param name=\"message\" select=\"'PDF front and back covers via a &quot;docinfo/covers&quot; element has moved to the publication file with some small changes.  We will try to honor your intent'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2023-01-27  deprecate \"datafile\" in favor of \"dataurl\"   -->\n    <!-- 2023-02-01  tightened deprecation to uses without @label -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//datafile[not(@label)]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2023-01-27'\" />\n        <xsl:with-param name=\"message\" select=\"'the old use of the &quot;datafile&quot; element has been replaced by the functionally-equivalent &quot;dataurl&quot; element.   New uses of &quot;datafile&quot; require a @label attribute.  So you are seeing this warning since your source has a &quot;datafile&quot; without a @label attribute.  We will try to honor your intent, but please make the change at your first convenience, as an automatic conversion might not be desirable in some cases.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2023-08-08  Simplify, and make more reliable, the URL for website entry of copyright page -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//colophon/website[address]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2023-08-08'\" />\n        <xsl:with-param name=\"message\" select=\"'a &quot;website&quot; element with &quot;address&quot; and &quot;name&quot; children has changed.  Continue to use the &quot;website&quot; element as before, but replace the &quot;address&quot; and &quot;name&quot; children with a single &quot;url&quot; element, which is more flexible and reliable.  We will try to honor your intent, but you may prefer your own adjustments.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2023-08-10  Kill the half-baked \"demonstration\" element-->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//demonstration&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2023-08-10'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;demonstration&quot; element has been removed with no natural replacement.  The &quot;interactive&quot; element may be sufficiently flexible to do something similar and will produce a standalone page that might serve a similar purpose.'\"/>\n    </xsl:call-template>\n    <!-- 2023-08-28  Deprecate console/prompt in favor of attributes-->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//console/prompt&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2023-08-28'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;prompt&quot; element of a &quot;console&quot; has been deprecated.  In its place, an &quot;input&quot; can have a @prompt attribute, or you can place a session-wide (not document-wide) @prompt attribute on the &quot;console&quot; element.  Until then, we will try to honor your intent.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2023-10-17  Deprecate docinfo/latex-preamble/package in favor of docinfo/math-package -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/latex-preamble/package&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2023-10-17'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;docinfo/latex-preamble/package&quot; element has been replaced by a &quot;docinfo/math-package&quot; element with &quot;@latex-name&quot; and &quot;@mathjax-name&quot; attributes.  Both attributes are required, but may be different, identical, or empty.  Note too that &quot;latex-preamble&quot; is no longer used for anything.  Until adjusted, we will honor your intent.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2023-10-17  docinfo/latex-preamble element is history -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/latex-preamble&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2023-10-17'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;docinfo/latex-preamble&quot; element no longer has a purpose.  Remove the element and adjust any contained &quot;package&quot; elements.  Then this warning will cease.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2023-02-13   initiate warnings about deprecation/removal of \"commentary\" string parameter -->\n    <!-- This is out of order chronologically, so that it is adjacent to a later follow-up message -->\n    <!-- NB: search entire code base on \"2023-02-13\"  and 2024-02-16                               -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//commentary[not(@component)]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2023-02-13'\" />\n        <xsl:with-param name=\"message\" select=\"'the string parameter &quot;commentary&quot; will be removed on, or after, 2024-02-13 (but not yet).  Any &quot;commentary&quot; elements present should be adjusted to have their visibility controlled by version support, specifically by first being placed in a &quot;component&quot;, and then controlled by entries of a publisher file.  Then &quot;commentary&quot; elements can be hidden just with version support.  To be visible you will need to use version support AND continue to use the string parameter.  On, or after, 2024-02-13, this warning will become a fatal error.'\"/>\n    </xsl:call-template>\n    <!-- 2024-02-16: add an additional warning message -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//commentary[not(@component)]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2024-02-16'\" />\n        <xsl:with-param name=\"message\" select=\"'a &quot;commentary&quot; element without a @component attribute is now routinely visible in all conversions.  This is unlikely to be what you want since the same effect can be had with no &quot;commentary&quot; element at all.  This message expands on the warning of 2023-02-13, and you might also be getting messages about the deprecation of the string parameter also named &quot;commentary&quot;.   Remove the &quot;commentary&quot; element, or consult the PreTeXt Guide to learn about version support and place the &quot;commentary&quot; element into a component using the attribute of the same name.'\"/>\n    </xsl:call-template>\n    <!-- 2025-03-08: add yet another warning message, but now -->\n    <!-- it is serious - \"commentary\" is deprecated (even if  -->\n    <!-- its use with version support will be respected)      -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//commentary&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2025-03-08'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;commentary&quot; element has been deprecated.  Remove the &quot;commentary&quot; element, and consult the PreTeXt Guide to learn about how version support can have the same effect. (If your &quot;commentary&quot; element uses a &quot;component&quot; attribute, we will try to honor your intent.)'\"/>\n    </xsl:call-template>\n    <!-- Any componentless \"commentary\" at all - fatal error -->\n    <!-- NB: $document-root is \"too late\" here it seems,     -->\n    <!-- as this is not the \"deprecation-message\" template,  -->\n    <!-- so we instead hard-code the $original tree          -->\n    <xsl:if test=\"$original//commentary[not(@component)]\">\n        <xsl:message terminate=\"yes\">PTX:FATAL:    a \"commentary\" without a @component attribute is a fatal error from 2024-02-16 onward.  Read preceding error messages (2023-02-13, 2024-02-16, 2025-03-08), and make the suggested changes.  Quitting...</xsl:message>\n    </xsl:if>\n    <!--  -->\n    <!-- 2024-07-08  various mis-matches all settled in favor of \"qrcode\" -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$publication/common/qr-code&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2024-07-08'\" />\n        <xsl:with-param name=\"message\" select=\"'the publisher file entry &quot;common/qr-code&quot; is obsolete and is being ignored.  Make a cosmetic change to &quot;common/qrcode&quot;.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2024-07-29  \"label\" element in \"latex-image\" is deprecated -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//latex-image/label&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2024-07-29'\" />\n        <xsl:with-param name=\"message\" select=\"'use of a &quot;label&quot; element inside a &quot;latex-image&quot; is deprecated and there is no replacement.  Formulate the appropriate LaTeX code (TikZ) as a replacement.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2024-07-31 (warning added 2024-08-05) metadata, notably idx, banned as child of sidebyside -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//sidebyside/*[&METADATA-FILTER;]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2017-07-31'\" />\n        <xsl:with-param name=\"message\" select=\"'metadata elements &quot;&METADATA;&quot; in a sidebyside will be ignored'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2024-10-08 titlepage no longer required for holding author|editor|credit|date in frontmatter -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root/frontmatter/titlepage[author or editor or credit or date or event]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2024-10-08'\" />\n        <xsl:with-param name=\"message\" select=\"'elements previously included in a &quot;titlepage&quot; element inside the &quot;frontmatter&quot; (author, editor, credit, date, and event) should now be placed in &quot;frontmatter/bibinfo&quot;.  To ensure a title page is created, put only the empty element &quot;titlepage-items&quot; inside &quot;titlepage&quot;.  Until you move these elements, we will try to honor your intent.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2024-10-08 colophon no longer required for holding copyright|credit|edition|website in frontmatter -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root/frontmatter/colophon[credit or copyright or edition or website]&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2024-10-08'\" />\n        <xsl:with-param name=\"message\" select=\"'elements previously included in a &quot;colophon&quot; element inside the &quot;frontmatter&quot; (credit, copyright, edition, and website) should now be placed in &quot;frontmatter/bibinfo&quot;. To produce a &quot;colophon&quot;, include only the empty element &quot;colophon-items&quot; inside &quot;colophon&quot; Until you move these elements, we will try to honor your intent.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2024-11-09 docinfo \"favicon\" now is a publisher file option -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/html/favicon&quot;\"/>\n        <xsl:with-param name=\"date-string\" select=\"'2024-11-09'\" />\n        <xsl:with-param name=\"message\" select=\"'use of a favicon in HTML output is no longer accomplished with a &quot;favicon&quot; element inside &quot;docinfo&quot;.  Instead use the publication file and put a &quot;@favicon&quot; attribute on the &quot;html&quot; element.  Set its value to &quot;simple&quot; for equivalent behavior.  Until you remove the element in &quot;docinfo&quot;, we will try to honor your intent.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2024-11-19 (warning added 2024-11-19) program/input renamed program/code and input repurposed -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//program/input&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2024-11-19'\" />\n        <xsl:with-param name=\"message\" select=\"'program/input now should be program/code. An automatic correction will be attempted.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!--  -->\n    <!-- 2025-03-09: mass removal of backward-compatiblity of old-style specifications in \"docinfo\" -->\n    <!--  -->\n    <!--  -->\n    <!-- From 2019-04-14 -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/analytics&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2025-03-09'\" />\n        <xsl:with-param name=\"message\" select=\"'site-specific ID for HTML analytics services (Statcounter, Google) provided within &quot;docinfo/analytics&quot; are now options supplied by publishers as command-line options.  See the Publishers Guide for specifics.  Specification in &quot;docinfo&quot; is now being ignored.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- From 2019-04-14 -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/search&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2025-03-09'\" />\n        <xsl:with-param name=\"message\" select=\"'site-specific ID for HTML search services (Google) is no longer provided within &quot;docinfo/search&quot;.  Please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide. Specification in &quot;docinfo&quot; is now being ignored.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- From 2020-11-22 -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/html/baseurl/@href&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2025-03-09'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;baseurl/@href&quot; element in the &quot;docinfo&quot; has been replaced and is now specified in the publisher file with &quot;html/baseurl/@href&quot;, as documented in the PreTeXt Guide.  Specification in &quot;docinfo&quot; is now being ignored.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- From 2023-01-07 -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/feedback&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2025-03-09'\" />\n        <xsl:with-param name=\"message\" select=\"'election and configuration of a feedback button via a &quot;docinfo/feedback&quot; element has moved to the publication file with some small changes.  Specification in &quot;docinfo&quot; is now being ignored.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- From 2023-01-10  -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/covers&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2025-03-09'\" />\n        <xsl:with-param name=\"message\" select=\"'PDF front and back covers via a &quot;docinfo/covers&quot; element has moved to the publication file with some small changes.  Specification in &quot;docinfo&quot; is now being ignored.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2024-07-24 @permid abolished -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//@permid&quot;\"/>\n        <xsl:with-param name=\"date-string\" select=\"'2024-07-24'\" />\n        <xsl:with-param name=\"max-reports\" select=\"'0'\" />\n        <xsl:with-param name=\"message\" select=\"'Experiments using the @permid attribute have concluded, and the attribute is now being ignored.  You can safely remove them all and then this message will stop.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2024-11-19 listing no longer has caption, uses title only -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"$document-root//listing/caption\"/>\n        <xsl:with-param name=\"date-string\" select=\"'2024-11-19'\" />\n        <xsl:with-param name=\"message\" select=\"'Use of caption in listings is no longer supported. Listings should only have a title. We will try to honor your intent.'\"/>\n    </xsl:call-template>\n  <!--  -->\n    <!-- 2025-04-18 -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//matches&quot;\"/>\n        <xsl:with-param name=\"date-string\" select=\"'2025-04-18'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;matches&quot; element inside an &quot;exercise&quot; (or similar) to specify a drag-n-drop problem has been replaced by the &quot;cardsort&quot; element.  This is an entirely cosmetic change.  Until you make the change in your source, we will try to honor your intent.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2025-04-23 -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//matches/match/@order|$document-root//cardsort/match/@order&quot;\"/>\n        <xsl:with-param name=\"date-string\" select=\"'2025-04-23'\" />\n        <xsl:with-param name=\"message\" select=\"'an &quot;@order&quot; attribute on a &quot;match&quot; is deprecated and should instead be placed on the contained &quot;premise&quot; element(s).  If your cardsort problem is simply a 1-1 correspondence, then we will honor your intent.  If your problem is more complicated (multiple &quot;premise&quot; inside a &quot;match&quot;) results may be variable and unpredictable.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2025-04-25  deprecate \"program@datafile\" in favor of \"program@add-files\"   -->\n    <xsl:call-template name=\"deprecation-message\">\n      <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//datafile[@datafile]&quot;\" />\n      <xsl:with-param name=\"date-string\" select=\"'2025-04-25'\" />\n      <xsl:with-param name=\"message\" select=\"'the program@datafile attribute containing datafile@filename has been deprecated. You should change programs to use the @add-files attribute and use it specify the xml:id of datafiles to make available.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2025-07-19  Docinfo worksheet margins for LaTeX now ignored -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/latex-output/worksheet&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2025-07-19'\" />\n        <xsl:with-param name=\"message\" select=\"'Custom margin specification for worksheets (in both HTML and LaTeX) has moved to the publication file in &quot;/publication/common/worksheet&quot;.  Any margins specified in &quot;docinfo/latex-output/worksheet&quot; will be ignored.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2025-08-27  \"label\" element in \"latex-image\" is no longer functional -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//latex-image/label&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2025-08-27'\" />\n        <xsl:with-param name=\"message\" select=\"'use of a &quot;label&quot; element inside a &quot;latex-image&quot; was deprecated on 2024-07-29.  It is no longer functional, so you must formulate the appropriate LaTeX code (TikZ) as a replacement.  If the &quot;label&quot; element remains, results could be unpredictable.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2025-11-04  @runestone attribute signals obsolete \"htmlhack\" exercises -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//@runestone&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2025-11-04'\" />\n        <xsl:with-param name=\"message\" select=\"'the temporary &quot;@runestone&quot; attribute was used to temporarily specify a raw HTML version of a Runestone problem.  That device is now obsolete.  The exercise remains, but its contents have been neutered to form an informational message.  Consider authoring the exercise using supported PreTeXt syntax.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2026-05-11  \"me\" and \"men\" deprecated in favor of bare \"md\" -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//me|$document-root//men&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2026-05-11'\" />\n        <xsl:with-param name=\"max-reports\" select=\"'8'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;me&quot; and &quot;men&quot; elements have been deprecated.  The replacement is an &quot;md&quot; with no &quot;mrow&quot; children, and numbering is controlled by the &quot;@number&quot; attribute, or a global setting in &quot;docinfo&quot;.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2026-05-11  \"mdn\" deprecated in favor of \"md\" -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//mdn&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2026-05-11'\" />\n        <xsl:with-param name=\"max-reports\" select=\"'8'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;mdn&quot; element has been deprecated.  The replacement is an &quot;md&quot;, and numbering is controlled by the &quot;@number&quot; attribute, or a global setting in &quot;docinfo&quot;.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2026-05-22  \"@include-source\" attribute deprecated -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//@include-source&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2026-05-22'\" />\n        <xsl:with-param name=\"message\" select=\"'the &quot;@include-source&quot; attribute has been deprecated and it will be ignored.  No replacement is planned.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2026-07-08  \"title\" deprecated on \"introduction\"/\"conclusion\" of a traditional division -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//introduction[parent::article or parent::chapter or parent::appendix or parent::section or parent::subsection]/title | $document-root//conclusion[parent::article or parent::chapter or parent::appendix or parent::section or parent::subsection]/title&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2026-07-08'\" />\n        <xsl:with-param name=\"message\" select=\"'a &quot;title&quot; on an &quot;introduction&quot; or &quot;conclusion&quot; of a traditional division has been deprecated, and it will be ignored.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2026-07-22  \"audio\", \"video\", \"interactive\" precluded within \"sidebyside\" -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//sidebyside//audio | $document-root//sidebyside//video | $document-root//sidebyside//interactive&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2026-07-22'\" />\n        <xsl:with-param name=\"message\" select=\"'an &quot;audio&quot;, &quot;video&quot;, or &quot;interactive&quot; element may not appear within a &quot;sidebyside&quot;, at any depth.  Content may go missing with no further warning.  Relocate the element outside the &quot;sidebyside&quot;.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2026-07-30  \"programs\" and \"parsons\" relocate into \"docinfo/defaults\" -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/programs | $docinfo/parsons&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2026-07-30'\" />\n        <xsl:with-param name=\"message\" select=\"'a &quot;programs&quot; or &quot;parsons&quot; element now resides within a &quot;defaults&quot; element of the &quot;docinfo&quot;, alongside other document-wide defaults for authored attributes.  We will honor your intent, but please relocate the element.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2026-07-30  \"docinfo/defaults/image-width\" element becomes \"images/@width\" -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/defaults/image-width&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2026-07-30'\" />\n        <xsl:with-param name=\"message\" select=\"'a document-wide default width for images is now a &quot;width&quot; attribute on an &quot;images&quot; element within &quot;docinfo/defaults&quot;, replacing the &quot;image-width&quot; element.  We will honor your intent, but please convert to the attribute form.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2026-07-30  \"docinfo/images/archive\" moves to the publication file -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/images&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2026-07-30'\" />\n        <xsl:with-param name=\"message\" select=\"'requests for archive (download) versions of images have moved to the publication file, as &quot;/publication/html/images/archive&quot;.  We will honor an &quot;images&quot; element within &quot;docinfo&quot; while the publication file is silent, but please relocate the request.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2026-07-30  \"docinfo/brandlogo\" moves to the publication file -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/brandlogo&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2026-07-30'\" />\n        <xsl:with-param name=\"message\" select=\"'the brand logo of the HTML masthead has moved to the publication file, as &quot;/publication/html/brandlogo&quot; with the same attributes.  We will honor a &quot;brandlogo&quot; within &quot;docinfo&quot; while the publication file is silent, but please relocate the element.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2026-07-30  \"event\" is bibliographic content, belongs in \"bibinfo\" -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/event&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2026-07-30'\" />\n        <xsl:with-param name=\"message\" select=\"'an &quot;event&quot; element now resides in the &quot;bibinfo&quot; of the &quot;frontmatter&quot;, alongside the other bibliographic facts of a document.  We will honor an &quot;event&quot; within &quot;docinfo&quot;, but please relocate the element.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2026-07-31  \"docinfo/cross-references\" becomes \"xrefs\" within \"docinfo/defaults\" -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$docinfo/cross-references&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2026-07-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the document-wide style of cross-reference text is now a &quot;text&quot; attribute on an &quot;xrefs&quot; element within &quot;docinfo/defaults&quot;, replacing the &quot;cross-references&quot; element.  We will honor your intent, but please convert to the new form.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2026-07-31  a footnote within a \"tabular\" cell becomes a \"tn\" table note -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//tabular//fn&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2026-07-31'\" />\n        <xsl:with-param name=\"message\" select=\"'a footnote (&quot;fn&quot;) within a &quot;tabular&quot; cell is now a table note, the &quot;tn&quot; element, lettered and placed at the bottom of the table.  We will honor your intent, but please convert to &quot;tn&quot;.  Note that a table note is not part of the numbering of true footnotes, and is not a target for a cross-reference.'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2026-08-06  references \"introduction\" is now a \"headnote\" -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//references/introduction&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2026-08-06'\" />\n        <xsl:with-param name=\"message\" select=\"'a &quot;references&quot; &quot;introduction&quot; is now a &quot;headnote&quot;.  We will attempt to fix your source, but a &quot;title&quot; on such an &quot;introduction&quot; is discarded entirely: its text will not appear in any output.  Please convert to a &quot;headnote&quot; yourself'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2026-08-06  references \"conclusion\" is obsolete -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//references/conclusion&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2026-08-06'\" />\n        <xsl:with-param name=\"message\" select=\"'a &quot;references&quot; division no longer has a &quot;conclusion&quot;.  The element is discarded entirely: its content will not appear in any output.  Please relocate the content, perhaps following the &quot;references&quot;'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2026-08-20  \"ol\" as a child of \"exercise\" is obsolete -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//exercise/ol&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2026-08-20'\" />\n        <xsl:with-param name=\"message\" select=\"'an &quot;ol&quot; is no longer a child of an &quot;exercise&quot;; a list belongs inside a &quot;p&quot;.  We will wrap it for you, and lettered exercise parts will letter as before.  Please convert: structure true parts with &quot;task&quot;, letter a plain list with marker=&quot;(a)&quot;, or consider an &quot;exercisegroup&quot; and its cols attribute for a compact multi-column layout'\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2026-08-20  \"ol\" as a child of an exercise \"statement\" is obsolete -->\n    <xsl:call-template name=\"deprecation-message\">\n        <xsl:with-param name=\"occurrences\" select=\"&quot;$document-root//exercise/statement/ol&quot;\" />\n        <xsl:with-param name=\"date-string\" select=\"'2026-08-20'\" />\n        <xsl:with-param name=\"message\" select=\"'an &quot;ol&quot; is no longer a child of an &quot;exercise&quot; &quot;statement&quot;; a list belongs inside a &quot;p&quot;.  We will wrap it for you, and lettered exercise parts will letter as before.  Please convert: structure true parts with &quot;task&quot;, letter a plain list with marker=&quot;(a)&quot;, or consider an &quot;exercisegroup&quot; and its cols attribute for a compact multi-column layout'\"/>\n    </xsl:call-template>\n    <!--  -->\n</xsl:template>\n\n<!-- Miscellaneous -->\n\n<!-- ToDo's are silent unless requested as part of an -->\n<!-- author's report, then marginal.  They exist in   -->\n<!-- source as prefixed comments, and that prefix     -->\n<!-- suffices as part of the output                   -->\n<xsl:template match=\"comment()[translate(substring(normalize-space(string(.)), 1, 4), &UPPERCASE;, &LOWERCASE;) = 'todo']\">\n    <xsl:call-template name=\"margin-warning\">\n        <xsl:with-param name=\"warning\">\n            <xsl:call-template name=\"strip-leading-whitespace\">\n                <xsl:with-param name=\"text\">\n                    <xsl:value-of select=\".\"/>\n                </xsl:with-param>\n            </xsl:call-template>\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- Converter information for header, generic -->\n<!-- params are strings to make comment lines in target file    -->\n<!-- \"copy-of\" supresses output-escaping of HTML/XML characters -->\n<!-- Parameterize by need/desire for date/commit information    -->\n<xsl:template name=\"converter-blurb\">\n    <xsl:param name=\"lead-in\" />\n    <xsl:param name=\"lead-out\" />\n    <xsl:copy-of select=\"$lead-in\" /><xsl:text>********************************************</xsl:text><xsl:copy-of select=\"$lead-out\" /><xsl:text>&#xa;</xsl:text>\n    <xsl:copy-of select=\"$lead-in\" /><xsl:text>*       Generated from PreTeXt source      *</xsl:text><xsl:copy-of select=\"$lead-out\" /><xsl:text>&#xa;</xsl:text>\n    <xsl:if test=\"$b-debug-datedfiles\">\n    <xsl:copy-of select=\"$lead-in\" /><xsl:text>*       on </xsl:text>  <xsl:value-of select=\"date:date-time()\" />\n                                                                      <xsl:text>       *</xsl:text><xsl:copy-of select=\"$lead-out\" /><xsl:text>&#xa;</xsl:text>\n    <xsl:copy-of select=\"$lead-in\" /><xsl:text>*   A recent stable commit (2022-07-01):   *</xsl:text><xsl:copy-of select=\"$lead-out\" /><xsl:text>&#xa;</xsl:text>\n    <xsl:copy-of select=\"$lead-in\" /><xsl:text>* 6c761d3dba23af92cba35001c852aac04ae99a5f *</xsl:text><xsl:copy-of select=\"$lead-out\" /><xsl:text>&#xa;</xsl:text>\n    </xsl:if>\n    <xsl:copy-of select=\"$lead-in\" /><xsl:text>*                                          *</xsl:text><xsl:copy-of select=\"$lead-out\" /><xsl:text>&#xa;</xsl:text>\n    <xsl:copy-of select=\"$lead-in\" /><xsl:text>*         https://pretextbook.org          *</xsl:text><xsl:copy-of select=\"$lead-out\" /><xsl:text>&#xa;</xsl:text>\n    <xsl:copy-of select=\"$lead-in\" /><xsl:text>*                                          *</xsl:text><xsl:copy-of select=\"$lead-out\" /><xsl:text>&#xa;</xsl:text>\n    <xsl:copy-of select=\"$lead-in\" /><xsl:text>********************************************</xsl:text><xsl:copy-of select=\"$lead-out\" /><xsl:text>&#xa;</xsl:text>\n</xsl:template>\n\n<!-- This version is identical (keep in sync) but *never* has any date  -->\n<!-- information.  This was added for the multitude of files in an HTML  -->\n<!-- conversion, when we just left one file (index.html) with a date. -->\n<xsl:template name=\"converter-blurb-no-date\">\n    <xsl:param name=\"lead-in\" />\n    <xsl:param name=\"lead-out\" />\n    <xsl:copy-of select=\"$lead-in\" /><xsl:text>********************************************</xsl:text><xsl:copy-of select=\"$lead-out\" /><xsl:text>&#xa;</xsl:text>\n    <xsl:copy-of select=\"$lead-in\" /><xsl:text>*       Generated from PreTeXt source      *</xsl:text><xsl:copy-of select=\"$lead-out\" /><xsl:text>&#xa;</xsl:text>\n    <xsl:copy-of select=\"$lead-in\" /><xsl:text>*                                          *</xsl:text><xsl:copy-of select=\"$lead-out\" /><xsl:text>&#xa;</xsl:text>\n    <xsl:copy-of select=\"$lead-in\" /><xsl:text>*         https://pretextbook.org          *</xsl:text><xsl:copy-of select=\"$lead-out\" /><xsl:text>&#xa;</xsl:text>\n    <xsl:copy-of select=\"$lead-in\" /><xsl:text>*                                          *</xsl:text><xsl:copy-of select=\"$lead-out\" /><xsl:text>&#xa;</xsl:text>\n    <xsl:copy-of select=\"$lead-in\" /><xsl:text>********************************************</xsl:text><xsl:copy-of select=\"$lead-out\" /><xsl:text>&#xa;</xsl:text>\n</xsl:template>\n\n<!-- We issue specialized blurbs with appropriate comment lines -->\n<xsl:template name=\"converter-blurb-text\">\n    <xsl:call-template name=\"converter-blurb\">\n        <xsl:with-param name=\"lead-in\"  select=\"''\" />\n        <xsl:with-param name=\"lead-out\" select=\"''\" />\n    </xsl:call-template>\n</xsl:template>\n\n<xsl:template name=\"converter-blurb-latex\">\n    <xsl:call-template name=\"converter-blurb\">\n        <xsl:with-param name=\"lead-in\"  select=\"'%'\" />\n        <xsl:with-param name=\"lead-out\" select=\"'%'\" />\n    </xsl:call-template>\n</xsl:template>\n\n<xsl:template name=\"converter-blurb-html\">\n    <xsl:call-template name=\"converter-blurb\">\n        <xsl:with-param name=\"lead-in\">\n            <xsl:text disable-output-escaping='yes'>&lt;!--</xsl:text>\n        </xsl:with-param>\n        <xsl:with-param name=\"lead-out\">\n            <xsl:text disable-output-escaping='yes'>--&gt;</xsl:text>\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n<xsl:template name=\"converter-blurb-html-no-date\">\n    <xsl:call-template name=\"converter-blurb-no-date\">\n        <xsl:with-param name=\"lead-in\">\n            <xsl:text disable-output-escaping='yes'>&lt;!--</xsl:text>\n        </xsl:with-param>\n        <xsl:with-param name=\"lead-out\">\n            <xsl:text disable-output-escaping='yes'>--&gt;</xsl:text>\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n<xsl:template name=\"converter-blurb-python\">\n    <xsl:call-template name=\"converter-blurb\">\n        <xsl:with-param name=\"lead-in\"  select=\"'#'\" />\n        <xsl:with-param name=\"lead-out\" select=\"'#'\" />\n    </xsl:call-template>\n</xsl:template>\n\n<xsl:template name=\"converter-blurb-perl\">\n    <xsl:call-template name=\"converter-blurb\">\n        <xsl:with-param name=\"lead-in\"  select=\"'#'\" />\n        <xsl:with-param name=\"lead-out\" select=\"'#'\" />\n    </xsl:call-template>\n</xsl:template>\n\n<!-- WeBWorK's editor is not monospaced, so the right border       -->\n<!-- looks ragged.  We effectively rubout the right margin,        -->\n<!-- then translate all asterisks to octothorpes.  The left margin -->\n<!-- becomes three octothorpes to not be confused with metadata    -->\n<!-- This can revert to  -perl  if the editor changes              -->\n<!-- 2026-05-22: removed dates, too much noise in diffs            -->\n<xsl:template name=\"converter-blurb-webwork\">\n    <xsl:variable name=\"blurb\">\n        <xsl:call-template name=\"converter-blurb-no-date\">\n            <xsl:with-param name=\"lead-in\"  select=\"'##'\" />\n            <xsl:with-param name=\"lead-out\" select=\"'XXX'\" />\n        </xsl:call-template>\n    </xsl:variable>\n    <xsl:value-of select=\"str:replace(str:replace($blurb, '*XXX', ''), '*', '#')\" />\n</xsl:template>\n\n<!-- ################# -->\n<!-- Percent Utilities -->\n<!-- ################# -->\n\n<!-- Take as input a node set of attributes -->\n<!-- of percentages (with '%' at the end)   -->\n<!-- Check that sum is under 100%           -->\n<!-- NB: can $nodes be stripped without the  position()  function? -->\n<xsl:template name=\"cap-width-at-one-hundred-percent\">\n    <xsl:param name=\"nodeset\" />\n    <xsl:param name=\"cap\" select=\"100\" />\n    <xsl:if test=\"$nodeset\">\n        <xsl:if test=\"substring-before($nodeset[1], '%')&gt;$cap\">\n            <xsl:message terminate=\"yes\">PTX:FATAL:   percentage attributes sum to over 100%</xsl:message>\n        </xsl:if>\n        <xsl:call-template name=\"cap-width-at-one-hundred-percent\">\n            <xsl:with-param name=\"nodeset\" select=\"$nodeset[position()&gt;1]\" />\n            <xsl:with-param name=\"cap\" select=\"$cap - substring-before($nodeset[1], '%')\" />\n        </xsl:call-template>\n    </xsl:if>\n</xsl:template>\n\n<!-- Take a string as input    -->\n<!-- Abort if not in the form  -->\n<!-- \\s*[0-9]*\\.?[0-9]*\\s*%\\s* -->\n<!-- Normalize to              -->\n<!-- [0-9]*\\.?[0-9]*%          -->\n<xsl:template name=\"normalize-percentage\">\n    <xsl:param name=\"percentage\" />\n    <xsl:variable name=\"stripped-percentage\">\n        <xsl:value-of select=\"normalize-space($percentage)\" />\n    </xsl:variable>\n    <xsl:if test=\"substring($stripped-percentage,string-length($stripped-percentage)) != '%'\">\n        <xsl:message terminate=\"yes\">PTX:FATAL:   expecting a percentage ending in '%'; got <xsl:value-of select=\"$stripped-percentage\"/></xsl:message>\n    </xsl:if>\n    <xsl:variable name=\"percent\">\n        <xsl:value-of select=\"normalize-space(substring($stripped-percentage,1,string-length($stripped-percentage) - 1))\" />\n    </xsl:variable>\n    <xsl:if test=\"number($percent) != $percent\">\n        <xsl:message terminate=\"yes\">PTX:FATAL:   expecting a numerical value preceding '%'; got <xsl:value-of select=\"$percent\"/></xsl:message>\n    </xsl:if>\n    <xsl:value-of select=\"concat($percent,'%')\" />\n</xsl:template>\n\n<!-- Sometimes this template is useful to see which    -->\n<!-- templates are not implemented at all in some new  -->\n<!-- (basic) conversion building just on this -common. -->\n<!-- Maybe \"dead-ending\" is preferable (remove the     -->\n<!-- apply-templates) and/or maybe a lower priority    -->\n<!-- will work better.                                 -->\n\n<!--\n<xsl:template match=\"*\" priority=\"0\">\n    <xsl:message>[<xsl:value-of select=\"local-name(.)\"/>]</xsl:message>\n    <xsl:apply-templates/>\n</xsl:template>\n-->\n\n</xsl:stylesheet>\n","pretext-html.xsl":"<?xml version='1.0'?> <!-- As XML file -->\n\n<!--********************************************************************\nCopyright (C) 2013-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- http://pimpmyxslt.com/articles/entity-tricks-part2/ -->\n<!DOCTYPE xsl:stylesheet [\n    <!ENTITY % entities SYSTEM \"entities.ent\">\n    %entities;\n]>\n\n<!-- Identify as a stylesheet -->\n<!-- We choose to not include a default namespace       -->\n<!-- (in particular  http://www.w3.org/1999/xhtml),     -->\n<!-- even if this complicates adding namespaces onto    -->\n<!-- derivatives, such as HTML destined for EPUB output -->\n<!-- xmlns=\"http://www.w3.org/1999/xhtml\"               -->\n<!--                                                    -->\n<!-- NB:                                                -->\n<!--   \"xsl\" is necessary to identify XSL functionality -->\n<!--   \"xml\" is automatic, hence redundant              -->\n<!--   \"svg\" is necessary to for Asymptote 3D images    -->\n<!--   \"pi\" is meant to mark private PreTeXt markup     -->\n<!--   \"exsl\" namespaces enable extension functions     -->\n<!--                                                    -->\n<!-- Excluding result prefixes keeps them from bleeding -->\n<!-- into output unnecessarily -->\n<xsl:stylesheet\n    xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\"\n    xmlns:xml=\"http://www.w3.org/XML/1998/namespace\"\n    xmlns:svg=\"http://www.w3.org/2000/svg\"\n    xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n    xmlns:pi=\"http://pretextbook.org/2020/pretext/internal\"\n    xmlns:exsl=\"http://exslt.org/common\"\n    xmlns:date=\"http://exslt.org/dates-and-times\"\n    xmlns:str=\"http://exslt.org/strings\"\n    xmlns:fn=\"http://www.w3.org/2005/xpath-functions\"\n    xmlns:pf=\"https://prefigure.org\"\n    exclude-result-prefixes=\"svg xlink pi fn pf\"\n    extension-element-prefixes=\"exsl date str\"\n>\n\n<!-- Allow writing of JSON from structured HTML -->\n<xsl:import href=\"./xml-to-json.xsl\"/>\n\n<!-- Standard conversion groundwork -->\n<xsl:import href=\"./publisher-variables.xsl\"/>\n<xsl:import href=\"./pretext-assembly.xsl\"/>\n<xsl:import href=\"./pretext-common.xsl\"/>\n\n<!-- Modularize lots of Runestone-specific code    -->\n<!-- Likely need not be an \"import\" (v. \"include\") -->\n<xsl:import href=\"./pretext-runestone.xsl\"/>\n<xsl:import href=\"./pretext-runestone-fitb.xsl\"/>\n\n<!-- Routines to provide \"View Source\" annotations on HTML output   -->\n<!-- as a service on the PreTeXt website. NB: we use an \"include\"   -->\n<!-- to provide this set of templates.  The included stylesheet has -->\n<!-- radically different \"strip-space\" and \"preserve-space\"         -->\n<!-- declarations, which seem to *not* provide overrrides, and are  -->\n<!-- simply \"local\" to that stylesheet.                             -->\n<xsl:import href=\"./pretext-view-source.xsl\"/>\n\n<!-- We create HTML5 output.  The @doctype-system attribute will    -->\n<!-- create a header in the old style that browsers will recognize  -->\n<!-- as signaling HTML5.  However  xsltproc  does one better and    -->\n<!-- writes the super-simple <!DOCTYPE html> header.  See all of    -->\n<!-- https://stackoverflow.com/questions/3387127/                   -->\n<!-- (set-html5-doctype-with-xslt)                                  -->\n<!--                                                                -->\n<!-- Indentation is weak, it is just strategic newlines.  This is   -->\n<!-- explained late in the thread by Daniel Veillard:               -->\n<!-- http://docbook-apps.oasis-open.narkive.com/tDqyEc91/           -->\n<!-- (two-issues-with-xslt-processors-xsltproc-and-xalan)           -->\n<!--                                                                -->\n<!-- Since we write output into multiple files, likely this         -->\n<!-- declaration is never active, but it serves as a model here for -->\n<!-- subsequent exsl:document elements.                             -->\n\n<xsl:output method=\"html\" indent=\"yes\" encoding=\"UTF-8\" doctype-system=\"about:legacy-compat\" />\n\n<!-- ################################################ -->\n<!-- Following is slated to migrate above, 2019-07-10 -->\n<!-- ################################################ -->\n\n<!-- Parameters -->\n<!-- Parameters to pass via xsltproc \"stringparam\" on command-line            -->\n<!-- Or make a thin customization layer and use 'select' to provide overrides -->\n<!-- See more generally applicable parameters in pretext-common.xsl file     -->\n\n<!-- CSS and Javascript Directories -->\n<!-- These are convenience variables to specify file prefixes  -->\n<!-- consistently.  If you know what you are doing you could   -->\n<!-- likely point them elsewhere, even to other servers.       -->\n<!-- So the name says \"dir\", but effectively it is \"location\". -->\n<!-- But this is not the intent, nor supported, and thus can   -->\n<!-- change without warning.                                   -->\n<xsl:variable name=\"html.css.dir\" select=\"concat($cdn-prefix, '_static/pretext/css')\"/>\n<!-- Root of the static JS tree (js/ from the pretext core repo) -->\n<xsl:variable name=\"html.js.root\" select=\"concat($cdn-prefix, '_static/pretext/js')\"/>\n<!-- Built distribution files live in a dist/ subdirectory -->\n<xsl:variable name=\"html.js.dir\" select=\"concat($html.js.root, '/dist')\"/>\n\n<!-- Add a prefix for the cdn url, which is empty unless the portable html variable is true -->\n<!-- We use version \"latest\" unless the CLI provides a version -->\n<xsl:param name=\"cli.version\" select=\"'latest'\"/>\n<xsl:variable name=\"cdn-prefix\">\n    <xsl:if test=\"$b-cdn-resources\">\n        <xsl:text>https://cdn.jsdelivr.net/gh/PreTeXtBook/html-static@</xsl:text>\n        <xsl:value-of select=\"$cli.version\"/>\n        <xsl:text>/dist/</xsl:text>\n    </xsl:if>\n</xsl:variable>\n\n<!-- The css file name is usually \"theme.css\", but if cdn resources are selected, -->\n<!-- then we use a minified version and need to give the full theme name.         -->\n<xsl:variable name=\"html-css-theme-file\">\n    <xsl:choose>\n        <xsl:when test=\"$b-cdn-resources\">\n            <xsl:text>theme-</xsl:text>\n            <xsl:value-of select=\"$html-theme-name\"/>\n            <xsl:text>.min.css</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>theme.css</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- Should we build the SCORM manifest file? -->\n<xsl:param name=\"html.scorm\" select=\"'no'\" />\n<!-- b-host-scorm is true when building a SCORM package  -->\n<!-- We might consider making this depend on a publisher variable instead of param -->\n<xsl:variable name=\"b-host-scorm\" select=\"($html.scorm = 'yes')\"/>\n\n<!-- ######### -->\n<!-- Variables -->\n<!-- ######### -->\n<!-- Variables that affect HTML creation -->\n<!-- More in the common file             -->\n\n<!-- The  pretext-assembly.xsl  stylesheet is parameterized to create  -->\n<!-- representations of interactive exercises in final \"static\"        -->\n<!-- versions or precursor \"dynamic\" versions.  The conversion to HTML -->\n<!-- is the motivation for this parameterization.  See the definition  -->\n<!-- of this variable in  pretext-assembly.xsl  for more detail.       -->\n<!--                                                                   -->\n<!-- Conversions that build on HTML, but produce formats unwilling     -->\n<!-- (EPUB, Jupyter) to employ Javascript, or similar, need to         -->\n<!-- override this variable back to \"static\".                          -->\n<xsl:variable name=\"exercise-style\" select=\"'dynamic'\"/>\n\n<!-- Search for the \"math.punctuation.include\" -->\n<!-- global variable, which is discussed in    -->\n<!-- closer proximity to its application.      -->\n\n<!-- Various components need to be built with pixel widths from % based widths -->\n<!-- design-width is the 100% value. We override the -common value here,       -->\n<!-- possibly getting a value defined in the pub file. If not, this should get -->\n<!-- set to the value from -common                                             -->\n<xsl:variable name=\"design-width\">\n    <xsl:value-of select=\"$html-design-width\"/>\n</xsl:variable>\n\n<!-- We generally want to chunk longer HTML output.       -->\n<!-- Delegates to $html-chunk-level in publisher-variables -->\n<!-- so lightweight stylesheets can access the same logic. -->\n<xsl:variable name=\"chunk-level\" select=\"$html-chunk-level\"/>\n\n<!-- A document with chunking set to 0, or with no chapters or sections -->\n<!-- will be a single page. -->\n<xsl:variable name=\"b-is-single-page\" select=\"$chunk-level = 0 or ($b-is-article and count($document-root/section) = 0) or ($b-is-book and count($document-root//chapter) = 0)\"/>\n\n<!-- HTML files as output -->\n<xsl:variable name=\"file-extension\" select=\"'.html'\" />\n\n<!-- \"presentation\" mode is experimental, target        -->\n<!-- is in-class presentation of a textbook             -->\n<!--   (1) clickable mathematics (MathJax) at 300% zoom -->\n<!-- boolean variable $b-html-presentation              -->\n<xsl:param name=\"html.presentation\" select=\"'no'\" />\n<xsl:variable name=\"b-html-presentation\" select=\"$html.presentation = 'yes'\" />\n\n<!-- Used to identify if target is reveal.js instead of vanilla html -->\n<xsl:variable name=\"b-reveal-build\" select=\"false()\" />\n\n<!-- Standard HTML builds start chunks from level 1. Other builds like epub -->\n<!-- may need a different value.                                            -->\n<xsl:variable name=\"chunk-heading-level\" select=\"1\"/>\n\n<!-- ############### -->\n<!-- Source Analysis -->\n<!-- ############### -->\n\n<!-- We check certain aspects of the source and record the results   -->\n<!-- in boolean ($b-has-*) variables or as particular nodes high up  -->\n<!-- in the structure ($document-root).  Scans here in -html should  -->\n<!-- help streamline the construction of the HTML page \"head\" by     -->\n<!-- computing properties that will be used in the \"head\" of every   -->\n<!-- page of every chunk. checked more than once. While technically  -->\n<!-- generally part of constructing the head, there is no real harm  -->\n<!-- in making these global variables.  Short, simple, and universal -->\n<!-- properties are determined in -common. These may duplicate       -->\n<!-- variables in disjoint conversions.                              -->\n\n<xsl:variable name=\"b-has-icon\"         select=\"boolean($document-root//icon)\"/>\n<xsl:variable name=\"b-has-webwork-reps\" select=\"boolean($document-root//webwork-reps)\"/>\n<xsl:variable name=\"b-has-myopenmath\"   select=\"boolean($document-root//myopenmath)\"/>\n<xsl:variable name=\"b-has-stack\"        select=\"boolean($document-root//exercise/stack)\"/>\n<xsl:variable name=\"b-has-program\"      select=\"boolean($document-root//program)\"/>\n<xsl:variable name=\"b-has-gdscript\"     select=\"boolean($document-root//program[@language='gdscript'])\"/>\n<xsl:variable name=\"b-has-sage\"         select=\"boolean($document-root//sage)\"/>\n<xsl:variable name=\"b-has-sfrac\"        select=\"boolean($document-root//m[contains(text(),'sfrac')] or $document-root//mrow[contains(text(),'sfrac')])\" />\n<xsl:variable name=\"b-has-geogebra\"     select=\"boolean($document-root//interactive[@platform='geogebra'])\"/>\n<xsl:variable name=\"b-has-mermaid\"      select=\"boolean($document-root//image[mermaid]|/image[mermaid])\"/>\n<!-- 2018-04-06:  jsxgraph deprecated -->\n<xsl:variable name=\"b-has-jsxgraph\"     select=\"boolean($document-root//jsxgraph)\"/>\n<!-- Plural \"annotations\" is a child of \"diagram\" -->\n<xsl:variable name=\"b-has-prefigure-annotations\" select=\"boolean($document-root//pf:prefigure/pf:diagram/pf:annotations)\"/>\n<xsl:variable name=\"b-dynamics-static-seed\" select=\"false()\"/>\n<!-- Every page has an index button, with a link to the index -->\n<!-- Here we assume there is at most one                      -->\n<xsl:variable name=\"the-index\"          select=\"($document-root//index)[1]\"/>\n\n<!-- ol markers                                                        -->\n<!-- Make a master list of all unique author-supplied ol marker styles -->\n<xsl:key name=\"marker-key\" match=\"ol|ol-marker\" use=\"@marker\"/> <!-- never used on node sets that contain mix of ol and ol-marker -->\n<xsl:variable name=\"ol-markers\">\n    <ol-markers>\n        <xsl:apply-templates select=\"$document-root//ol[@marker and count(. | key('marker-key', @marker)[1]) = 1]\" mode=\"ol-markers\"/>\n    </ol-markers>\n</xsl:variable>\n<!-- Following should be more efficient than 'select=\"boolean($document-root//ol[@marker])\"' -->\n<xsl:variable name=\"b-needs-custom-marker-css\" select=\"boolean(exsl:node-set($ol-markers)/ol-markers/ol-marker)\"/>\n\n\n<!-- #### EXPERIMENTAL #### -->\n<!-- We allow for the HTML conversion to chunk output, starting  -->\n<!-- from an arbitrary node.  $subtree-node needs context.       -->\n<xsl:param name=\"subtree\" select=\"''\"/>\n<xsl:variable name=\"b-subsetting\" select=\"not($subtree = '')\"/>\n<!-- #### EXPERIMENTAL #### -->\n\n\n<!-- ############## -->\n<!-- Entry Template -->\n<!-- ############## -->\n\n<!-- Deprecation warnings are universal analysis of source and parameters   -->\n<!-- There is always a \"document root\" directly under the pretext element,  -->\n<!-- and we process it with the chunking template called below              -->\n<!-- Note that \"docinfo\" is at the same level and not structural, so killed -->\n<!-- TODO: consider moving  manifests, etc to  the \"pretext\" template,      -->\n<!-- leaving this entry template for derived stylesheets to (a) test        -->\n<!-- source, and (b) set the root                                           -->\n<xsl:template match=\"/\">\n    <!-- temporary - while Hypothesis annotation is beta -->\n    <xsl:if test=\"$b-activate-hypothesis\">\n        <xsl:call-template name=\"banner-warning\">\n            <xsl:with-param name=\"warning\">Hypothes.is annotation is experimental</xsl:with-param>\n        </xsl:call-template>\n    </xsl:if>\n    <!--  -->\n    <xsl:apply-templates select=\"$original\" mode=\"generic-warnings\"/>\n    <xsl:apply-templates select=\"$original\" mode=\"element-deprecation-warnings\"/>\n    <xsl:apply-templates select=\"$original\" mode=\"parameter-deprecation-warnings\"/>\n    <!-- Usually no manifest is created -->\n    <xsl:call-template name=\"runestone-manifest\"/>\n    <!-- A structured Table of Contents for a React app approach -->\n    <xsl:call-template name=\"doc-manifest\"/>\n    <!-- build a search page (in development) -->\n    <xsl:if test=\"$has-native-search and not($b-portable-html)\">\n        <xsl:call-template name=\"search-page-construction\"/>\n    </xsl:if>\n    <!-- Optionally, build a SCORM manifest -->\n    <xsl:if test=\"$b-host-scorm\">\n        <xsl:call-template name=\"scorm-manifest\"/>\n    </xsl:if>\n    <!-- The main event                          -->\n    <!-- We process the enhanced source pointed  -->\n    <!-- to by $root at  /mathbook  or  /pretext -->\n    <xsl:apply-templates select=\"$root\"/>\n</xsl:template>\n\n\n<!-- We process structural nodes via chunking routine in xsl/pretext-common.xsl    -->\n<!-- This in turn calls specific modal templates defined elsewhere in this file     -->\n<!-- The xref-knowl templates run independently on content node of document tree    -->\n<xsl:template match=\"/mathbook|/pretext\">\n\n    <xsl:choose>\n        <!-- usually not working on a subset -->\n        <xsl:when test=\"not($b-subsetting)\">\n            <!-- Build the index-redirect-page, but not if doing a portable build -->\n            <xsl:if test=\"not($b-portable-html)\">\n                <xsl:call-template name=\"index-redirect-page\"/>\n            </xsl:if>\n            <xsl:apply-templates mode=\"chunking\" />\n        </xsl:when>\n        <!-- if subsetting, begin chunking at specified node -->\n        <!-- and do not build an \"index.html\" page           -->\n        <xsl:otherwise>\n            <!-- we compute the subset node while the context is the -->\n            <!-- tree produced by the -assembly stylesheet, and only -->\n            <!-- if actually requested                               -->\n            <xsl:variable name=\"subtree-node\" select=\"id($subtree)\"/>\n            <!-- this error-checking should be parked somewhere else -->\n            <!-- and maybe there is a fallback to full processing?   -->\n            <xsl:choose>\n                <xsl:when test=\"not($subtree-node)\">\n                    <xsl:message terminate=\"yes\">PTX:FATAL:  the @xml:id given as a subtree root (\"<xsl:value-of select=\"$subtree\"/>\") does not specify any element.  (Check spelling?)  Quitting...</xsl:message>\n                </xsl:when>\n                <xsl:when test=\"not($subtree-node[&STRUCTURAL-FILTER;])\">\n                    <xsl:message terminate=\"yes\">PTX:FATAL:  the element with the @xml:id given as a subtree root (\"<xsl:value-of select=\"$subtree\"/>\") is not division that can be chunked into HTML page(s).  Quitting...</xsl:message>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:variable name=\"current-level\">\n                        <!-- this should be successful having passed previous filter -->\n                        <xsl:apply-templates select=\"$subtree-node\" mode=\"level\"/>\n                    </xsl:variable>\n                    <!-- too deep to chunk into a page (or pages) -->\n                    <xsl:if test=\"$current-level > $chunk-level\">\n                        <xsl:message terminate=\"yes\">PTX:FATAL:  the element with @xml:id given as a subtree root (\"<xsl:value-of select=\"$subtree\"/>\") is only a partial HTML page at the current chunking level.  Quitting...</xsl:message>\n                    </xsl:if>\n                </xsl:otherwise>\n            </xsl:choose>\n            <!-- seems to now be a good place to start chunking -->\n            <xsl:apply-templates select=\"$subtree-node\" mode=\"chunking\" />\n        </xsl:otherwise>\n    </xsl:choose>\n    <!-- knowl-production -->\n    <!-- subsetting? don't bother (for now) -->\n    <!-- portable html does not get xref knowls either. -->\n    <xsl:if test=\"not($b-subsetting) and not($b-portable-html)\">\n        <xsl:apply-templates select=\".\" mode=\"make-xref-knowls\"/>\n    </xsl:if>\n    <!-- custom ol marker css production -->\n    <!-- A CDN cannot host these styles, since they are derived from the -->\n    <!-- source.  CDN builds get them inline instead, see \"css-common\".  -->\n    <xsl:if test=\"not($b-subsetting) and not($b-cdn-resources)\">\n        <xsl:call-template name=\"ol-marker-styles\"/>\n    </xsl:if>\n</xsl:template>\n\n<!-- However, some PTX document types do not have    -->\n<!-- universal conversion, so these default warnings -->\n<!-- should be overridden by supported conversions   -->\n<xsl:template match=\"letter\" mode=\"chunking\">\n    <xsl:message terminate=\"yes\">\n        <xsl:text>PTX:FATAL:  HTML conversion does not support the \"letter\" document type.  Quitting...</xsl:text>\n    </xsl:message>\n</xsl:template>\n\n<xsl:template match=\"memo\" mode=\"chunking\">\n    <xsl:message terminate=\"yes\">\n        <xsl:text>PTX:FATAL:  HTML conversion does not support the \"memo\" document type.  Quitting...</xsl:text>\n    </xsl:message>\n</xsl:template>\n\n<!-- We build a simple, instantaneous, redirection page based on the    -->\n<!-- publisher html/index-page/@ref option.  We write it first, so if   -->\n<!-- the deprecated scheme is in place then it will overwrite this one. -->\n<!-- See https://css-tricks.com/redirect-web-page/ for alternatives     -->\n<!-- NB: the use of the \"containing-filename\" template will require a   -->\n<!-- chunking level or else the template may go into infinite           -->\n<!-- recursion.  So we also protect against the chunking-level not      -->\n<!-- being set properly.                                                -->\n<xsl:template name=\"index-redirect-page\">\n    <!-- $html-index-page-entered-ref comes from the publisher variables -->\n    <!-- stylesheet.  It may be empty, signifying no election beyond     -->\n    <!-- the defaults, or it is a reference to some actual node with a   -->\n    <!-- matching @xml:id value.  We now need to see if it is a node     -->\n    <!-- that is a complete webpage at the current chunking level.       -->\n    <!--                                                                 -->\n    <!-- But first, we see if there is a coding error, due to            -->\n    <!-- the critical chunk level variable being overridden              -->\n    <xsl:if test=\"$chunk-level = ''\">\n        <xsl:message>PTX:BUG:    the $chunk-level variable has been left undefined&#xa;due to a change in a stylesheet that imports the HTML conversion&#xa;and the computation of an index page may fail spectacularly (infinite recursion?)\"</xsl:message>\n    </xsl:if>\n    <xsl:variable name=\"sanitized-ref\">\n        <xsl:choose>\n            <!-- no publisher file entry implies empty entered ref -->\n            <xsl:when test=\"$html-index-page-entered-ref = ''\"/>\n            <!-- now we have a node, is it the top of a page? -->\n            <xsl:otherwise>\n                <!-- true/false values if node creates a web page -->\n                <xsl:variable name=\"is-intermediate\">\n                    <xsl:apply-templates select=\"id($html-index-page-entered-ref)\" mode=\"is-intermediate\"/>\n                </xsl:variable>\n                <xsl:variable name=\"is-chunk\">\n                    <xsl:apply-templates select=\"id($html-index-page-entered-ref)\" mode=\"is-chunk\"/>\n                </xsl:variable>\n                <xsl:choose>\n                    <!-- really is a web-page -->\n                    <xsl:when test=\"($is-intermediate = 'true') or ($is-chunk = 'true')\">\n                        <xsl:value-of select=\"$html-index-page-entered-ref\"/>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:message>PTX:FALLBACK:   the requested HTML index page cannot be constructed since \"<xsl:value-of select=\"$html-index-page-entered-ref\"/>\" is not a complete web page at the current chunking level (level <xsl:value-of select=\"$chunk-level\"/>).  Defaults will be used instead</xsl:message>\n                        <xsl:text/>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- Now have a good @xml:id for an extant webpage, or an empty -->\n    <!-- string signals we need to choose a sensible default. The   -->\n    <!-- default is the \"frontmatter\" page, if possible, otherwise  -->\n    <!-- the root page. The variable $html-index-page will be the   -->\n    <!-- full name (*.html) of a page guaranteed to be built by     -->\n    <!-- the chunking routines.                                     -->\n    <xsl:variable name=\"html-index-page\">\n        <xsl:choose>\n            <!-- publisher's choice survives -->\n            <xsl:when test=\"not($sanitized-ref = '')\">\n                <xsl:apply-templates select=\"id($sanitized-ref)\" mode=\"containing-filename\"/>\n            </xsl:when>\n            <!-- now need to create defaults                        -->\n            <!-- the level of the frontmatter is a bit conflicted   -->\n            <!-- but it is a chunk iff there is any chunking at all -->\n            <xsl:when test=\"$document-root/frontmatter and ($chunk-level &gt; 0)\">\n                <xsl:apply-templates select=\"$document-root/frontmatter\" mode=\"containing-filename\"/>\n            </xsl:when>\n            <!-- absolute last option is $document-root, *always* a webpage -->\n            <xsl:otherwise>\n                <xsl:apply-templates select=\"$document-root\" mode=\"containing-filename\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- build a very simple  index.html  page pointing at  $html-index-page -->\n    <!-- This is the one place we insert a (timestamped) blurb, since the    -->\n    <!-- file is already exceptional and one-off                             -->\n    <exsl:document href=\"index.html\" method=\"html\" indent=\"yes\" encoding=\"UTF-8\" doctype-system=\"about:legacy-compat\">\n        <html>\n            <xsl:text>&#xa;</xsl:text>\n            <xsl:call-template name=\"converter-blurb-html\"/>\n            <!-- Open Graph Protocol only in \"meta\" elements, within \"head\" -->\n            <head xmlns:og=\"http://ogp.me/ns#\" xmlns:book=\"https://ogp.me/ns/book#\">\n                <meta http-equiv=\"refresh\" content=\"0; URL='{$html-index-page}'\" />\n                <!-- Add a canonical link here, in generic build case? -->\n                <!-- more \"meta\" elements for discovery -->\n                <xsl:call-template name=\"social-meta-info\"/>\n            </head>\n            <!-- body is non-existent, i.e. empty -->\n            <body/>\n        </html>\n    </exsl:document>\n</xsl:template>\n\n<!-- ################ -->\n<!-- Structural Nodes -->\n<!-- ################ -->\n\n<!-- Read the code and documentation for \"chunking\" in      -->\n<!-- xsl/pretext-common.xsl  This will help explain         -->\n<!-- document structure (not XML structure).                -->\n<!--                                                        -->\n<!-- With an implementation of a file-wrapping routine,     -->\n<!-- a typical use is to                                    -->\n<!--                                                        -->\n<!--   (a) apply a default template to the structural       -->\n<!--       node for a complete (chunk'ed) node              -->\n<!--                                                        -->\n<!--   (b) apply a modal template to the structural         -->\n<!--       node for a summary (intermediate) node           -->\n<!--                                                        -->\n<!-- The \"file-wrap\" routine should accept a $content       -->\n<!-- parameter holding the contents of the body of the page -->\n\n<!-- The HTML conversion (and hence its derivatives) opts in -->\n<!-- to \"division companion\" chunks: introduction, conclusion, -->\n<!-- objectives, outcomes of a division realized as a summary -->\n<!-- page become pages themselves (see pretext-common.xsl)    -->\n<xsl:variable name=\"b-division-companion-chunks\" select=\"true()\"/>\n\n<!-- A complete page for a structural division -->\n<xsl:template match=\"&STRUCTURAL;\" mode=\"chunk\">\n    <xsl:apply-templates select=\".\" mode=\"file-wrap\">\n        <xsl:with-param name=\"content\">\n            <xsl:apply-templates select=\".\">\n                 <xsl:with-param name=\"heading-level\" select=\"$chunk-heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:with-param>\n        <!-- Set b-has-printout to true if the structural node is or contains a  -->\n        <!-- worksheet or handout, or a PROJECT-LIKE acting as its own printout. -->\n        <xsl:with-param name=\"b-has-printout\" select=\"descendant-or-self::worksheet or descendant-or-self::handout or descendant::*[&PROJECT-FILTER;][not(ancestor::worksheet|ancestor::handout)][@workspace|.//@workspace]\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- A summary page for a structural division -->\n<!-- Processing of a structural node realized as an           -->\n<!-- intermediate/summary node.                               -->\n<xsl:template match=\"&STRUCTURAL;\" mode=\"intermediate\">\n    <xsl:apply-templates select=\".\" mode=\"file-wrap\">\n        <xsl:with-param name=\"content\">\n            <!-- location info for debugging efforts -->\n            <xsl:apply-templates select=\".\" mode=\"debug-location\" />\n            <!-- Heading, div for this structural subdivision -->\n            <section class=\"{local-name(.)}\">\n                <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n                <xsl:apply-templates select=\".\" mode=\"section-heading\">\n                    <xsl:with-param name=\"heading-level\" select=\"$chunk-heading-level\"/>\n                </xsl:apply-templates>\n                <xsl:apply-templates select=\".\" mode=\"author-byline\"/>\n                <!-- Special case when building page for frontmatter without a titlepage -->\n                <xsl:if test=\"self::frontmatter[not(titlepage)]\">\n                    <xsl:call-template name=\"frontmatter-title\" />\n                </xsl:if>\n                <xsl:apply-templates select=\"titlepage|abstract\">\n                    <xsl:with-param name=\"heading-level\" select=\"$chunk-heading-level + 1\"/>\n                </xsl:apply-templates>\n                <!-- Links to subsidiary divisions, as a group of button/hyperlinks -->\n                <nav class=\"summary-links\">\n                    <ul>\n                        <xsl:apply-templates select=\"*\" mode=\"summary-nav\" />\n                    </ul>\n                </nav>\n                <!-- Insert permalink -->\n                <xsl:apply-templates select=\".\" mode=\"permalink\"/>\n            </section>\n        </xsl:with-param>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Navigation -->\n<!-- Structural nodes on a summary page  -->\n<!-- become attractive button/hyperlinks -->\n<xsl:template match=\"&STRUCTURAL;\" mode=\"summary-nav\">\n    <xsl:variable name=\"num\">\n        <xsl:apply-templates select=\".\" mode=\"number\" />\n    </xsl:variable>\n    <xsl:variable name=\"url\">\n        <xsl:apply-templates select=\".\" mode=\"url\" />\n    </xsl:variable>\n    <li>\n        <a href=\"{$url}\" class=\"internal\">\n            <!-- do not include an empty codenumber span -->\n            <xsl:if test=\"not($num = '')\">\n                <span class=\"codenumber\">\n                    <xsl:value-of select=\"$num\" />\n                    <xsl:apply-templates select=\".\" mode=\"division-number-separator\"/>\n                </span>\n                <xsl:text> </xsl:text>\n            </xsl:if>\n            <!-- title is required on structural elements -->\n            <span class=\"title\">\n                <xsl:apply-templates select=\".\" mode=\"title-short\" />\n            </span>\n        </a>\n    </li>\n</xsl:template>\n\n<!-- Division companions become links, like the structural children; -->\n<!-- document order places an \"introduction\" before the subdivision -->\n<!-- links and a \"conclusion\" after, with no extra machinery        -->\n<xsl:template match=\"&DIVISION-COMPANION;\" mode=\"summary-nav\">\n    <!-- a link only when realized as a page (a conversion that -->\n    <!-- has not opted in renders no link, and no bare content) -->\n    <xsl:variable name=\"chunk\">\n        <xsl:apply-templates select=\".\" mode=\"is-chunk\"/>\n    </xsl:variable>\n    <xsl:if test=\"$chunk = 'true'\">\n        <xsl:variable name=\"url\">\n            <xsl:apply-templates select=\".\" mode=\"url\" />\n        </xsl:variable>\n        <li>\n            <a href=\"{$url}\" class=\"internal\">\n                <span class=\"title\">\n                    <xsl:apply-templates select=\".\" mode=\"division-companion-text\"/>\n                </span>\n            </a>\n        </li>\n    </xsl:if>\n</xsl:template>\n\n<!-- everything else on a summary page gets dropped -->\n<xsl:template match=\"*\" mode=\"summary-nav\" />\n\n<!-- Text for links (and ToC entries) to a division companion page.  -->\n<!-- \"introduction\"/\"conclusion\": the localized type-name only (an  -->\n<!-- authored title is silently ignored, pending deprecation).      -->\n<!-- \"objectives\"/\"outcomes\": the localized type-name, plus the     -->\n<!-- title when authored, mirroring the inline block headings.      -->\n<xsl:template match=\"introduction|conclusion\" mode=\"division-companion-text\">\n    <xsl:apply-templates select=\".\" mode=\"type-name\"/>\n</xsl:template>\n\n<xsl:template match=\"objectives|outcomes\" mode=\"division-companion-text\">\n    <xsl:apply-templates select=\".\" mode=\"type-name\"/>\n    <xsl:if test=\"title\">\n        <xsl:text>: </xsl:text>\n        <xsl:apply-templates select=\".\" mode=\"title-short\"/>\n    </xsl:if>\n</xsl:template>\n\n<!-- A division companion realized as its own page -->\n<xsl:template match=\"&DIVISION-COMPANION;\" mode=\"chunk\">\n    <xsl:apply-templates select=\".\" mode=\"file-wrap\">\n        <xsl:with-param name=\"content\">\n            <xsl:apply-templates select=\".\" mode=\"division-companion-page\"/>\n        </xsl:with-param>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Page content: a manufactured heading (the link text), then the -->\n<!-- children, much as the inline realization would present them    -->\n<xsl:template match=\"introduction|conclusion\" mode=\"division-companion-page\">\n    <xsl:text>&#xa;</xsl:text>\n    <section>\n        <xsl:attribute name=\"class\">\n            <xsl:value-of select=\"local-name(.)\" />\n        </xsl:attribute>\n        <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n        <xsl:apply-templates select=\".\" mode=\"heading-generic\">\n            <xsl:with-param name=\"heading-level\" select=\"$chunk-heading-level\"/>\n            <xsl:with-param name=\"heading-title\">\n                <xsl:apply-templates select=\".\" mode=\"division-companion-text\"/>\n            </xsl:with-param>\n        </xsl:apply-templates>\n        <xsl:apply-templates select=\"*\">\n            <xsl:with-param name=\"heading-level\" select=\"$chunk-heading-level + 1\"/>\n        </xsl:apply-templates>\n    </section>\n</xsl:template>\n\n<!-- Page content: the ordinary block realization, whose heading -->\n<!-- already displays the type-name and any authored title       -->\n<xsl:template match=\"objectives|outcomes\" mode=\"division-companion-page\">\n    <xsl:apply-templates select=\".\">\n        <xsl:with-param name=\"heading-level\" select=\"$chunk-heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Default template for content of a structural  -->\n<!-- division, which could be an entire page's     -->\n<!-- worth, or just a subdivision within a page    -->\n<!-- Increment $heading-level via this template    -->\n<!-- We use a modal template, so it can be called  -->\n<!-- one more time for a printout to make          -->\n<!-- printable standalone versions.                -->\n<xsl:template match=\"&STRUCTURAL;\">\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:apply-templates select=\".\" mode=\"structural-division-content\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- This is where a division becomes an HTML \"section\".  It may -->\n<!-- be the content wrapped as an entire HTML page, or it may be -->\n<!-- a subdivision that is just part of a page.                  -->\n<xsl:template match=\"&STRUCTURAL;\" mode=\"structural-division-content\">\n    <xsl:param name=\"heading-level\"/>\n\n    <!-- Specialized divisions \"exercises\" and \"worksheet\" can be used   -->\n    <!-- as vehicles for collections of \"exercise\" as group work modules -->\n    <!-- NB: this assumes that the \"exercises\" is an entire page, so     -->\n    <!-- checks if it is a subdivision of a \"chapter\" (or \"appendix\").   -->\n    <!-- In other words, these divisions must be Runestone \"subchapter\". -->\n\n    <xsl:variable name=\"b-is-groupwork\"\n                  select=\"$b-host-runestone and (@groupwork = 'yes') and (self::worksheet or self::exercises) and (parent::chapter or parent::appendix)\"/>\n\n    <!-- location info for debugging efforts -->\n    <xsl:apply-templates select=\".\" mode=\"debug-location\" />\n    <!-- Heading, div for this structural subdivision -->\n    <!-- newlines inserted to encourage formatted output -->\n    <xsl:text>&#xa;</xsl:text>\n    <section>\n        <xsl:attribute name=\"class\">\n            <xsl:value-of select=\"local-name(.)\"/>\n            <!-- mark \"section\" for potential styling, etc -->\n            <xsl:if test=\"$b-is-groupwork\">\n                <xsl:text> groupwork</xsl:text>\n            </xsl:if>\n        </xsl:attribute>\n        <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n        <!-- page-margins-attribute will be empty unless in a printout division -->\n        <xsl:apply-templates select=\".\" mode=\"page-margins-attribute\"/>\n        <!-- page-header-footer-attributes; empty except in a printout division -->\n        <xsl:apply-templates select=\".\" mode=\"page-header-footer-attributes\"/>\n        <xsl:apply-templates select=\".\" mode=\"section-heading\">\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n        <!-- Special case when building page for frontmatter without a titlepage -->\n        <xsl:if test=\"self::frontmatter[not(titlepage)]\">\n            <xsl:call-template name=\"frontmatter-title\"/>\n        </xsl:if>\n        <xsl:apply-templates select=\".\" mode=\"author-byline\"/>\n        <!-- If there is watermark text, we print it here in an assistive p -->\n        <!-- so that it is the first thing read by a screen-reader user.    -->\n        <xsl:if test=\"$b-watermark and $heading-level = $chunk-heading-level\">\n            <p class=\"watermark\">\n                <xsl:text>Watermark text: </xsl:text>\n                <xsl:value-of select=\"$watermark-text\"/>\n                <xsl:text></xsl:text>\n            </p>\n        </xsl:if>\n        <!-- After the heading, and before the actual guts, we      -->\n        <!-- sometimes annotate with the source                     -->\n        <!-- of the current element.  This calls a stub, unless     -->\n        <!-- a separate stylesheet is used to define the template,  -->\n        <!-- and the method is defined there.                       -->\n        <xsl:apply-templates select=\".\" mode=\"view-source-widget\"/>\n\n        <!-- The \"solutions\" modal templates increment $heading-level  -->\n        <!-- themselves, so bypassing the increment here avoids a skip -->\n        <!-- for both a solutions page and an inline \"solutions\".      -->\n        <xsl:variable name=\"next-level\">\n            <xsl:choose>\n                <xsl:when test=\"self::solutions\">\n                    <xsl:value-of select=\"$heading-level\"/>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:value-of select=\"$heading-level + 1\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:variable>\n\n        <!-- Most divisions are a simple list of elements to be       -->\n        <!-- processed in document order, once we handle metadata     -->\n        <!-- properly, and also kill it so it is not caught up here.  -->\n        <!-- So the \"inner-content\" template just processes children  -->\n        <!-- in document order.  Exceptions are:                      -->\n        <!--   \"solutions\": no children, so built via a constructive  -->\n        <!--                modal template                            -->\n        <!--   \"glossary\": is presumed to have a very specific        -->\n        <!--               structure which requires elements          -->\n        <!--               at the division level                      -->\n\n        <xsl:apply-templates select=\".\" mode=\"structural-division-inner-content\">\n            <xsl:with-param name=\"heading-level\" select=\"$next-level\"/>\n        </xsl:apply-templates>\n\n        <!-- Groupwork submission items are not emitted here.  They belong   -->\n        <!-- above the Runestone progress indicator, which the various        -->\n        <!-- \"structural-division-inner-content\" templates emit as their last -->\n        <!-- act, so each of those emits the submission items just before it. -->\n\n        <!-- Include permalink for the section as last child -->\n        <xsl:apply-templates select=\".\" mode=\"permalink\"/>\n    <xsl:text>&#xa;</xsl:text>\n    </section>\n</xsl:template>\n\n<!-- A glossary has a headnote, followed by a sequence  -->\n<!-- of glossary items ('gi\").  This could be the place -->\n<!-- to get fancy and segment the entries with spacing  -->\n<!-- by letter, or similar. Terminal (as a specialized  -->\n<!-- division) and the  $heading-level  affects nothing -->\n<xsl:template match=\"glossary\" mode=\"structural-division-inner-content\">\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:apply-templates select=\"headnote\"/>\n    <dl class=\"glossary\">\n        <xsl:apply-templates select=\"gi\"/>\n    </dl>\n</xsl:template>\n\n<!-- A \"solutions\" specialized division does not have any children -->\n<!-- at all, it gets built by mining content from other places     -->\n<xsl:template match=\"solutions\" mode=\"structural-division-inner-content\">\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:apply-templates select=\".\" mode=\"solutions\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- This is identical to the default \"structural-division-inner-content\" -->\n<!-- template just below, excepting there are modifications for Runestone -->\n<!-- to accomodate timed exams and group work.                            -->\n<xsl:template match=\"exercises\" mode=\"structural-division-inner-content\">\n    <xsl:param name=\"heading-level\"/>\n\n    <!-- Similar to variable above, except we know this is an \"exercises\" -->\n    <xsl:variable name=\"b-is-groupwork\"\n              select=\"$b-host-runestone and (@groupwork = 'yes') and (parent::chapter or parent::appendix)\"/>\n\n    <xsl:variable name=\"the-exercises\">\n        <xsl:apply-templates select=\"*\">\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n\n    <xsl:choose>\n        <xsl:when test=\"@time-limit and $b-is-groupwork\">\n            <xsl:message>PTX:ERROR:   an &quot;exercises&quot; division cannot simultaneously be a timed exam AND group work</xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\"/>\n        </xsl:when>\n        <xsl:when test=\"$b-is-groupwork\">\n            <!-- the actual list of exercises -->\n            <xsl:copy-of select=\"$the-exercises\"/>\n            <!-- and the group selection and submission items -->\n            <xsl:apply-templates select=\".\" mode=\"runestone-groupwork\"/>\n            <!-- No progress indicator in this case -->\n        </xsl:when>\n        <!-- some extra wrapping for timed exercises      -->\n        <!-- so we pass the $the-exercises as a parameter -->\n        <!-- presence of @time-limit is the signal        -->\n        <xsl:when test=\"@time-limit\">\n            <xsl:apply-templates select=\".\" mode=\"runestone-timed-exam\">\n                <xsl:with-param name=\"the-exercises\" select=\"$the-exercises\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- the actual list of exercises -->\n            <xsl:copy-of select=\"$the-exercises\"/>\n            <!-- only at \"section\" level. only when building for a Runestone server -->\n            <xsl:apply-templates select=\".\" mode=\"runestone-progress-indicator\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Only &STRUCTURAL; elements will pass through here, but we -->\n<!-- can't limit the match (without explicit exclusions), this -->\n<!-- is the default.  Which is to just apply templates to      -->\n<!-- elements within the division. Optional: add RS progress.  -->\n<xsl:template match=\"*\" mode=\"structural-division-inner-content\">\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:apply-templates select=\"*\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n    <!-- A \"worksheet\" electing group work arrives here, and its submission  -->\n    <!-- items go above the progress indicator: Runestone attaches the \"mark -->\n    <!-- as completed\" control to that indicator, and a reader chooses their -->\n    <!-- group before declaring the page done, not after.                    -->\n    <xsl:if test=\"$b-host-runestone and (@groupwork = 'yes') and (self::worksheet or self::exercises) and (parent::chapter or parent::appendix)\">\n        <xsl:apply-templates select=\".\" mode=\"runestone-groupwork\"/>\n    </xsl:if>\n    <!-- only at \"section\" level. only when building for a Runestone server -->\n    <xsl:apply-templates select=\".\" mode=\"runestone-progress-indicator\"/>\n</xsl:template>\n\n\n<!-- ############### -->\n<!-- Bits and Pieces -->\n<!-- ############### -->\n\n<!-- Heading for Document Nodes -->\n<!-- Every document node goes the same way, a    -->\n<!-- heading followed by its subsidiary elements -->\n<!-- hit with templates.  This is the heading.   -->\n<!-- Only \"chapter\" ever gets shown generically  -->\n<!-- Subdivisions have titles, or default titles -->\n<xsl:template match=\"*\" mode=\"section-heading\">\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:variable name=\"html-heading\">\n        <xsl:apply-templates select=\".\" mode=\"html-heading\">\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <!-- newline inserted to encourage formatted output -->\n    <xsl:text>&#xa;</xsl:text>\n    <xsl:element name=\"{$html-heading}\">\n        <xsl:attribute name=\"class\">\n            <xsl:choose>\n                <xsl:when test=\"(self::chapter or self::appendix or self::solutions/parent::backmatter) and ($numbering-maxlevel > 0)\">\n                    <xsl:text>heading</xsl:text>\n                </xsl:when>\n                <!-- hide \"Chapter\" when numbers are killed -->\n                <xsl:otherwise>\n                    <xsl:text>heading hide-type</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:attribute>\n        <xsl:apply-templates select=\".\" mode=\"heading-content\" />\n    </xsl:element>\n</xsl:template>\n\n<!-- Add an author's names, if present   -->\n<!-- TODO: make match more restrictive?  -->\n<xsl:template match=\"&STRUCTURAL;\" mode=\"author-byline\">\n    <xsl:if test=\"author\">\n        <p class=\"byline\">\n            <xsl:apply-templates select=\"author\" mode=\"name-list\"/>\n        </p>\n    </xsl:if>\n</xsl:template>\n\n<!-- The frontmatter has its own style -->\n<xsl:template match=\"frontmatter\" mode=\"section-heading\" />\n\n<!-- Fixed header for the backmatter contents.      -->\n<!-- We generally will hide this for sighted users. -->\n<xsl:template match=\"backmatter\" mode=\"section-heading\">\n    <xsl:if test=\"not($b-is-single-page)\">\n        <xsl:variable name=\"html-heading\">\n            <xsl:apply-templates select=\".\" mode=\"html-heading\">\n                <xsl:with-param name=\"heading-level\" select=\"$chunk-heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:variable>\n        <xsl:element name=\"{$html-heading}\">\n            <xsl:attribute name=\"class\">heading ptx-backmatter-heading</xsl:attribute>\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'backmatter'\"/>\n            </xsl:apply-templates>\n        </xsl:element>\n    </xsl:if>\n</xsl:template>\n\n<!-- A book or article is the top level, using the title would be -->\n<!-- duplicative of the banner. Instead, the page-specific header -->\n<!-- announces that this is the table of contents unless build is -->\n<!-- a single page.                                               -->\n<!-- We generally will hide this for sighted users.               -->\n<xsl:template match=\"book|article\" mode=\"section-heading\">\n    <xsl:if test=\"not($b-is-single-page)\">\n        <xsl:variable name=\"html-heading\">\n            <xsl:apply-templates select=\".\" mode=\"html-heading\">\n                <xsl:with-param name=\"heading-level\" select=\"$chunk-heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:variable>\n        <xsl:element name=\"{$html-heading}\">\n            <xsl:attribute name=\"class\">heading ptx-toc-heading</xsl:attribute>\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'toc'\"/>\n            </xsl:apply-templates>\n        </xsl:element>\n    </xsl:if>\n</xsl:template>\n\n<!-- An abstract needs structure, and an ID for a -->\n<!-- link out of the ToC sidebar for an article   -->\n<xsl:template match=\"abstract\">\n    <div class=\"abstract\">\n        <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n        <!-- title or heading?  We go with a default title, which will -->\n        <!-- be localized.  Then ban an author-provided title in the   -->\n        <!-- schema.  This allows for reasonable behavior in a ToC     -->\n        <!-- sidebar.  (This is a non-issue for LaTeX, where a good    -->\n        <!-- \"abstract\" environment exists.)                           -->\n        <span class=\"title\">\n            <xsl:apply-templates select=\".\" mode=\"title-full\"/>\n        </span>\n        <xsl:apply-templates select=\"*\"/>\n        <!-- Display keywords.  Note: the placement of this here works for  -->\n        <!-- articles that have an abstract.  Books (no abstract) will put  -->\n        <!-- their keywords in the colophon.                                -->\n        <xsl:apply-templates select=\"$bibinfo/keywords\" />\n        <!-- Display general support (funding) statement -->\n        <xsl:apply-templates select=\"$bibinfo/support\" />\n    </div>\n</xsl:template>\n\n<!-- ######## -->\n<!-- Headings -->\n<!-- ######## -->\n\n<!-- Both environments and sections have a \"type,\"         -->\n<!-- a \"codenumber,\" and a \"title.\"  We format these       -->\n<!-- consistently here with a modal template.  We can hide -->\n<!-- components with classes on the enclosing \"heading\"    -->\n<xsl:template match=\"*\" mode=\"heading-content\">\n    <span class=\"type\">\n        <xsl:apply-templates select=\".\" mode=\"type-name\" />\n    </span>\n    <xsl:call-template name=\"space-styled\"/>\n    <span class=\"codenumber\">\n        <xsl:apply-templates select=\".\" mode=\"number\" />\n        <xsl:apply-templates select=\".\" mode=\"division-number-separator\"/>\n    </span>\n    <xsl:call-template name=\"space-styled\"/>\n    <span class=\"title\">\n        <xsl:apply-templates select=\".\" mode=\"title-full\" />\n    </span>\n</xsl:template>\n\n<!-- Specialized Divisions -->\n<!-- A specialized division may inherit a number from its parent  -->\n<!-- (\"exercises\"), or it may not ever even get a number          -->\n<!-- (backmatter/references is a singleton).  Whether or not to   -->\n<!-- *display* a number at birth is therefore more complicated    -->\n<!-- than *having* a number or not.                               -->\n<!-- NB: We sneak in links for standalone versions of printouts.  -->\n<xsl:template match=\"exercises|solutions|glossary|references|worksheet|handout|reading-questions\" mode=\"heading-content\">\n    <span class=\"type\">\n        <xsl:apply-templates select=\".\" mode=\"type-name\"/>\n    </span>\n    <xsl:call-template name=\"space-styled\"/>\n    <!-- be selective about displaying numbers at birth-->\n    <xsl:variable name=\"is-numbered\">\n        <xsl:apply-templates select=\".\" mode=\"is-specialized-own-number\"/>\n    </xsl:variable>\n    <span class=\"codenumber\">\n        <xsl:if test=\"($is-numbered = 'true')\">\n            <xsl:apply-templates select=\".\" mode=\"number\"/>\n        </xsl:if>\n    </span>\n    <xsl:call-template name=\"space-styled\"/>\n    <span class=\"title\">\n        <xsl:apply-templates select=\".\" mode=\"title-full\" />\n    </span>\n    <!-- add print preview button for printouts -->\n    <xsl:if test=\"(&PRINTOUT-FILTER;)\">\n        <xsl:apply-templates select=\".\" mode=\"standalone-printout-links\"/>\n    </xsl:if>\n</xsl:template>\n\n<!-- Add print preview button for printouts                          -->\n<!-- As of 2025-12-29, we no longer create a separate html page for  -->\n<!-- print previews.  A simple button with printer icon that reloads -->\n<!-- the page with a url parameter that tells javascript to switch   -->\n<!-- to printout css and format all the pages and workspace.         -->\n<xsl:template match=\"&PRINTOUT;|&PROJECT-LIKE;\" mode=\"standalone-printout-links\">\n    <xsl:variable name=\"printout-id\">\n        <xsl:apply-templates select=\".\" mode=\"html-id\"/>\n    </xsl:variable>\n    <xsl:variable name=\"print-preview-text\">\n        <xsl:apply-templates select=\".\" mode=\"type-name\">\n            <xsl:with-param name=\"string-id\" select=\"'print-preview'\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <div class=\"print-links\">\n        <a href=\"?printpreview={$printout-id}\" class=\"print-link\" title=\"{$print-preview-text}\">\n            <xsl:call-template name=\"insert-symbol\">\n                <xsl:with-param name=\"name\" select=\"'print'\"/>\n            </xsl:call-template>\n        </a>\n    </div>\n</xsl:template>\n\n<!-- Recursively finds enclosing structural node -->\n<!-- and reports if it has an xml:id on it       -->\n<!-- Note: from mode=\"containing-filename\", can we return a node-set? -->\n<xsl:template match=\"*\" mode=\"has-id-on-enclosure\">\n    <xsl:variable name=\"intermediate\"><xsl:apply-templates select=\".\" mode=\"is-intermediate\" /></xsl:variable>\n    <xsl:variable name=\"chunk\"><xsl:apply-templates select=\".\" mode=\"is-chunk\" /></xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$intermediate='true' or $chunk='true'\">\n            <!-- found it, is there an xml:id? -->\n            <xsl:choose>\n                <xsl:when test=\"@xml:id\">\n                    <xsl:value-of select=\"true()\" />\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:value-of select=\"false()\" />\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\"..\" mode=\"has-id-on-enclosure\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- ####################### -->\n<!-- Front Matter Components -->\n<!-- ####################### -->\n\n<!-- Title Page -->\n<!-- A frontmatter has no title, so we reproduce the       -->\n<!-- title of the work (book or article) here              -->\n<!-- NB: this could done with a \"section-heading\" template?-->\n<!-- Other divisions (eg, colophon, preface) will follow   -->\n<!-- This is all within a .frontmatter class for CSS       -->\n<xsl:template match=\"titlepage\">\n    <!-- Use a context-free template to generate -->\n    <!-- an \"h1\" title/subtitle heading          -->\n    <xsl:call-template name=\"frontmatter-title\"/>\n    <!-- text generator for title page items from \"bibinfo\" -->\n    <xsl:apply-templates select=\"$document-root/frontmatter/titlepage/titlepage-items\" />\n</xsl:template>\n\n<xsl:template match=\"titlepage-items\">\n    <!-- Put authors and editors first, in document order -->\n    <xsl:apply-templates select=\"$bibinfo/author|$bibinfo/editor\" mode=\"full-info\"/>\n    <!-- Followed by \"contributors\" authored as credit (which have titles) -->\n    <xsl:apply-templates select=\"$bibinfo/credit[title]\" />\n    <!-- and finally date -->\n    <xsl:apply-templates select=\"$bibinfo/date\" />\n</xsl:template>\n\n<!-- Title to put on frontmatter page.  This is a context-free named template      -->\n<!-- since an author's source may not have a frontmatter/titlepage element,        -->\n<!-- yet we still want to grap the title (and subtitle) for use on pages           -->\n<!-- generated by a \"frontmatter\" element (including, e.g., an intermediate page). -->\n<xsl:template name=\"frontmatter-title\">\n    <xsl:variable name=\"b-has-subtitle\" select=\"$document-root/subtitle\"/>\n    <!-- heading level should match default chunk heading level -->\n    <xsl:variable name=\"html-heading\">\n        <xsl:apply-templates select=\".\" mode=\"html-heading\">\n            <xsl:with-param name=\"heading-level\" select=\"$chunk-heading-level\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <xsl:element name=\"{$html-heading}\">\n        <xsl:attribute name=\"class\">heading</xsl:attribute>\n        <span class=\"title\">\n            <xsl:apply-templates select=\"$document-root\" mode=\"title-full\" />\n        </span>\n        <xsl:if test=\"$b-has-subtitle\">\n            <span class=\"subtitle\">\n                <xsl:apply-templates select=\"$document-root\" mode=\"subtitle\" />\n            </span>\n        </xsl:if>\n    </xsl:element>\n</xsl:template>\n\n<!-- A \"credit\" required \"title\" followed by an author (or several)    -->\n<!-- CSS should give lesser prominence to these (versus \"full\" author) -->\n<xsl:template match=\"bibinfo/credit[title]\">\n    <div class=\"credit\">\n        <div class=\"title\">\n            <xsl:apply-templates select=\".\" mode=\"title-full\"/>\n        </div>\n        <xsl:apply-templates select=\"author\" mode=\"full-info\" />\n    </div>\n</xsl:template>\n\n<!-- The time element has content that is \"human readable\" time -->\n<xsl:template match=\"bibinfo/date\">\n    <div class=\"date\">\n        <xsl:apply-templates/>\n    </div>\n</xsl:template>\n\n<!-- Authors, Editors, Creditors -->\n\n<!-- Authors and editors with affiliations (eg, on title page) -->\n<!-- CSS does not distinguish authors from editors             -->\n<xsl:template match=\"author|editor\" mode=\"full-info\">\n    <div class=\"author\">\n        <div class=\"author-name\">\n            <xsl:apply-templates select=\"personname\" />\n            <xsl:if test=\"self::editor\">\n                <xsl:text>, </xsl:text>\n                <xsl:apply-templates select=\".\" mode=\"type-name\" />\n            </xsl:if>\n        </div>\n        <div class=\"author-info\">\n            <xsl:if test=\"affiliation\">\n                <xsl:apply-templates select=\"affiliation\"/>\n                <xsl:if test=\"affiliation/following-sibling::*\">\n                    <br />\n                </xsl:if>\n            </xsl:if>\n            <xsl:if test=\"email\">\n                <xsl:apply-templates select=\"email\" />\n                <xsl:if test=\"email/following-sibling::*\">\n                    <br />\n                </xsl:if>\n            </xsl:if>\n            <xsl:if test=\"support\">\n                <xsl:apply-templates select=\"support\" />\n                <xsl:if test=\"support/following-sibling::*\">\n                    <br />\n                </xsl:if>\n            </xsl:if>\n        </div>\n    </div>\n</xsl:template>\n\n<xsl:template match=\"affiliation\">\n    <xsl:if test=\"position\">\n        <xsl:apply-templates select=\"position\" />\n        <xsl:if test=\"position/following-sibling::*\">\n            <br />\n        </xsl:if>\n    </xsl:if>\n    <xsl:if test=\"department\">\n        <xsl:apply-templates select=\"department\" />\n        <xsl:if test=\"department/following-sibling::*\">\n            <br />\n        </xsl:if>\n    </xsl:if>\n    <xsl:if test=\"institution\">\n        <xsl:apply-templates select=\"institution\" />\n        <xsl:if test=\"institution/following-sibling::*\">\n            <br />\n        </xsl:if>\n    </xsl:if>\n    <xsl:if test=\"location\">\n        <xsl:apply-templates select=\"location\" />\n        <xsl:if test=\"location/following-sibling::*\">\n            <br />\n        </xsl:if>\n    </xsl:if>\n</xsl:template>\n\n<!-- Departments and Institutions are free-form, or sequences of lines -->\n<xsl:template match=\"position|department|institution|location\">\n    <xsl:apply-templates/>\n</xsl:template>\n\n<xsl:template match=\"position[line]|department[line]|institution[line]|location[line]\">\n    <xsl:apply-templates select=\"line\" />\n</xsl:template>\n\n<!-- Keywords -->\n<xsl:template match=\"bibinfo/keywords\">\n    <div class=\"keywords\">\n        <span class=\"title\">\n            <xsl:apply-templates select=\".\" mode=\"title-full\"/>\n        </span>\n        <xsl:apply-templates select=\"*\" />\n        <xsl:text>.</xsl:text>\n    </div>\n</xsl:template>\n\n<!-- General support (not for a particular author).  The schema -->\n<!-- says a \"support\" statement is text-level, mixed content    -->\n<xsl:template match=\"bibinfo/support\">\n    <div class=\"support\">\n        <xsl:apply-templates select=\"node()\"/>\n    </div>\n</xsl:template>\n\n\n<!-- Front Colophon -->\n<!-- Licenses, ISBN, Cover Designer, etc -->\n<!-- We process pieces, in document order -->\n<!-- TODO: edition, publisher, production notes, cover design, etc -->\n<!-- TODO: revision control commit hash -->\n<xsl:template match=\"frontmatter/colophon\" mode=\"structural-division-inner-content\">\n    <xsl:param name=\"heading-level\"/>\n    <!-- Include publication data from titlepage appropriate for colophon -->\n    <xsl:apply-templates select=\"colophon-items\"/>\n</xsl:template>\n\n<xsl:template match=\"colophon-items\">\n     <xsl:apply-templates select=\"$bibinfo/credit[role]\" />\n     <xsl:apply-templates select=\"$bibinfo/edition\" />\n     <xsl:apply-templates select=\"$bibinfo/website\" />\n     <xsl:apply-templates select=\"$bibinfo/copyright\" />\n     <!-- NB: keywords are included in a colophon for a book, but under the abstract of an article -->\n     <xsl:apply-templates select=\"$bibinfo/keywords\" />\n     <xsl:apply-templates select=\"$bibinfo/support\" />\n</xsl:template>\n\n<xsl:template match=\"bibinfo/credit[role]\">\n    <div class=\"credit\">\n        <b class=\"title\">\n            <xsl:apply-templates select=\"role\" />\n        </b>\n        <xsl:text> </xsl:text>\n        <xsl:apply-templates select=\"entity\"/>\n    </div>\n</xsl:template>\n\n<xsl:template match=\"bibinfo/edition\">\n    <div class=\"credit\">\n        <b class=\"title\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\" />\n        </b>\n        <xsl:text> </xsl:text>\n        <xsl:apply-templates/>\n    </div>\n</xsl:template>\n\n<!-- website for the book -->\n<xsl:template match=\"bibinfo/website\">\n    <div class=\"credit\">\n        <b class=\"title\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\" />\n        </b>\n        <xsl:text> </xsl:text>\n        <!-- URL for canonical project website                -->\n        <!-- NB: interior of \"website\" is a \"url\" in author's -->\n        <!-- source, but the pre-processor adds a footnote    -->\n        <!-- Only one presumed, and thus enforced here        -->\n        <xsl:apply-templates select=\"url[1]|fn[1]\" />\n    </div>\n</xsl:template>\n\n<xsl:template match=\"bibinfo/copyright\">\n    <div class=\"para copyright\">\n        <xsl:call-template name=\"character\">\n            <xsl:with-param name=\"name\" select=\"'copyright'\"/>\n        </xsl:call-template>\n        <xsl:apply-templates select=\"year\" />\n        <xsl:text> </xsl:text>\n        <xsl:apply-templates select=\"holder\" />\n    </div>\n    <xsl:if test=\"shortlicense\">\n        <div class=\"para license\">\n            <xsl:apply-templates select=\"shortlicense\" />\n        </div>\n    </xsl:if>\n</xsl:template>\n\n<!-- Introductions and Conclusions -->\n<!-- Simple containers, allowed before and after           -->\n<!-- explicit subdivisions, to introduce or summarize      -->\n<!-- Title optional, typically just a few paragraphs       -->\n<!-- Also occur in \"smaller\" units (elsewhere), so the     -->\n<!-- HTML element varies from a \"section\" to an \"article\"  -->\n\n<!-- Not knowlable as a component of bigger things, a      -->\n<!-- pure container.  This is the component of a division. -->\n<!-- Tunnel the duplication flag, drop id if duplicate     -->\n<!-- NB: self::page for inside printouts -->\n<xsl:template match=\"introduction[parent::*[&STRUCTURAL-FILTER; or self::page]]|conclusion[parent::*[&STRUCTURAL-FILTER; or self::page]]\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n    <!-- newline inserted to encourage formatted output -->\n    <xsl:text>&#xa;</xsl:text>\n    <section>\n        <!-- cheap, but it works -->\n        <xsl:attribute name=\"class\">\n            <xsl:value-of select=\"local-name(.)\" />\n        </xsl:attribute>\n        <xsl:if test=\"$b-original\">\n            <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n        </xsl:if>\n        <xsl:if test=\"title\">\n            <xsl:apply-templates select=\".\" mode=\"heading-generic\">\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                <xsl:with-param name=\"heading-title\">\n                    <xsl:apply-templates select=\".\" mode=\"title-full\" />\n                    <span> </span>\n                </xsl:with-param>\n            </xsl:apply-templates>\n        </xsl:if>\n        <xsl:apply-templates select=\"*\">\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n    </section>\n</xsl:template>\n\n<!-- ####################### -->\n<!-- Back Matter Components -->\n<!-- ####################### -->\n\n<!-- Back Colophon -->\n<!-- Nothing special, so just process similarly to front -->\n\n<!--               -->\n<!-- Notation List -->\n<!--               -->\n\n<!-- Implementation of abstract templates.       -->\n<!-- See more complete code comments in -common. -->\n\n<xsl:template name=\"present-notation-list\">\n    <xsl:param name=\"content\"/>\n\n    <table class=\"notation-list\">\n        <tr>\n            <th>\n                <xsl:apply-templates select=\".\" mode=\"type-name\">\n                    <xsl:with-param name=\"string-id\" select=\"'symbol'\"/>\n                </xsl:apply-templates>\n            </th>\n            <th>\n                <xsl:apply-templates select=\".\" mode=\"type-name\">\n                    <xsl:with-param name=\"string-id\" select=\"'description'\"/>\n                </xsl:apply-templates>\n            </th>\n            <th>\n                <xsl:apply-templates select=\".\" mode=\"type-name\">\n                    <xsl:with-param name=\"string-id\" select=\"'location'\"/>\n                </xsl:apply-templates>\n            </th>\n        </tr>\n        <xsl:copy-of select=\"$content\"/>\n    </table>\n</xsl:template>\n\n<!-- Process *exactly* one \"m\" element             -->\n<!-- Duplicate the provided description            -->\n<!-- Create a cross-reference to enclosing content -->\n<xsl:template match=\"notation\" mode=\"present-notation-item\">\n    <tr>\n        <td>\n            <xsl:apply-templates select=\"usage/m[1]\"/>\n        </td>\n        <td>\n            <xsl:apply-templates select=\"description\" />\n        </td>\n        <td>\n            <xsl:apply-templates select=\".\" mode=\"enclosure-xref\" />\n        </td>\n    </tr>\n</xsl:template>\n\n<!-- Experimental: maybe belongs in -common -->\n<!-- Not -md, know where the link lives     -->\n<!-- NB: presumes this only gets used for   -->\n<!-- knowls that end up in a \"notation\"     -->\n<!-- list (can't adjust @match since it     -->\n<!-- claws up the tree)                     -->\n<xsl:template match=\"*\" mode=\"enclosure-xref\">\n    <xsl:variable name=\"structural\">\n        <xsl:apply-templates select=\".\" mode=\"is-structural\" />\n    </xsl:variable>\n    <xsl:variable name=\"block\">\n        <xsl:apply-templates select=\".\" mode=\"is-block\" />\n    </xsl:variable>\n    <xsl:choose>\n        <!-- found a structural or block parent -->\n        <!-- we fashion a cross-reference link  -->\n        <!-- TODO: xref-link's select is a fiction, maybe lead to bugs? -->\n        <xsl:when test=\"$structural='true' or $block='true'\">\n            <xsl:apply-templates select=\".\" mode=\"xref-link\">\n                <xsl:with-param name=\"target\" select=\".\" />\n                <xsl:with-param name=\"origin\" select=\"'notation'\"/>\n                <xsl:with-param name=\"content\">\n                    <xsl:apply-templates select=\".\" mode=\"type-name\" />\n                    <xsl:variable name=\"enclosure-number\">\n                        <xsl:apply-templates select=\".\" mode=\"number\" />\n                    </xsl:variable>\n                    <xsl:if test=\"not($enclosure-number = '')\">\n                        <xsl:text> </xsl:text>\n                        <xsl:value-of select=\"$enclosure-number\" />\n                    </xsl:if>\n                </xsl:with-param>\n            </xsl:apply-templates>\n            <!-- As we make knowl content selectively, we need -->\n            <!-- nto produce the content for the notation link -->\n            <xsl:variable name=\"is-knowl\">\n                <xsl:apply-templates select=\".\" mode=\"xref-as-knowl\"/>\n            </xsl:variable>\n            <xsl:if test=\"$is-knowl = 'true'\">\n                <xsl:apply-templates select=\".\" mode=\"manufacture-knowl\">\n                    <xsl:with-param name=\"origin\" select=\"'notation'\"/>\n                </xsl:apply-templates>\n            </xsl:if>\n        </xsl:when>\n        <!-- nothing interesting here, so step up a level -->\n        <!-- Eventually we find the top-level structure   -->\n        <!-- eg article, book, etc                        -->\n        <xsl:otherwise>\n            <xsl:apply-templates select=\"parent::*\" mode=\"enclosure-xref\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- ####################################### -->\n<!-- Solutions Divisions, Content Generation -->\n<!-- ####################################### -->\n\n<!-- The \"division-in-solutions\" modal template from -common -->\n<!-- calls the \"duplicate-heading\" modal template.           -->\n\n<xsl:template match=\"*\" mode=\"duplicate-heading\">\n    <!-- If we default b-make-link to true() we could make -->\n    <!-- section headings that appear in solutions into    -->\n    <!-- backlinks to the corresponding sections. As it is -->\n    <!-- only exercises etc become backlinks.              -->\n    <xsl:param name=\"b-make-link\" select=\"false()\"/>\n    <xsl:param name=\"heading-level\"/>\n    <xsl:param name=\"heading-stack\" select=\".\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-generic\">\n        <xsl:with-param name=\"b-make-link\" select=\"$b-make-link\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"extra-heading-classes\">\n            <xsl:if test=\"not(self::chapter) or ($numbering-maxlevel = 0)\">\n                <xsl:text> hide-type</xsl:text>\n            </xsl:if>\n        </xsl:with-param>\n        <xsl:with-param name=\"heading-attr-title\">\n            <xsl:apply-templates select=\".\" mode=\"tooltip-text\" />\n        </xsl:with-param>\n        <xsl:with-param name=\"heading-title\">\n            <xsl:apply-templates select=\"$heading-stack\" mode=\"duplicate-heading-content\"/>\n        </xsl:with-param>\n    </xsl:apply-templates>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"duplicate-heading-content\">\n    <xsl:variable name=\"show-number\">\n        <xsl:apply-templates select=\".\" mode=\"duplicate-heading-show-number\"/>\n    </xsl:variable>\n    <xsl:variable name=\"title\">\n        <xsl:apply-templates select=\".\" mode=\"title-full\" />\n    </xsl:variable>\n    <!-- Since headings stack, we use a \"p\" to aid screen readers in pausing between headings -->\n    <xsl:if test=\"$show-number = 'true'\">\n        <span class=\"codenumber\">\n            <xsl:apply-templates select=\".\" mode=\"number\" />\n        </span>\n        <xsl:if test=\"$title != ''\">\n            <xsl:call-template name=\"space-styled\"/>\n        </xsl:if>\n    </xsl:if>\n    <xsl:if test=\"$title != ''\">\n        <span class=\"title\">\n            <xsl:apply-templates select=\".\" mode=\"title-full\" />\n        </span>\n    </xsl:if>\n    <xsl:if test=\"position() != last()\">\n        <br/>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- ############### -->\n<!-- Arbitrary Lists -->\n<!-- ############### -->\n\n<!-- See general routine in  xsl/pretext-common.xsl -->\n<!-- which expects the two named templates and the  -->\n<!-- two division'al and element'al templates below,  -->\n<!-- it contains the logic of constructing such a list -->\n\n<!-- List-of entry/exit hooks -->\n<!-- No ops for HTML          -->\n<xsl:template name=\"list-of-begin\" />\n<xsl:template name=\"list-of-end\" />\n\n<!-- Subdivision headings in list-of's -->\n<xsl:template match=\"*\" mode=\"list-of-heading\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"duplicate-heading\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Entries in list-of's -->\n<!-- Partly borrowed from common routines -->\n<!-- TODO: CSS styling of the div forcing the knowl to open in the right place -->\n<!-- And spacing should be done with .type, .codenumber, .title                -->\n<xsl:template match=\"*\" mode=\"list-of-element\">\n    <!-- Name and number as a knowl/link, div to open against -->\n    <!-- TODO: xref-link's select is a fiction, maybe lead to bugs? -->\n    <div>\n        <xsl:apply-templates select=\".\" mode=\"xref-link\">\n            <xsl:with-param name=\"target\" select=\".\" />\n            <xsl:with-param name=\"origin\" select=\"'list-of'\"/>\n            <xsl:with-param name=\"content\">\n                <xsl:apply-templates select=\".\" mode=\"type-name\" />\n                <xsl:text> </xsl:text>\n                <xsl:apply-templates select=\".\" mode=\"number\" />\n            </xsl:with-param>\n        </xsl:apply-templates>\n        <!-- title plain, separated             -->\n        <!-- xref version, no additional period -->\n        <xsl:text> </xsl:text>\n        <xsl:apply-templates select=\".\" mode=\"title-xref\"/>\n    </div>\n    <!-- As we make knowl content selectively, we need -->\n    <!-- nto produce the content for a \"list-of\" link  -->\n    <xsl:variable name=\"is-knowl\">\n        <xsl:apply-templates select=\".\" mode=\"xref-as-knowl\"/>\n    </xsl:variable>\n    <xsl:if test=\"$is-knowl = 'true'\">\n        <xsl:apply-templates select=\".\" mode=\"manufacture-knowl\">\n            <xsl:with-param name=\"origin\" select=\"'list-of'\"/>\n        </xsl:apply-templates>\n    </xsl:if>\n</xsl:template>\n\n<!-- ################ -->\n<!-- Contributor List -->\n<!-- ################ -->\n\n<!-- Not much happening here, will drop -->\n<!-- into environment manufacture       -->\n<xsl:template match=\"contributors\">\n    <xsl:apply-templates select=\"contributor\" />\n</xsl:template>\n\n<!-- ############## -->\n<!-- Index Creation -->\n<!-- ############## -->\n\n<!-- Implementation of abstract index template -->\n<!-- No wrapper in HTML output                 -->\n<xsl:template name=\"present-index\">\n    <xsl:param name=\"content\"/>\n\n    <xsl:copy-of select=\"$content\"/>\n</xsl:template>\n\n<!-- Implementation of abstract letter group template        -->\n<!-- wrap the group in a div, which will be used for styling -->\n<xsl:template name=\"present-letter-group\">\n    <xsl:param name=\"the-index-list\"/>\n    <xsl:param name=\"letter-group\"/>\n    <xsl:param name=\"current-letter\"/>\n    <xsl:param name=\"content\"/>\n\n    <div class=\"indexletter\" id=\"indexletter-{$current-letter}\">\n        <xsl:copy-of select=\"$content\"/>\n    </div>\n</xsl:template>\n\n<!-- Implementation of presentation of index item, sub index item,      -->\n<!-- sub sub index item, in other words, headings at depth 1, 2, and 3. -->\n<!--   $heading-level: is 1, 2 or 3, to be translated to indicators     -->\n<!--                   for styling (such as indentation, newlines, etc) -->\n<!--   $content:       the actual text of the heading                   -->\n\n<xsl:template name=\"present-index-heading\">\n    <xsl:param name=\"the-index-list\"/>\n    <xsl:param name=\"heading-group\"/>\n    <xsl:param name=\"b-write-locators\"/>\n    <xsl:param name=\"heading-level\"/>\n    <xsl:param name=\"content\"/>\n\n    <div class=\"indexitem\">\n        <!-- translate heading-level to a CSS class name -->\n        <xsl:attribute name=\"class\">\n            <xsl:choose>\n                <xsl:when test=\"$heading-level = 1\">\n                    <xsl:text>indexitem</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$heading-level = 2\">\n                    <xsl:text>subindexitem</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$heading-level = 3\">\n                    <xsl:text>subsubindexitem</xsl:text>\n                </xsl:when>\n            </xsl:choose>\n        </xsl:attribute>\n        <!-- the actual heading content -->\n        <xsl:copy-of select=\"$content\"/>\n        <!-- perhaps time to write locators -->\n        <xsl:if test=\"$b-write-locators\">\n            <xsl:call-template name=\"locator-list\">\n                <xsl:with-param name=\"the-index-list\" select=\"$the-index-list\"/>\n                <xsl:with-param name=\"heading-group\" select=\"$heading-group\" />\n                <!-- use space to separate knowls -->\n                <xsl:with-param name=\"cross-reference-separator\" select=\"' '\" />\n            </xsl:call-template>\n        </xsl:if>\n    </div>\n</xsl:template>\n\n<!-- Implementation of abstract templates for presentation of locators -->\n\n<xsl:template name=\"present-index-locator\">\n    <xsl:param name=\"content\"/>\n\n    <span class=\"indexknowl\">\n        <xsl:copy-of select=\"$content\"/>\n    </span>\n</xsl:template>\n\n<xsl:template name=\"present-index-see\">\n    <xsl:param name=\"content\"/>\n\n    <span class=\"see\">\n        <xsl:copy-of select=\"$content\"/>\n    </span>\n</xsl:template>\n\n<xsl:template name=\"present-index-see-also\">\n    <xsl:param name=\"content\"/>\n\n    <span class=\"seealso\">\n        <xsl:copy-of select=\"$content\"/>\n    </span>\n</xsl:template>\n\n<xsl:template name=\"present-index-italics\">\n    <xsl:param name=\"content\"/>\n\n    <em>\n        <xsl:copy-of select=\"$content\"/>\n    </em>\n</xsl:template>\n\n\n<!-- Climb the tree looking for an enclosing structure of        -->\n<!-- interest.  Create cross-reference.                          -->\n<!-- One notable case: paragraph must be \"top-level\", just below -->\n<!-- a structural document node                                  -->\n<!-- Recursion always halts, since \"pretext\" is structural       -->\n<!-- TODO: save knowl or section link                            -->\n<!-- We create content of \"xref-knowl\" if it is a block.         -->\n<!-- TODO: identify index targets consistently in \"make-xref-knowls\" -->\n<!-- template, presumably parents of \"idx\" that are knowlable.       -->\n<xsl:template match=\"index-list\" mode=\"index-enclosure\">\n    <xsl:param name=\"enclosure\"/>\n\n    <xsl:variable name=\"structural\">\n        <xsl:apply-templates select=\"$enclosure\" mode=\"is-structural\"/>\n    </xsl:variable>\n    <xsl:variable name=\"block\">\n        <xsl:apply-templates select=\"$enclosure\" mode=\"is-block\"/>\n    </xsl:variable>\n    <xsl:choose>\n        <!-- found a structural parent first           -->\n        <!-- collect a url for a traditional hyperlink -->\n        <xsl:when test=\"($structural = 'true') or ($block = 'true')\">\n            <xsl:apply-templates select=\".\" mode=\"xref-link\">\n                <xsl:with-param name=\"target\" select=\"$enclosure\"/>\n                <xsl:with-param name=\"origin\" select=\"'index'\"/>\n                <xsl:with-param name=\"content\">\n                    <xsl:apply-templates select=\"$enclosure\" mode=\"type-name\"/>\n                </xsl:with-param>\n            </xsl:apply-templates>\n            <xsl:variable name=\"need-knowl\">\n                <xsl:apply-templates select=\"$enclosure\" mode=\"xref-as-knowl\"/>\n            </xsl:variable>\n            <xsl:if test=\"$block = 'true' and $need-knowl = 'true'\">\n                <xsl:apply-templates select=\"$enclosure\" mode=\"manufacture-knowl\">\n                    <xsl:with-param name=\"origin\" select=\"'index'\"/>\n                </xsl:apply-templates>\n            </xsl:if>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- Recurse.  The \"index-list\" gets passed along unchanged,     -->\n            <!-- as the context for location of the eventual cross-reference -->\n            <xsl:apply-templates select=\".\" mode=\"index-enclosure\">\n                <xsl:with-param name=\"enclosure\" select=\"$enclosure/parent::*\"/>\n            </xsl:apply-templates>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- ################################### -->\n<!-- Cross-Reference Knowls (xref-knowl) -->\n<!-- ################################### -->\n\n<!-- Many elements are candidates for cross-references     -->\n<!-- and many of those are nicely implemented as knowls.   -->\n\n<!-- Cross-references as knowls                               -->\n<!-- Override to turn off cross-references as knowls          -->\n<!-- NB: this device makes it easy to turn off knowlification -->\n<!-- entirely, since some renders cannot use knowl JavaScript -->\n<xsl:template match=\"*\" mode=\"xref-as-knowl\">\n    <xsl:value-of select=\"false()\" />\n</xsl:template>\n<!-- TEMPORARY: var/li is a WeBWorK popup or radio button, -->\n<!-- which is not a cross-reference target (it originates  -->\n<!-- in PG-code), and an error results when the heading in -->\n<!-- the knowl content tries to compute a number           -->\n<xsl:template match=\"fn|p|blockquote|biblio|biblio/note|interactive/instructions|gi|&DEFINITION-LIKE;|&OPENPROBLEM-LIKE;|&EXAMPLE-LIKE;|&PROJECT-LIKE;|task|&FIGURE-LIKE;|&THEOREM-LIKE;|&PROOF-LIKE;|case|&AXIOM-LIKE;|&REMARK-LIKE;|&COMPUTATION-LIKE;|&ASIDE-LIKE;|poem|assemblage|paragraphs|&GOAL-LIKE;|exercise|&SOLUTION-LIKE;|&DISCUSSION-LIKE;|exercisegroup|md[@pi:authored-one-line]|mrow|li[not(parent::var)]|contributor|fragment\" mode=\"xref-as-knowl\">\n    <xsl:param name=\"link\" select=\"/..\" />\n    <xsl:choose>\n        <xsl:when test=\"$b-skip-knowls or $html-xref-knowled = 'never' or $b-portable-html\">\n            <xsl:value-of select=\"false()\"/>\n        </xsl:when>\n        <xsl:when test=\"$html-xref-knowled = 'maximum'\">\n            <xsl:value-of select=\"true()\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- Case $html-xref-knowled = 'cross-page'                                    -->\n            <!-- Find the nearest common ancestor of the link and target                   -->\n            <!-- https://stackoverflow.com/questions/538293/find-common-parent-using-xpath -->\n            <xsl:variable name=\"nearest-common-ancestor\"\n                          select=\"./ancestor::*[count(. | $link/ancestor::*) = count($link/ancestor::*)] [1]\"/>\n            <xsl:choose>\n                <!-- A division's \"introduction\" or \"conclusion\" renders on   -->\n                <!-- its division's page, whole, whatever the chunk level.    -->\n                <!-- So a link and target together inside one companion are   -->\n                <!-- always on one page, though the companion's level would   -->\n                <!-- say otherwise.  Deliberately a containment test, not     -->\n                <!-- level arithmetic: the levels of these companions are     -->\n                <!-- slated for rework.                                       -->\n                <xsl:when test=\"$nearest-common-ancestor/ancestor-or-self::introduction[parent::*[&STRUCTURAL-FILTER;]] or $nearest-common-ancestor/ancestor-or-self::conclusion[parent::*[&STRUCTURAL-FILTER;]]\">\n                    <xsl:value-of select=\"false()\"/>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:variable name=\"nearest-ancestor-level\">\n                        <xsl:apply-templates select=\"$nearest-common-ancestor\" mode=\"enclosing-level\"/>\n                    </xsl:variable>\n                    <!-- remove not(), replace operator with <, then radically different behavior -->\n                    <xsl:value-of select=\"not($nearest-ancestor-level >= $chunk-level)\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- This template makes the knowl content for cross-references    -->\n<!-- (and not index entries, notation list entries, etc.)  It      -->\n<!-- accumulates and de-duplicagtes all the @ref/@xml:id strings   -->\n<!-- and then makes the files of content for the target *once*.    -->\n<!-- Initiation is one-time, late in the entry template.           -->\n<!--                                                               -->\n<!-- A \"fragref\" for literate programming has specialized behavior -->\n<!-- when reconstructing program code.  But as a knowl in HTML it  -->\n<!-- is isomorphic to \"xref\", so we lump them into this template.  -->\n<!-- Also, because we collect unique id's it will no longer be     -->\n<!-- possible to use the \"origin\" parameter to distinguish the     -->\n<!-- reference provoking the knowl (an \"xref\" and a \"fragref\"      -->\n<!-- could point to the same target).  There is little downside in -->\n<!-- this, and some upside in not putting identical content into   -->\n<!-- multiple locations.                                           -->\n<xsl:template match=\"*\" mode=\"make-xref-knowls\">\n    <xsl:variable name=\"xref-ids\">\n        <!-- Round up all \"xref\" elements -->\n        <xsl:variable name=\"all-xref\" select=\"$document-root//xref\"/>\n        <!-- Rund up all \"fragref\" elements, which are very similar -->\n        <xsl:variable name=\"all-fragref\" select=\"$document-root//fragref\"/>\n        <!-- A \"proof\" (or similar) with a @ref attribute doubles as  -->\n        <!-- an \"xref\" to the theorem it proves.  This should only be -->\n        <!-- a \"detached\" proof, not living inside a THEOREM-LIKE,    -->\n        <!-- nor inside a SOLUTION-LIKE. An author's attempt to put a -->\n        <!-- @ref on a non-detached proof will not create a knowl     -->\n        <!-- clickable and so will be unavailable. We make the knowl  -->\n        <!-- content here anyway, which does no real harm and should  -->\n        <!-- stop once the author mends their ways.                   -->\n        <!-- NB: there is an implicit PROOF-LIKE here.                -->\n        <xsl:variable name=\"all-proofref\" select=\"$document-root//proof[@ref]|$document-root//argument[@ref]|$document-root//justification[@ref]|$document-root//reasoning[@ref]|$document-root//explanation[@ref]\"/>\n        <!-- Consider all \"xref-like\" together as a group -->\n        <xsl:for-each select=\"$all-xref|$all-fragref|$all-proofref\">\n            <xsl:choose>\n                <!-- ignore, no-op -->\n                <xsl:when test=\"@provisional\"/>\n                <!-- just use @first, clean-up spaces -->\n                <xsl:when test=\"@first and @last\">\n                    <xid>\n                        <xsl:value-of select=\"normalize-space(@first)\"/>\n                    </xid>\n                </xsl:when>\n                <!-- a space-separated or comma-separated list -->\n                <!-- to bust up and wrap many times in \"xid\"   -->\n                <xsl:when test=\"@ref and (contains(normalize-space(@ref), ' ') or contains(@ref, ','))\">\n                    <xsl:variable name=\"clean-list\" select=\"concat(normalize-space(translate(@ref, ',', ' ')), ' ')\"/>\n                    <xsl:call-template name=\"split-ref-list\">\n                        <xsl:with-param name=\"list\" select=\"$clean-list\"/>\n                    </xsl:call-template>\n                </xsl:when>\n                <!-- clean-up reference as a courtesy -->\n                <xsl:when test=\"@ref\">\n                    <xid>\n                        <xsl:value-of select=\"normalize-space(@ref)\"/>\n                    </xid>\n                </xsl:when>\n                <!-- could error-check here -->\n                <xsl:otherwise/>\n            </xsl:choose>\n            <!-- TODO: cruise \"idx\" to get references to parents -->\n        </xsl:for-each>\n    </xsl:variable>\n    <xsl:variable name=\"id-nodes\" select=\"exsl:node-set($xref-ids)\"/>\n\n    <!-- might work better if sorted first -->\n    <xsl:variable name=\"unique-ids-rtf\">\n        <xsl:for-each select=\"$id-nodes/xid[not(. = preceding::*/.)]\">\n            <xsl:copy-of select=\".\"/>\n        </xsl:for-each>\n    </xsl:variable>\n    <xsl:variable name=\"unique-ids\" select=\"exsl:node-set($unique-ids-rtf)\"/>\n\n    <xsl:for-each select=\"$unique-ids/xid\">\n        <!-- context change coming, so save off the actual id string -->\n        <xsl:variable name=\"the-id\" select=\".\"/>\n        <!-- for-each only loops over one item, but changes context, -->\n        <!-- so the id() function is checking against the right document -->\n        <xsl:for-each select=\"$document-root\">\n            <xsl:variable name=\"target\" select=\"id($the-id)\"/>\n            <xsl:variable name=\"is-knowl\">\n                <xsl:apply-templates select=\"$target\" mode=\"xref-as-knowl\"/>\n            </xsl:variable>\n            <xsl:if test=\"$is-knowl = 'true'\">\n                <xsl:apply-templates select=\"$target\" mode=\"manufacture-knowl\">\n                    <xsl:with-param name=\"origin\" select=\"'xref'\" />\n                </xsl:apply-templates>\n            </xsl:if>\n        </xsl:for-each>\n    </xsl:for-each>\n</xsl:template>\n\n<!-- Decompose a string of references into elements for id  -->\n<!-- rtf above.  Note: each token has a space following it  -->\n<xsl:template name=\"split-ref-list\">\n    <xsl:param name=\"list\"/>\n\n    <xsl:choose>\n        <!-- final space causes recursion with -->\n        <!-- totally empty list, so halt       -->\n        <xsl:when test=\"$list = ''\"/>\n        <xsl:otherwise>\n            <xid>\n                <xsl:value-of select=\"substring-before($list, ' ')\"/>\n            </xid>\n            <xsl:call-template name=\"split-ref-list\">\n                <xsl:with-param name=\"list\" select=\"substring-after($list, ' ')\"/>\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Build file for xref-knowl content                            -->\n<!-- Context is an object that is the target of a cross-reference -->\n<!-- (\"xref\") and is known/checked to be implemented as a knowl.  -->\n<xsl:template match=\"*\" mode=\"manufacture-knowl\">\n    <xsl:param name=\"origin\" select=\"''\"/>\n\n    <xsl:variable name=\"knowl-file\">\n        <xsl:apply-templates select=\".\" mode=\"knowl-filename\">\n            <xsl:with-param name=\"origin\" select=\"$origin\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <!-- N.B. can't form @href with xsl:attribute -->\n    <exsl:document href=\"{$knowl-file}\" method=\"html\" indent=\"yes\" encoding=\"UTF-8\" doctype-system=\"about:legacy-compat\">\n        <html>\n            <xsl:call-template name=\"language-attributes\"/>\n            <xsl:call-template name=\"pretext-advertisement-and-style\"/>\n            <!-- header since separate file -->\n            <xsl:text>&#xa;</xsl:text>\n            <xsl:call-template name=\"converter-blurb-html-no-date\"/>\n            <head>\n                <!-- dissuade indexing duplicated content -->\n                <meta name=\"robots\" content=\"noindex, nofollow\" />\n                <!-- we need Sage cell configuration functions     -->\n                <!-- in the knowl file itself, the main Javascript -->\n                <!-- is being placed on *every* page, if present   -->\n                <!-- anywhere in the document, and that is         -->\n                <!-- sufficient for the external knowl             -->\n                <xsl:apply-templates select=\".\" mode=\"sagecell\" />\n            </head>\n            <!-- ignore MathJax signals everywhere, then enable selectively -->\n            <body class=\"ignore-math\">\n                <!-- content, in xref style or hidden style     -->\n                <!-- initiate tunneling duplication flag here   -->\n                <!-- We send a flag to the \"body\" template      -->\n                <!-- indicating the call is at the outermost    -->\n                <!-- level of the knowl being constructed,      -->\n                <!-- rather than to manufacture a child element -->\n                <!-- Usually this parameter is ignored          -->\n                <!-- An xref to an mrow results in a knowl      -->\n                <!-- whose content is more than just the xref,  -->\n                <!-- it is the entire containing md or mdn      -->\n\n                <!-- NB: the Javascript controlling the animation of the   -->\n                <!-- open/close of a knowl, presumes it begins with an     -->\n                <!-- element enclosing the content.  This is guaranteed by -->\n                <!-- the \"body\" template via the \"body-element\" template.  -->\n                <xsl:choose>\n                    <xsl:when test=\"self::mrow\">\n                        <xsl:apply-templates select=\"parent::*\" mode=\"body\">\n                            <xsl:with-param name=\"block-type\" select=\"'xref'\" />\n                            <xsl:with-param name=\"b-original\" select=\"false()\" />\n                            <xsl:with-param name=\"b-top-level\" select=\"true()\" />\n                            <xsl:with-param name=\"heading-level\" select=\"2\"/>\n                        </xsl:apply-templates>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:apply-templates select=\".\" mode=\"body\">\n                            <xsl:with-param name=\"block-type\" select=\"'xref'\" />\n                            <xsl:with-param name=\"b-original\" select=\"false()\" />\n                            <xsl:with-param name=\"b-top-level\" select=\"true()\" />\n                            <xsl:with-param name=\"heading-level\" select=\"2\"/>\n                        </xsl:apply-templates>\n                    </xsl:otherwise>\n                </xsl:choose>\n                <!-- in-context link for xref-knowl content -->\n                <span class=\"incontext\">\n                    <a class=\"internal\">\n                        <xsl:attribute name=\"href\">\n                            <xsl:apply-templates select=\".\" mode=\"url\"/>\n                        </xsl:attribute>\n                        <xsl:apply-templates select=\".\" mode=\"type-name\">\n                            <xsl:with-param name=\"string-id\" select=\"'incontext'\"/>\n                        </xsl:apply-templates>\n                    </a>\n                </span>\n            </body>\n        </html>\n    </exsl:document>\n</xsl:template>\n\n<!-- The directories of knowls that are targets of references.  Most,   -->\n<!-- but not all, filenames are based on the \"unique-id\" template,      -->\n<!-- but this is organized so alternate naming conventions can be used. -->\n<!-- The file extension is *.html so recognized as OK by Moodle, etc    -->\n<xsl:template match=\"*\" mode=\"knowl-filename\">\n    <xsl:param name=\"origin\" select=\"''\"/>\n\n    <xsl:text>./knowl/</xsl:text>\n    <xsl:choose>\n        <xsl:when test=\"$origin = 'xref'\">\n            <xsl:text>xref/</xsl:text>\n            <!-- Target of an \"xref\" must always have an author-supplied -->\n            <!-- @xml:id value and this is backward-compatible with the  -->\n            <!-- situation before @label became prominent.               -->\n            <xsl:value-of select=\"@xml:id\"/>\n        </xsl:when>\n        <xsl:when test=\"$origin = 'index'\">\n            <xsl:text>index/</xsl:text>\n            <xsl:apply-templates select=\".\" mode=\"unique-id\" />\n        </xsl:when>\n        <xsl:when test=\"$origin = 'list-of'\">\n            <xsl:text>list-of/</xsl:text>\n            <xsl:apply-templates select=\".\" mode=\"unique-id\" />\n        </xsl:when>\n        <xsl:when test=\"$origin = 'notation'\">\n            <xsl:text>notation/</xsl:text>\n            <xsl:apply-templates select=\".\" mode=\"unique-id\" />\n        </xsl:when>\n        <!-- put a \"location-report\" template here to debug a bad knowl file -->\n        <!-- (the file, or a reference to it) that lacks a subdirectory      -->\n        <xsl:otherwise/>\n    </xsl:choose>\n    <xsl:text>.html</xsl:text>\n</xsl:template>\n\n<!-- ######## -->\n<!-- Headings -->\n<!-- ######## -->\n\n<!-- Pretty much everything for actually manipluating titles -->\n<!-- happens in the -common template. But when structured by -->\n<!-- \"line\" we need to implement an abstract variable with a -->\n<!-- separator string.  Since HTML (and EPUB, etc) are       -->\n<!-- zoomable and reflowable, we just insert spaces and      -->\n<!-- leave actual line-breaking to the laTeX conversion.     -->\n<xsl:variable name=\"title-separator\" select=\"' '\"/>\n\n<!-- This template manufactures HTML \"headings\", the \"hN\" elements.   -->\n<!-- We do not style based on these elements, but a screen-reader     -->\n<!-- or offline (no CSS) environment will use these profitably.       -->\n<!-- So it is important for the elements to be in a logical           -->\n<!-- progression corresponding to \"section\" and \"article\" nodes       -->\n<!-- of the HTML tree.                                                -->\n<!--                                                                  -->\n<!-- We set the \"heading-level\" to \"1\" when chunking is initiated.    -->\n<!-- Whenever a template processes its children, we increment the     -->\n<!-- variable as we pass it down, so a template receives the correct  -->\n<!-- level (and before it ever gets here, since we have consciously   -->\n<!-- chosen *not* to increment here).                                 -->\n<!--                                                                  -->\n<!-- There is no h7, so we need to just settle for h6, I guess.       -->\n<!-- TODO: address h7 when \"article\" get careful headings             -->\n<xsl:template match=\"*\" mode=\"html-heading\">\n    <xsl:param name=\"heading-level\"/>\n\n    <!-- Debugging code, preserve temporarily, just for divisions now -->\n    <!-- Turn on \"CHUNK: and \"INTER:\" debugging in -common templates  -->\n    <!-- <xsl:message> -->\n        <!-- <xsl:text>  </xsl:text><xsl:value-of select=\"$heading-level\"/> -->\n        <!-- <xsl:text> : </xsl:text><xsl:value-of select=\"local-name(.)\"/><xsl:text> : </xsl:text><xsl:apply-templates select=\".\" mode=\"long-name\"/> -->\n    <!-- </xsl:message> -->\n\n    <!-- simple -->\n    <xsl:text>h</xsl:text>\n    <xsl:choose>\n        <xsl:when test=\"$heading-level &lt; 7\">\n            <xsl:value-of select=\"$heading-level\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- TODO: Report excessive heading here, as informational item           -->\n            <!-- Perhaps include advice: chunk more, author with shallower divisions, -->\n            <!-- use less comprehensive solutions nested at depth                     -->\n            <xsl:text>6</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- These are convenience methods for frequently-used headings -->\n\n<!-- Emit the \"hN\" tag name for a heading element.  Every caller is -->\n<!-- expected to thread a $heading-level parameter through from the -->\n<!-- chunk-template starting point.                                 -->\n<xsl:template match=\"*\" mode=\"hN\">\n    <xsl:param name=\"heading-level\" />\n    <xsl:variable name=\"actual-heading-level\">\n        <xsl:choose>\n            <xsl:when test=\"$heading-level\">\n                <xsl:value-of select=\"$heading-level\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <!-- Reaching this branch is a BUG: every caller of    -->\n                <!-- mode=\"hN\" should now thread a $heading-level      -->\n                <!-- parameter down through \"body\", \"wrapped-content\", -->\n                <!-- and the various heading-* templates.  If you see  -->\n                <!-- this message, locate the apply-templates chain    -->\n                <!-- that omitted the parameter and add it.            -->\n                <xsl:message>PTX:BUG:     \"hN\" template reached without a $heading-level parameter on element &lt;<xsl:value-of select=\"local-name(.)\"/>&gt; at <xsl:for-each select=\"ancestor::*\"><xsl:value-of select=\"local-name(.)\"/><xsl:text>/</xsl:text></xsl:for-each><xsl:value-of select=\"local-name(.)\"/>; defaulting to h1</xsl:message>\n                <xsl:text>1</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$actual-heading-level > 6\">\n            <xsl:text>h6</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"concat('h',$actual-heading-level)\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- REMARK-LIKE, COMPUTATION-LIKE, DEFINITION-LIKE, SOLUTION-LIKE, objectives (xref-content), outcomes (xref-content), EXAMPLE-LIKE, PROJECT-LIKE, OPENPROBLEM-LIKE, exercise (inline), task (xref-content), fn (xref-content), biblio/note (xref-content)-->\n<!-- E.g. Corollary 4.1 (Leibniz, Newton).  The fundamental theorem of calculus. -->\n<xsl:template match=\"*\" mode=\"heading-full\">\n    <xsl:param name=\"b-make-link\" select=\"false()\"/>\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-generic\">\n        <xsl:with-param name=\"b-make-link\" select=\"$b-make-link\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"heading-title\">\n            <span class=\"type\">\n                <xsl:apply-templates select=\".\" mode=\"type-name\"/>\n            </span>\n            <!--  -->\n            <xsl:variable name=\"the-number\">\n                <xsl:apply-templates select=\".\" mode=\"number\" />\n            </xsl:variable>\n            <xsl:if test=\"not($the-number='')\">\n                <xsl:call-template name=\"space-styled\"/>\n                <span class=\"codenumber\">\n                    <xsl:value-of select=\"$the-number\"/>\n                </span>\n            </xsl:if>\n            <!--  -->\n            <xsl:if test=\"creator and (&THEOREM-FILTER; or &AXIOM-FILTER;)\">\n                <xsl:call-template name=\"space-styled\"/>\n                <span class=\"creator\">\n                    <xsl:text>(</xsl:text>\n                    <xsl:apply-templates select=\".\" mode=\"creator-full\"/>\n                    <xsl:text>)</xsl:text>\n                </span>\n            </xsl:if>\n            <!-- A period now, no matter which of 4 combinations we have above-->\n            <xsl:call-template name=\"period-styled\"/>\n            <!-- A title carries its own punctuation -->\n            <xsl:if test=\"title\">\n                <xsl:call-template name=\"space-styled\"/>\n                <span class=\"title\">\n                    <xsl:apply-templates select=\".\" mode=\"title-full\"/>\n                </span>\n            </xsl:if>\n        </xsl:with-param>\n    </xsl:apply-templates>\n</xsl:template>\n\n<xsl:template match=\"&FIGURE-LIKE;\" mode=\"figure-caption\">\n    <xsl:param name=\"b-original\"/>\n\n    <!-- Subnumbered panels of a \"sidebyside\" get a simpler caption/title -->\n    <xsl:variable name=\"fig-placement\">\n        <xsl:apply-templates select=\".\" mode=\"figure-placement\"/>\n    </xsl:variable>\n    <xsl:variable name=\"b-subnumbered\" select=\"$fig-placement = 'subnumber'\"/>\n    <figcaption>\n        <!-- A normal caption/title, or a subnumbered caption/title -->\n        <xsl:choose>\n            <xsl:when test=\"$b-subnumbered\">\n                <span class=\"codenumber\">\n                    <xsl:apply-templates select=\".\" mode=\"serial-number\"/>\n                </span>\n            </xsl:when>\n            <xsl:otherwise>\n                <span class=\"type\">\n                    <xsl:apply-templates select=\".\" mode=\"type-name\"/>\n                </span>\n                <xsl:call-template name=\"space-styled\"/>\n                <span class=\"codenumber\">\n                    <xsl:apply-templates select=\".\" mode=\"number\"/>\n                    <xsl:call-template name=\"period-styled\"/>\n                </span>\n            </xsl:otherwise>\n        </xsl:choose>\n        <xsl:call-template name=\"space-styled\"/>\n        <xsl:choose>\n            <!-- a caption can have a footnote, hence a -->\n            <!-- knowl, hence original or duplicate     -->\n            <xsl:when test=\"self::figure\">\n                <xsl:apply-templates select=\".\" mode=\"caption-full\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                </xsl:apply-templates>\n            </xsl:when>\n            <xsl:when test=\"self::table or self::list or self::listing\">\n                <xsl:apply-templates select=\".\" mode=\"title-full\"/>\n            </xsl:when>\n        </xsl:choose>\n        <!-- Insert permalink directly below the title or caption -->\n        <xsl:apply-templates select=\".\" mode=\"permalink\"/>\n    </figcaption>\n</xsl:template>\n\n<!-- hN generic: Helper for other hN constructs.                                                    -->\n<!-- heading-level: Inherited from caller, determines the N                                         -->\n<!-- heading-title: The actual text, including any numbering                                        -->\n<!-- heading-attr-title: If provided, a title attribute will be created on the hN tag               -->\n<!-- extra-heading-classes: Added to the default \"heading\" class on the hN tag                      -->\n<!-- b-make-link: Whether to turn the heading into a link to its origin. Used in solutions sections -->\n<xsl:template match=\"*\" mode=\"heading-generic\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:param name=\"heading-title\"/>\n    <xsl:param name=\"heading-attr-title\"/>\n    <xsl:param name=\"extra-heading-classes\"/>\n    <xsl:param name=\"b-make-link\" select=\"false()\" />\n    <xsl:variable name=\"hN\">\n        <xsl:apply-templates select=\".\" mode=\"hN\">\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\" />\n        </xsl:apply-templates>\n    </xsl:variable>\n    <xsl:element name=\"{$hN}\">\n        <xsl:attribute name=\"class\">\n            <xsl:text>heading</xsl:text>\n            <xsl:value-of select=\"$extra-heading-classes\"/>\n        </xsl:attribute>\n        <xsl:if test=\"$heading-attr-title\">\n            <xsl:attribute name=\"title\">\n                <xsl:value-of select=\"$heading-attr-title\"/>\n            </xsl:attribute>\n        </xsl:if>\n        <xsl:choose>\n            <xsl:when test=\"$b-make-link\">\n                <xsl:element name=\"a\">\n                    <xsl:attribute name=\"href\">\n                        <xsl:apply-templates select=\".\" mode=\"url\"/>\n                    </xsl:attribute>\n                    <xsl:attribute name=\"aria-label\">\n                        <xsl:text>Back to </xsl:text>\n                        <xsl:copy-of select=\"$heading-title\"/>\n                    </xsl:attribute>\n                    <xsl:copy-of select=\"$heading-title\"/>\n                </xsl:element>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:copy-of select=\"$heading-title\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:element>\n</xsl:template>\n\n\n<!-- hN, no type name, full number, title (if exists)   -->\n<!-- divisional exercise, principally for solution list -->\n<xsl:template match=\"*\" mode=\"heading-divisional-exercise\">\n    <xsl:param name=\"b-make-link\" select=\"false()\" />\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-generic\">\n        <xsl:with-param name=\"b-make-link\" select=\"$b-make-link\" />\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"heading-title\">\n            <span class=\"codenumber\">\n                <xsl:apply-templates select=\".\" mode=\"number\" />\n                <xsl:call-template name=\"period-styled\"/>\n            </span>\n            <xsl:if test=\"title\">\n                <xsl:call-template name=\"space-styled\"/>\n                <span class=\"title\">\n                    <xsl:apply-templates select=\".\" mode=\"title-full\" />\n                </span>\n            </xsl:if>\n        </xsl:with-param>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- hN, no type name, serial number, title (if exists) -->\n<!-- divisional exercise, principally when born         -->\n<xsl:template match=\"*\" mode=\"heading-divisional-exercise-serial\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-generic\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"heading-title\">\n            <span class=\"codenumber\">\n                <xsl:apply-templates select=\".\" mode=\"serial-number\" />\n                <xsl:call-template name=\"period-styled\"/>\n            </span>\n            <xsl:if test=\"title\">\n                <xsl:call-template name=\"space-styled\"/>\n                <span class=\"title\">\n                    <xsl:apply-templates select=\".\" mode=\"title-full\" />\n                </span>\n            </xsl:if>\n        </xsl:with-param>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- hN, type name, serial number, title (if exists) -->\n<!-- exercise (divisional, xref-content)      -->\n<xsl:template match=\"*\" mode=\"heading-divisional-exercise-typed\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-generic\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"heading-title\">\n            <span class=\"type\">\n                <xsl:apply-templates select=\".\" mode=\"type-name\" />\n            </span>\n            <xsl:call-template name=\"space-styled\"/>\n            <span class=\"codenumber\">\n                <xsl:apply-templates select=\".\" mode=\"serial-number\" />\n                <xsl:call-template name=\"period-styled\"/>\n            </span>\n            <xsl:if test=\"title\">\n                <xsl:call-template name=\"space-styled\"/>\n                <span class=\"title\">\n                    <xsl:apply-templates select=\".\" mode=\"title-full\" />\n                </span>\n            </xsl:if>\n        </xsl:with-param>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- hN, no type name, just simple list number, no title -->\n<!-- task (when born) -->\n<xsl:template match=\"*\" mode=\"heading-list-number\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-generic\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"heading-title\">\n            <span class=\"codenumber\">\n                <xsl:text>(</xsl:text>\n                <xsl:apply-templates select=\".\" mode=\"list-number\" />\n                <xsl:text>)</xsl:text>\n            </span>\n            <xsl:if test=\"title\">\n                <xsl:call-template name=\"space-styled\"/>\n                <span class=\"title\">\n                    <xsl:apply-templates select=\".\" mode=\"title-full\"/>\n                </span>\n            </xsl:if>\n        </xsl:with-param>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- hN, type name, no number (even if exists), title (if exists)              -->\n<!-- eg, objectives is one-per-subdivison, max, so no need to display at birth -->\n<!-- NB: rather specific to \"objectives\" and \"outcomes\", careful               -->\n<!-- objectives and outcomes (when born) -->\n<xsl:template match=\"*\" mode=\"heading-full-implicit-number\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-generic\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"heading-title\">\n            <span class=\"type\">\n                <xsl:apply-templates select=\".\" mode=\"type-name\" />\n                <xsl:if test=\"title\">\n                    <xsl:call-template name=\"dividing-string-styled\">\n                        <xsl:with-param name=\"divider\" select=\"':'\"/>\n                        <xsl:with-param name=\"name\" select=\"'colon'\"/>\n                    </xsl:call-template>\n                </xsl:if>\n            </span>\n            <!-- codenumber is implicit via placement -->\n            <xsl:if test=\"title\">\n                <xsl:call-template name=\"space-styled\"/>\n                <span class=\"title\">\n                    <xsl:apply-templates select=\".\" mode=\"title-full\" />\n                </span>\n            </xsl:if>\n        </xsl:with-param>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Not normally titled, but knowl content gives some indication -->\n<!-- NB: no punctuation, intended only for xref knowl content     -->\n<!-- blockquote, exercisegroup, defined term -->\n<xsl:template match=\"*\" mode=\"heading-type\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-generic\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"heading-title\">\n            <span class=\"type\">\n                <xsl:apply-templates select=\".\" mode=\"type-name\" />\n            </span>\n        </xsl:with-param>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- A title or the type, with a period   -->\n<!-- PROOF-LIKE. interactive/instructions -->\n<xsl:template match=\"&PROOF-LIKE;|interactive/instructions\" mode=\"heading-no-number\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-generic\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"heading-title\">\n            <xsl:choose>\n                <xsl:when test=\"title\">\n                    <!-- comes with punctuation -->\n                    <span class=\"title\">\n                        <xsl:apply-templates select=\".\" mode=\"title-full\"/>\n                    </span>\n                </xsl:when>\n                <xsl:otherwise>\n                    <!-- supply a period -->\n                    <span class=\"type\">\n                        <xsl:apply-templates select=\".\" mode=\"type-name\" />\n                        <xsl:call-template name=\"period-styled\"/>\n                    </span>\n                </xsl:otherwise>\n            </xsl:choose>\n            <xsl:if test=\"@ref\">\n                <xsl:text>&#xa0;(</xsl:text>\n                <xsl:apply-templates select=\".\" mode=\"proof-xref-theorem\"/>\n                <xsl:text>)</xsl:text>\n            </xsl:if>\n        </xsl:with-param>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Title only -->\n<!-- exercisegroup, dl/li             -->\n<!-- PROOF-LIKE, when titled          -->\n<!-- Subsidiary to paragraphs,        -->\n<!-- and divisions of \"exercises\"     -->\n<!-- No title, then nothing happens   -->\n<xsl:template match=\"*\" mode=\"heading-title\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:variable name=\"has-default-title\">\n        <xsl:apply-templates select=\".\" mode=\"has-default-title\"/>\n    </xsl:variable>\n    <xsl:if test=\"title/*|title/text() or $has-default-title = 'true'\">\n        <xsl:apply-templates select=\".\" mode=\"heading-generic\">\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            <xsl:with-param name=\"heading-title\">\n                <span class=\"title\">\n                    <xsl:apply-templates select=\".\" mode=\"title-full\" />\n                </span>\n            </xsl:with-param>\n        </xsl:apply-templates>\n    </xsl:if>\n</xsl:template>\n\n<!-- Title only, paragraphs         -->\n<!-- No title, then nothing happens -->\n<!-- TODO: titles will be mandatory sometime -->\n<xsl:template match=\"*\" mode=\"heading-title-paragraphs\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:if test=\"title/*|title/text()\">\n        <xsl:apply-templates select=\".\" mode=\"heading-generic\">\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            <xsl:with-param name=\"heading-title\">\n                <span class=\"title\">\n                    <xsl:apply-templates select=\".\" mode=\"title-full\" />\n                </span>\n            </xsl:with-param>\n        </xsl:apply-templates>\n    </xsl:if>\n</xsl:template>\n\n<!-- A type, with maybe a serial number to disambiguate -->\n<!-- No hN, optional title                              -->\n<!-- SOLUTION-LIKE (xref-text), biblio/note (xref-text),-->\n<!-- interactive/instructions (xref-text)               -->\n<xsl:template match=\"*\" mode=\"heading-simple\">\n    <!-- the name of the object, its \"type\" -->\n    <!-- The <xsl:text> </xsl:text> to produce a space is -->\n    <!-- essential for EPUB. Calling space-styled creates -->\n    <!-- a line break in EPUB/Kindle.                     -->\n    <span class=\"type\">\n        <xsl:apply-templates select=\".\" mode=\"type-name\" />\n    </span>\n    <xsl:variable name=\"the-number\">\n        <xsl:apply-templates select=\".\" mode=\"non-singleton-number\" />\n    </xsl:variable>\n    <!-- An empty value means element is a singleton -->\n    <!-- else the serial number comes through        -->\n    <xsl:if test=\"not($the-number = '')\">\n        <xsl:call-template name=\"space-styled\"/>\n        <span class=\"codenumber\">\n            <xsl:apply-templates select=\".\" mode=\"serial-number\" />\n        </span>\n    </xsl:if>\n    <!-- Always end, e.g. \"Hint\" or \"Hint 4\", with a period -->\n    <xsl:call-template name=\"period-styled\"/>\n    <xsl:if test=\"title\">\n        <xsl:call-template name=\"space-styled\"/>\n        <span class=\"title\">\n            <xsl:apply-templates select=\".\" mode=\"title-full\" />\n        </span>\n    </xsl:if>\n</xsl:template>\n\n<!-- The next template, \"heading-non-singleton-number\", is basically    -->\n<!-- \"heading-no-number\" with an (optional) non-singleton number,       -->\n<!-- much like in \"heading-simple\".  If/Once PROOF-LIKE gets a          -->\n<!-- non-singleton number then maybe \"heading-no-number\" can come here. -->\n\n<!-- A title or the type, with a period, and an optional number -->\n<!-- &SOLUTION-LIKE;, when unknowled, is the only known case    -->\n<xsl:template match=\"*\" mode=\"heading-non-singleton-number\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-generic\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"heading-title\">\n            <xsl:choose>\n                <xsl:when test=\"title\">\n                    <!-- comes with punctuation -->\n                    <span class=\"title\">\n                        <xsl:apply-templates select=\".\" mode=\"title-full\"/>\n                    </span>\n                </xsl:when>\n                <xsl:otherwise>\n                    <span class=\"type\">\n                        <xsl:apply-templates select=\".\" mode=\"type-name\" />\n                    </span>\n                    <xsl:variable name=\"the-number\">\n                        <xsl:apply-templates select=\".\" mode=\"non-singleton-number\" />\n                    </xsl:variable>\n                    <!-- An empty value means element is a singleton -->\n                    <!-- else the serial number comes through        -->\n                    <xsl:if test=\"not($the-number = '')\">\n                        <xsl:call-template name=\"space-styled\"/>\n                        <span class=\"codenumber\">\n                            <xsl:apply-templates select=\".\" mode=\"serial-number\" />\n                        </span>\n                    </xsl:if>\n                    <!-- supply a period -->\n                    <xsl:call-template name=\"period-styled\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:with-param>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- A case in a PROOF-LIKE, eg \"(=>) Necessity.\" -->\n\n<!-- First we need to set up arrow symbols for this output target. -->\n<xsl:template name=\"double-right-arrow-symbol\">\n    <!-- 'RIGHTWARDS DOUBLE ARROW' (U+21D2) -->\n    <xsl:comment>Style arrows in CSS?</xsl:comment>\n    <xsl:text>&#x21d2;</xsl:text>\n</xsl:template>\n<xsl:template name=\"double-left-arrow-symbol\">\n    <!-- 'LEFTWARDS DOUBLE ARROW' (U+21D0) -->\n    <xsl:comment>Style arrows in CSS?</xsl:comment>\n    <xsl:text>&#x21d0;</xsl:text>\n</xsl:template>\n<!-- Also need a \"delimiter space\" for when \"direction\" is \"cycle\". -->\n<xsl:template name=\"case-cycle-delimiter-space\">\n    <!-- 'HAIR SPACE'  (U+200A)                -->\n    <!-- 'WORD JOINER' (U+2060)                -->\n    <!-- Prevents line break after whitespace. -->\n    <!-- May not work in Firefox.              -->\n    <xsl:text>&#x200a;&#x2060;</xsl:text>\n</xsl:template>\n\n<!-- case -->\n<xsl:template match=\"*\" mode=\"heading-case\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-generic\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"heading-title\">\n            <!-- optional direction, given by attribute -->\n            <xsl:apply-templates select=\".\" mode=\"case-direction\" />\n            <!-- If there is a title, the following will produce it. If -->\n            <!-- no title, and we don't have a direction already, the   -->\n            <!-- following will produce a default title, eg \"Case.\"     -->\n            <xsl:if test=\"boolean(title) or not(@direction)\">\n                <xsl:apply-templates select=\".\" mode=\"title-full\" />\n            </xsl:if>\n        </xsl:with-param>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading Utilities -->\n\n<!-- These named templates create a dividing character  -->\n<!-- with enough HTML markup to allow for hiding        -->\n<!-- them if some other part of a heading is hidden.    -->\n<!-- space/period versions are convience wrappers for   -->\n<!-- commonly used characters.                          -->\n\n<xsl:template name=\"space-styled\">\n    <xsl:call-template name=\"dividing-string-styled\"/>\n</xsl:template>\n\n<xsl:template name=\"period-styled\">\n    <xsl:call-template name=\"dividing-string-styled\">\n        <xsl:with-param name=\"divider\" select=\"'.'\"/>\n        <xsl:with-param name=\"name\" select=\"'period'\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<xsl:template name=\"dividing-string-styled\">\n    <xsl:param name=\"divider\" select=\"' '\"/>\n    <xsl:param name=\"name\" select=\"'space'\"/>\n    <span class=\"{$name} heading-divison-mark heading-divison-mark__{$name}\">\n        <xsl:value-of select=\"$divider\"/>\n    </span>\n</xsl:template>\n\n\n<!-- ######################## -->\n<!-- Block Production, Knowls -->\n<!-- ######################## -->\n\n<!-- Generically, a \"block\" is a child of a \"division\"; see the schema for  -->\n<!-- the precise rules.  Blocks also have \"significant components\": for     -->\n<!-- example, a \"solution\" is a significant component of an \"example\".  A   -->\n<!-- \"p\" can be a block in its own right, can be a significant component of -->\n<!-- a larger block, or can be neither.                                     -->\n\n<!-- A block (or significant component) is rendered into HTML in one of     -->\n<!-- three modes:                                                           -->\n\n<!-- (a) Visible and original.  Drawn directly on a main page, with full    -->\n<!-- identifying information (HTML @id, etc.).                              -->\n\n<!-- (b) Hidden and original.  Drawn on a main page as an HTML \"details\"    -->\n<!-- element, with the heading carried by a clickable \"summary\" and the     -->\n<!-- content initially collapsed.  We call this a \"born-hidden knowl\";      -->\n<!-- historically it was called an \"embedded knowl\" because the content     -->\n<!-- lives on the page (in contrast to the external file behind a           -->\n<!-- cross-reference knowl).  Whether a block is born hidden may be         -->\n<!-- automatic (\"hint\" is always hidden), publisher-elective (\"theorem\",    -->\n<!-- \"remark\", \"definition\"), or forbidden (\"blockquote\" is never hidden);  -->\n<!-- the modal \"is-hidden\" template decides.                                -->\n\n<!-- (c) Visible and duplicate.  Drawn into a separate external file, as    -->\n<!-- the content of a cross-reference knowl.  All identifying information   -->\n<!-- is stripped, because the file may be opened many times in many pages   -->\n<!-- and any HTML @id must remain unique within the page it is shown on.    -->\n\n<!-- Every block element appears in the final output at most once as an     -->\n<!-- \"original\" (with identifying information) and at most once as a        -->\n<!-- \"duplicate\" (without).  Duplicates should re-use other duplicates as   -->\n<!-- much as possible.                                                      -->\n\n<!-- The generic (non-modal) dispatch template below matches any element    -->\n<!-- that is a block or a significant component.  Each incoming element     -->\n<!-- falls into one of three situations:                                    -->\n\n<!-- Original, born visible.  The element is rendered as part of a main     -->\n<!-- page with full identification.  The parameter \"b-original\" defaults to -->\n<!-- true.  Children that are themselves blocks recurse through this same   -->\n<!-- dispatch and are rendered as visible or born-hidden originals          -->\n<!-- according to their own \"is-hidden\".                                    -->\n\n<!-- Original, born hidden.  The element is wrapped in an HTML \"details\"    -->\n<!-- element; the @id is placed on the visible \"summary\" (so the element    -->\n<!-- remains a cross-reference target) and the body is placed inside the    -->\n<!-- \"details\".  The \"b-original\" parameter remains true throughout the     -->\n<!-- subtree, so descendant blocks may themselves be original (visible or   -->\n<!-- hidden) as appropriate.                                                -->\n\n<!-- Duplicate (cross-reference knowl).  The set of cross-reference targets -->\n<!-- is collected by the \"make-xref-knowls\" template, which walks the       -->\n<!-- document, gathers every element actually pointed at by an \"xref\", and  -->\n<!-- hands each one to \"manufacture-knowl\".  That template writes one       -->\n<!-- external HTML file per target, whose body comes from a single call to  -->\n<!-- the modal \"body\" template with block-type='xref' and b-original=false. -->\n<!-- Both parameters then flow down through the subtree: every descendant   -->\n<!-- receives b-original=false (so no @id is ever emitted inside the file), -->\n<!-- while block-type reverts to 'visible' or 'hidden' at each block        -->\n<!-- boundary according to that descendant's own \"is-hidden\".               -->\n\n<!-- The cross-reference knowl is also given a richer top-level heading     -->\n<!-- than a born element (see \"heading-xref-knowl\"), so the reader can      -->\n<!-- identify what they have opened.  As a special case, an \"xref\" to an    -->\n<!-- \"mrow\" generates a knowl whose body is the containing \"md\", not just   -->\n<!-- the row.                                                               -->\n\n<!-- The \"b-original\" boolean is threaded down explicitly through every     -->\n<!-- body, wrapped-content, and container template (e.g. \"sidebyside\").     -->\n<!-- XSLT 1.0 has no tunnel parameter, so each forwarding must be written   -->\n<!-- by hand and a missing one is a real source of bugs.  The \"block-type\"  -->\n<!-- parameter (values 'visible', 'hidden', 'xref') is threaded the same    -->\n<!-- way, and is also forwarded down to Sage cells so they can configure    -->\n<!-- themselves correctly when they live inside a knowl.                    -->\n\n<!-- The per-element templates that customize the production of a block     -->\n<!-- are:                                                                   -->\n\n<!-- (1) \"is-hidden\": returns the string 'true' or 'false'.  Decides        -->\n<!-- whether the block is born hidden.  Often a fixed value; sometimes tied -->\n<!-- to a publisher option.                                                 -->\n\n<!-- (2) \"body-element\", \"body-css-class\": the outermost HTML element       -->\n<!-- wrapping the block, and its CSS classes.  The body-element must be a   -->\n<!-- block-level HTML element, because it is the outer container of knowl   -->\n<!-- content and the knowl-open Javascript expects exactly one enclosing    -->\n<!-- element.                                                               -->\n\n<!-- (3) \"heading-birth\": the heading used both when the block is drawn     -->\n<!-- visibly on a page and as the clickable text of a born-hidden knowl.    -->\n\n<!-- (4) \"heading-xref-knowl\": the heading used at the top of a             -->\n<!-- cross-reference knowl.  Sometimes richer than \"heading-birth\"; for     -->\n<!-- example, a cross-reference to a list item benefits from naming the     -->\n<!-- enclosing list and the item's number.                                  -->\n\n<!-- (5) \"body\": the generic body template, defined much later in this      -->\n<!-- file.  It emits the body-element wrapper, an @id when appropriate      -->\n<!-- (visible original; not on a born-hidden wrapper, since the @id is on   -->\n<!-- the summary instead; never in a duplicate), a heading-birth (visible   -->\n<!-- case) or heading-xref-knowl (xref case), and then the inner content    -->\n<!-- via \"wrapped-content\".                                                 -->\n\n<!-- (6) \"wrapped-content\": the inner content of the block.  Most blocks    -->\n<!-- simply apply-templates over their children; some restrict the          -->\n<!-- selection in order to avoid pulling in elements such as \"prelude\" or   -->\n<!-- \"postlude\", which the body template instead places outside the block.  -->\n\n<xsl:template match=\"&REMARK-LIKE;|&COMPUTATION-LIKE;|&DEFINITION-LIKE;|&ASIDE-LIKE;|poem|&FIGURE-LIKE;|assemblage|blockquote|paragraphs|&GOAL-LIKE;|&OPENPROBLEM-LIKE;|&EXAMPLE-LIKE;|subexercises|exercisegroup|exercise|&PROJECT-LIKE;|task|&SOLUTION-LIKE;|&DISCUSSION-LIKE;|&THEOREM-LIKE;|&AXIOM-LIKE;|&PROOF-LIKE;|case|contributor|biblio|biblio/note|interactive/instructions|gi|p|li|md[mrow]|fragment\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n    <xsl:variable name=\"hidden\">\n        <xsl:apply-templates select=\".\" mode=\"is-hidden\" />\n    </xsl:variable>\n    <xsl:choose>\n        <!-- born-hidden case -->\n        <xsl:when test=\"$hidden = 'true'\">\n            <xsl:apply-templates select=\".\" mode=\"born-hidden\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- born-visible case -->\n        <xsl:otherwise>\n            <!-- pass-thru of b-original mandatory -->\n            <xsl:apply-templates select=\".\" mode=\"born-visible\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"born-visible\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"body\">\n        <xsl:with-param name=\"block-type\" select=\"'visible'\" />\n        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"born-hidden\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n\n    <!-- newline inserted to encourage formatted output -->\n    <xsl:text>&#xa;</xsl:text>\n    <details>\n        <!-- put an HTML id as a target of cross-references, etc, -->\n        <!-- but only when this is original content.  In other    -->\n        <!-- words, not when a consituent of an xref knowl        -->\n        <xsl:if test=\"$b-original\">\n            <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n        </xsl:if>\n        <!-- put relevant class names on \"details\" to help with styling -->\n        <xsl:attribute name=\"class\">\n            <xsl:apply-templates select=\".\" mode=\"body-css-class\"/>\n            <xsl:text> born-hidden-knowl</xsl:text>\n        </xsl:attribute>\n        <!-- the clickable that is visible on the page -->\n        <summary class=\"knowl__link\">\n           <xsl:apply-templates select=\".\" mode=\"heading-birth\">\n               <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n           </xsl:apply-templates>\n        </summary>\n        <!-- the content of the knowl, to be revealed later        -->\n        <!-- NB: the Javascript controlling the animation of the   -->\n        <!-- open/close of a knowl, presumes it begins with an     -->\n        <!-- element enclosing the content.  This is guaranteed by -->\n        <!-- the \"body\" template via the \"body-element\" template.  -->\n        <xsl:apply-templates select=\".\" mode=\"body\">\n            <xsl:with-param name=\"block-type\" select=\"'hidden'\" />\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n    </details>\n</xsl:template>\n\n<!-- ######### -->\n<!-- Footnotes -->\n<!-- ######### -->\n\n<!-- A table note (\"tn\") drops only its superscript letter mark at the -->\n<!-- cell location, linked to the note text collected below the table  -->\n<!-- in the \"tabular-inclusion\" template.  Letters count per-tabular   -->\n<!-- in document order (Notes to tables: CMoS 18th ed., 3.77-3.81;     -->\n<!-- specific notes at 3.80).  Adjacency is the presentation: a note   -->\n<!-- sits just below its table, so there is no knowl.                  -->\n<xsl:template match=\"tabular//tn\">\n    <xsl:variable name=\"note-number\">\n        <xsl:apply-templates select=\".\" mode=\"number\"/>\n    </xsl:variable>\n    <sup class=\"tablenote-mark\">\n        <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n        <a>\n            <xsl:attribute name=\"href\">\n                <xsl:text>#</xsl:text>\n                <xsl:apply-templates select=\".\" mode=\"html-id\"/>\n                <xsl:text>-note</xsl:text>\n            </xsl:attribute>\n            <xsl:attribute name=\"aria-label\">\n                <xsl:text>Go to table note </xsl:text>\n                <xsl:value-of select=\"$note-number\"/>\n            </xsl:attribute>\n            <i>\n                <xsl:value-of select=\"$note-number\"/>\n            </i>\n        </a>\n    </sup>\n</xsl:template>\n\n<!-- Currently implemented as a details html element with no guardrails   -->\n<!-- on nested content. Other footnotes, block content, etc... will all   -->\n<!-- be rendered, but perhaps not well. Caveat emptor.                    -->\n<xsl:template match=\"fn\">\n    <details class=\"ptx-footnote\" aria-live=\"polite\">\n        <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n        <!-- A superscript number, as the clickable content -->\n        <summary class=\"ptx-footnote__number\">\n            <xsl:attribute name=\"title\">\n                <xsl:apply-templates select=\".\" mode=\"tooltip-text\" />\n            </xsl:attribute>\n            <xsl:apply-templates select=\".\" mode=\"heading-birth\"/>\n        </summary>\n        <!-- the content of the knowl, to be revealed later        -->\n        <!-- NB: the Javascript controlling the animation of the   -->\n        <!-- open/close of a knowl, presumes it begins with an     -->\n        <!-- element enclosing the content.  This is guaranteed by -->\n        <!-- the \"body\" template via the \"body-element\" template.  -->\n        <xsl:apply-templates select=\".\" mode=\"body\"/>\n    </details>\n    <!-- xref-knowl content is manufactured elsewhere in a brute-force   -->\n    <!-- fashion.  This would be a better place to ensure that every     -->\n    <!--  \"fn\" had its content produced in the right way no matter what. -->\n</xsl:template>\n\n<!-- ##################### -->\n<!-- Block Implementations -->\n<!-- ##################### -->\n\n<!-- We devise the more straightforward blocks first, -->\n<!-- saving the exceptions for subsequent exposition  -->\n\n<!-- REMARK-LIKE -->\n<!-- A simple block with full titles and generic contents -->\n\n<!-- Born-hidden behavior is configurable -->\n<xsl:template match=\"&REMARK-LIKE;\" mode=\"is-hidden\">\n    <xsl:value-of select=\"$knowl-remark = 'yes'\" />\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"&REMARK-LIKE;\" mode=\"body-element\">\n    <xsl:text>article</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"&REMARK-LIKE;\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n    <xsl:text> remark-like</xsl:text>\n</xsl:template>\n\n<!-- When born use this heading -->\n<xsl:template match=\"&REMARK-LIKE;\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"&REMARK-LIKE;\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Primary content of generic \"body\" template  -->\n<!-- Pass along b-original flag                  -->\n<!-- Potentially knowled, may have statement     -->\n<!-- with Sage, so pass block type               -->\n<!-- Simply process contents, could restict here -->\n<xsl:template match=\"&REMARK-LIKE;\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:apply-templates select=\"*\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n        <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n\n<!-- COMPUTATION-LIKE -->\n<!-- A simple block with full titles, but more substantial contents -->\n\n<!-- Born-hidden behavior is configurable -->\n<xsl:template match=\"&COMPUTATION-LIKE;\" mode=\"is-hidden\">\n    <xsl:value-of select=\"$knowl-remark = 'yes'\" />\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"&COMPUTATION-LIKE;\" mode=\"body-element\">\n    <xsl:text>article</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"&COMPUTATION-LIKE;\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n    <xsl:text> computation-like</xsl:text>\n</xsl:template>\n\n<!-- When born use this heading -->\n<xsl:template match=\"&COMPUTATION-LIKE;\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"&COMPUTATION-LIKE;\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Primary content of generic \"body\" template  -->\n<!-- Pass along b-original flag                  -->\n<!-- Potentially knowled, may have statement     -->\n<!-- with Sage, so pass block type               -->\n<!-- Simply process contents, could restict here -->\n<xsl:template match=\"&COMPUTATION-LIKE;\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:apply-templates select=\"*\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n        <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n\n<!-- OPENPROBLEM-LIKE -->\n<!-- A simple block with full titles, but more substantial contents -->\n\n<!-- Born-hidden behavior is configurable -->\n<xsl:template match=\"&OPENPROBLEM-LIKE;\" mode=\"is-hidden\">\n    <xsl:value-of select=\"false()\"/>\n    <!-- <xsl:value-of select=\"$knowl-remark = 'yes'\" /> -->\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"&OPENPROBLEM-LIKE;\" mode=\"body-element\">\n    <xsl:text>article</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"&OPENPROBLEM-LIKE;\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n    <xsl:text> openproblem-like</xsl:text>\n</xsl:template>\n\n<!-- When born use this heading -->\n<xsl:template match=\"&OPENPROBLEM-LIKE;\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"&OPENPROBLEM-LIKE;\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Primary content of generic \"body\" template  -->\n<!-- Pass along b-original flag                  -->\n<!-- Potentially knowled, may have statement     -->\n<!-- with Sage, so pass block type               -->\n<!-- Simply process contents, could restict here -->\n\n<!-- NB: we explicitly ignore \"prelude\" and      -->\n<!-- \"postlude\" by being very careful about what -->\n<!-- we process.  A more general template will   -->\n<!-- pick them up *only* when it is original     -->\n<!-- content, and place outside the block.       -->\n\n<xsl:template match=\"&OPENPROBLEM-LIKE;\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:choose>\n        <!-- structured by \"task\" so let templates for tasks work -->\n        <!-- down to terminal task with SOLUTION-LIKE appendages  -->\n        <xsl:when test=\"task\">\n            <xsl:apply-templates select=\"introduction|task|conclusion\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- structured with \"statement\" and DISCUSSION-LIKE  -->\n        <!-- (We don't entertain bare content for a statement -->\n        <xsl:otherwise>\n            <xsl:apply-templates select=\"statement|&DISCUSSION-LIKE;\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- DEFINITION-LIKE -->\n<!-- A simple block with full titles and generic contents -->\n\n<!-- Born-hidden behavior is configurable -->\n<xsl:template match=\"&DEFINITION-LIKE;\" mode=\"is-hidden\">\n    <xsl:value-of select=\"$knowl-definition = 'yes'\" />\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"&DEFINITION-LIKE;\" mode=\"body-element\">\n    <xsl:text>article</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"&DEFINITION-LIKE;\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n    <xsl:text> definition-like</xsl:text>\n</xsl:template>\n\n<!-- When born use this heading -->\n<xsl:template match=\"&DEFINITION-LIKE;\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"&DEFINITION-LIKE;\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Primary content of generic \"body\" template  -->\n<!-- Pass along b-original flag                  -->\n<!-- Potentially knowled, may have statement     -->\n<!-- with Sage, so pass block type               -->\n<!-- Simply process contents, could restict here -->\n<xsl:template match=\"&DEFINITION-LIKE;\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:apply-templates select=\"*\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n        <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n\n<!-- ASIDE-LIKE -->\n<!-- A simple block with a title (no number) and generic contents -->\n\n<!-- Rendered as a born hidden knowl -->\n<xsl:template match=\"&ASIDE-LIKE;\" mode=\"is-hidden\">\n    <xsl:text>true</xsl:text>\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"&ASIDE-LIKE;\" mode=\"body-element\">\n    <xsl:text>aside</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"&ASIDE-LIKE;\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n    <xsl:text> aside-like</xsl:text>\n</xsl:template>\n\n<!-- When born use this heading -->\n<xsl:template match=\"&ASIDE-LIKE;\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full-implicit-number\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"&ASIDE-LIKE;\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full-implicit-number\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Primary content of generic \"body\" template   -->\n<!-- Pass along b-original flag                   -->\n<!-- Potentially knowled, may have statement      -->\n<!-- with Sage, so pass block type                -->\n<!-- Simply process contents, could restrict here -->\n<xsl:template match=\"&ASIDE-LIKE;\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n\n    <!-- Coordinate with schema, since we enforce it here -->\n    <xsl:apply-templates select=\"p|blockquote|pre|image|video|program|console|tabular\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n        <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n\n<!-- Poem -->\n<!-- Titled, not numbered, but with an author's name. -->\n<!-- Knowled as a cross-reference target, but never born  -->\n<!-- hidden (for now particular reason).  A complicated  -->\n<!-- implementation, which should rely more on CSS. -->\n\n<!-- Never born-hidden, other devices partially hide -->\n<xsl:template match=\"poem\" mode=\"is-hidden\">\n    <xsl:text>false</xsl:text>\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"poem\" mode=\"body-element\">\n    <xsl:text>article</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"poem\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n</xsl:template>\n\n<!-- When born use this heading -->\n<xsl:template match=\"poem\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-title\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"poem\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-title\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Primary content of generic \"body\" template   -->\n<!-- Pass along b-original flag                   -->\n<!-- Simply process contents, could restrict here -->\n<xsl:template match=\"poem\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\"stanza\" >\n        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n    </xsl:apply-templates>\n    <!-- author comes early in schema, but is rendered below -->\n    <xsl:apply-templates select=\"author\" >\n        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- ################### -->\n<!-- Structured by Lines -->\n<!-- ################### -->\n\n<!-- The HTML-specific line separator for use by   -->\n<!-- the abstract template for a \"line\" elent used -->\n<!-- to (optionally) structure certain elements.   -->\n\n<xsl:template name=\"line-separator\">\n    <br/>\n</xsl:template>\n\n<!-- ###### -->\n<!-- Poetry -->\n<!-- ###### -->\n\n<!-- TODO: Address GitHub issues regarding poetry output:   -->\n<!-- https://github.com/BooksHTML/mathbook-assets/issues/65 -->\n\n<xsl:template match=\"poem/author\">\n    <div>\n        <xsl:attribute name=\"class\">\n            <xsl:text>author</xsl:text>\n            <xsl:text> </xsl:text>\n            <xsl:apply-templates select=\".\" mode=\"poem-halign\"/>\n        </xsl:attribute>\n        <xsl:apply-templates/>\n    </div>\n</xsl:template>\n\n<xsl:template match=\"stanza\">\n    <div class=\"stanza\">\n        <xsl:apply-templates select=\".\" mode=\"heading-title\"/>\n        <xsl:apply-templates select=\"line\"/>\n    </div>\n</xsl:template>\n\n<xsl:template match=\"stanza/line\">\n    <xsl:variable name=\"alignment\">\n        <xsl:apply-templates select=\".\" mode=\"poem-halign\"/>\n    </xsl:variable>\n    <xsl:variable name=\"indentation\">\n        <xsl:apply-templates select=\".\" mode=\"poem-indent\"/>\n    </xsl:variable>\n    <div>\n        <xsl:attribute name=\"class\">\n            <xsl:text>line</xsl:text>\n            <xsl:text> </xsl:text>\n            <xsl:apply-templates select=\".\" mode=\"poem-halign\"/>\n        </xsl:attribute>\n        <!-- Left Alignment: Indent from Left -->\n        <xsl:if test=\"$alignment='left'\">\n            <xsl:call-template name=\"poem-line-indenting\">\n                <xsl:with-param name=\"count\" select=\"$indentation\"/>\n            </xsl:call-template>\n        </xsl:if>\n        <!-- Center Alignment: Ignore Indentation -->\n        <xsl:apply-templates/>\n        <!-- Right Alignment: Indent from Right -->\n        <xsl:if test=\"$alignment='right'\">\n            <xsl:call-template name=\"poem-line-indenting\">\n                <xsl:with-param name=\"count\" select=\"$indentation\"/>\n            </xsl:call-template>\n        </xsl:if>\n    </div>\n</xsl:template>\n\n<xsl:template name=\"poem-line-indenting\">\n    <xsl:param name=\"count\"/>\n    <xsl:choose>\n        <xsl:when test=\"(0 >= $count)\"/>\n        <xsl:otherwise>\n            <span class=\"tab\"/>\n            <xsl:call-template name=\"poem-line-indenting\">\n                <xsl:with-param name=\"count\" select=\"$count - 1\"/>\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- FIGURE-LIKE -->\n<!-- Captioned, titled (heading) -->\n\n<!-- Born-hidden behavior is configurable -->\n<!-- On a per-element basis               -->\n<xsl:template match=\"figure\" mode=\"is-hidden\">\n    <xsl:value-of select=\"$knowl-figure = 'yes'\" />\n</xsl:template>\n\n<xsl:template match=\"table\" mode=\"is-hidden\">\n    <xsl:value-of select=\"$knowl-table = 'yes'\" />\n</xsl:template>\n\n<xsl:template match=\"listing\" mode=\"is-hidden\">\n    <xsl:value-of select=\"$knowl-listing = 'yes'\" />\n</xsl:template>\n\n<xsl:template match=\"list\" mode=\"is-hidden\">\n    <xsl:value-of select=\"$knowl-list = 'yes'\" />\n</xsl:template>\n\n<!-- The optionally born-hidden items can be panels of -->\n<!-- a sidebyside, where we should not be hiding them. -->\n<!-- A figure wrapping the sidebyside could be knowled -->\n<!-- if they need to be hidden.                        -->\n<xsl:template match=\"sidebyside/figure|sidebyside/table|sidebyside/listing|sidebyside/list\" mode=\"is-hidden\">\n    <xsl:value-of select=\"false()\" />\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<!-- Natural HTML element      -->\n<xsl:template match=\"&FIGURE-LIKE;\" mode=\"body-element\">\n    <xsl:text>figure</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"figure|listing\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n    <xsl:text> figure-like</xsl:text>\n</xsl:template>\n<!-- a table of data will use this class when -->\n<!-- the title is placed above the tabular    -->\n<xsl:template match=\"table|list\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n    <xsl:text> table-like</xsl:text>\n</xsl:template>\n\n<!-- TODO - sort out title/caption -->\n<!-- Use title for xref-link text  -->\n\n<!-- When born use this heading -->\n<!-- no heading, since captioned -->\n<xsl:template match=\"&FIGURE-LIKE;\" mode=\"heading-birth\" />\n\n<!-- Heading for interior of xref-knowl content -->\n<!-- no heading, since captioned -->\n<xsl:template match=\"&FIGURE-LIKE;\" mode=\"heading-xref-knowl\" />\n\n<!-- Primary content of generic \"body\" template   -->\n<!-- Pass along b-original flag                   -->\n<!-- Handle \"caption\" exceptionally               -->\n<xsl:template match=\"&FIGURE-LIKE;\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n\n    <!-- Subnumbered caption/title go below, to help with alignment -->\n    <xsl:variable name=\"fig-placement\">\n        <xsl:apply-templates select=\".\" mode=\"figure-placement\"/>\n    </xsl:variable>\n    <xsl:variable name=\"b-place-title-below\" select=\"($fig-placement = 'subnumber') or ($fig-placement = 'panel')\"/>\n    <xsl:choose>\n        <!-- caption at the bottom, always -->\n        <xsl:when test=\"self::figure\">\n            <xsl:apply-templates select=\"*\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n            <xsl:apply-templates select=\".\" mode=\"figure-caption\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- caption at the top as per CMoS if not subnumbered -->\n        <xsl:when test=\"self::listing\">\n            <xsl:if test=\"not($b-place-title-below)\">\n                <xsl:apply-templates select=\".\" mode=\"figure-caption\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                </xsl:apply-templates>\n            </xsl:if>\n            <div class=\"listing__contents\">\n                <xsl:apply-templates select=\"program|console\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                    <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                </xsl:apply-templates>\n            </div>\n            <xsl:if test=\"$b-place-title-below\">\n                <xsl:apply-templates select=\".\" mode=\"figure-caption\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                </xsl:apply-templates>\n            </xsl:if>\n        </xsl:when>\n        <!-- table only contains a tabular; if not subnumbered  -->\n        <!-- then title is displayed before data/tabular        -->\n        <xsl:when test=\"self::table\">\n            <xsl:if test=\"not($b-place-title-below)\">\n                <xsl:apply-templates select=\".\" mode=\"figure-caption\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                </xsl:apply-templates>\n            </xsl:if>\n            <xsl:apply-templates select=\"tabular\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n            <xsl:if test=\"$b-place-title-below\">\n                <xsl:apply-templates select=\".\" mode=\"figure-caption\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                </xsl:apply-templates>\n            </xsl:if>\n        </xsl:when>\n        <!-- \"title\" at the top, subnumber at the bottom -->\n        <xsl:when test=\"self::list\">\n            <xsl:if test=\"not($b-place-title-below)\">\n                <xsl:apply-templates select=\".\" mode=\"figure-caption\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                </xsl:apply-templates>\n            </xsl:if>\n            <div class=\"named-list-content\">\n                <xsl:apply-templates select=\"introduction|ol|ul|dl|conclusion\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                    <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                </xsl:apply-templates>\n            </div>\n            <xsl:if test=\"$b-place-title-below\">\n                <xsl:apply-templates select=\".\" mode=\"figure-caption\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                </xsl:apply-templates>\n            </xsl:if>\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- Assemblage -->\n<!-- A simple block with an optional title and limited contents -->\n\n<!-- Never born-hidden, simply by design -->\n<xsl:template match=\"assemblage\" mode=\"is-hidden\">\n    <xsl:text>false</xsl:text>\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"assemblage\" mode=\"body-element\">\n    <xsl:text>article</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"assemblage\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n    <xsl:text> assemblage-like</xsl:text>\n</xsl:template>\n\n<!-- When born use this heading -->\n<xsl:template match=\"assemblage\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-title\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"assemblage\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-title\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Primary content of generic \"body\" template    -->\n<!-- Pass along b-original flag                    -->\n<!-- Simply process contents, restrictions match   -->\n<!-- schema, except schema says no captioned items -->\n<!-- in the side-by-side                           -->\n<xsl:template match=\"assemblage\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n    <!-- Coordinate with schema, since we enforce it here -->\n    <xsl:apply-templates select=\"p|blockquote|pre|image|video|program|console|tabular|sidebyside|sbsgroup\" >\n        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n\n<!-- Block Quote -->\n<!-- A very simple block with just an enclosing div -->\n\n<!-- Never born-hidden, does not make sense -->\n<xsl:template match=\"blockquote\" mode=\"is-hidden\">\n    <xsl:text>false</xsl:text>\n</xsl:template>\n\n<!-- Overall enclosing element     -->\n<!-- Natural HTML element, usually -->\n<xsl:template match=\"blockquote\" mode=\"body-element\">\n    <xsl:text>blockquote</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"blockquote\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n</xsl:template>\n\n<!-- When born use this heading         -->\n<!-- Never hidden, never gets a heading -->\n<xsl:template match=\"blockquote\" mode=\"heading-birth\" />\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"blockquote\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-type\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Primary content of generic \"body\" template   -->\n<!-- Pass along b-original flag                   -->\n<!-- Simply process contents, could restrict here -->\n<xsl:template match=\"blockquote\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\"*\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n\n<!-- Paragraphs -->\n<!-- Technically a division, but small enough to xref knowl -->\n\n<!-- Never born-hidden, does not make sense -->\n<xsl:template match=\"paragraphs\" mode=\"is-hidden\">\n    <xsl:text>false</xsl:text>\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"paragraphs\" mode=\"body-element\">\n    <xsl:text>section</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"paragraphs\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n</xsl:template>\n\n<!-- When born use this heading -->\n<xsl:template match=\"paragraphs\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-title-paragraphs\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"paragraphs\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-title-paragraphs\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Primary content of generic \"body\" template   -->\n<!-- Pass along b-original flag                   -->\n<!-- Simply process contents, could restrict here -->\n<xsl:template match=\"paragraphs\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\"*\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n\n<!-- GOAL-LIKE -->\n<!-- Special, and restricted, blocks -->\n\n<!-- Born-hidden behavior is configurable -->\n<xsl:template match=\"objectives\" mode=\"is-hidden\">\n    <xsl:value-of select=\"$knowl-objectives = 'yes'\" />\n</xsl:template>\n<xsl:template match=\"outcomes\" mode=\"is-hidden\">\n    <xsl:value-of select=\"$knowl-outcomes = 'yes'\" />\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"&GOAL-LIKE;\" mode=\"body-element\">\n    <xsl:text>article</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"&GOAL-LIKE;\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n    <xsl:text> goal-like</xsl:text>\n</xsl:template>\n\n<!-- When born use this heading -->\n<xsl:template match=\"&GOAL-LIKE;\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full-implicit-number\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"&GOAL-LIKE;\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Primary content of generic \"body\" template        -->\n<!-- Pass along b-original flag                        -->\n<!-- Simply process contents, with partial restriction -->\n<xsl:template match=\"&GOAL-LIKE;\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\"introduction|ol|ul|dl|conclusion\" >\n        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n\n<!-- The next few implementations have hints, answers, -->\n<!-- or solutions hanging off the ends.  Examples may  -->\n<!-- elect to have these.  Exercises may have them and -->\n<!-- they are more configurable.  Projects may have    -->\n<!-- them prima facie, or associated with tasks.  In   -->\n<!-- all cases the hints, answers, and solutions are   -->\n<!-- presented as knowls.                              -->\n\n<!-- EXAMPLE-LIKE -->\n<!-- A simple block, but with possible appendages -->\n\n<!-- Born-hidden behavior is configurable -->\n<xsl:template match=\"&EXAMPLE-LIKE;\" mode=\"is-hidden\">\n    <xsl:value-of select=\"$knowl-example = 'yes'\" />\n    <!-- Preserving a way to not knowl anything in a worksheet -->\n    <!--\n    <xsl:choose>\n        <xsl:when test=\"ancestor::worksheet\">\n            <xsl:value-of select=\"false()\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"$knowl-example = 'yes'\" />\n        </xsl:otherwise>\n    </xsl:choose>\n    -->\n </xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"&EXAMPLE-LIKE;\" mode=\"body-element\">\n    <xsl:text>article</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"&EXAMPLE-LIKE;\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n    <xsl:text> example-like</xsl:text>\n</xsl:template>\n\n<!-- When born use this heading -->\n<xsl:template match=\"&EXAMPLE-LIKE;\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"&EXAMPLE-LIKE;\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Primary content of generic \"body\" template  -->\n<!-- Pass along b-original flag                  -->\n<!-- Potentially knowled, may have statement     -->\n<!-- with Sage, so pass block type               -->\n<!-- Process according to structure              -->\n<xsl:template match=\"&EXAMPLE-LIKE;\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:choose>\n        <!-- structured by \"task\" so let templates for tasks work -->\n        <!-- down to terminal task with SOLUTION-LIKE appendages  -->\n        <xsl:when test=\"task\">\n            <xsl:apply-templates select=\"introduction|task|conclusion\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- structured with \"statement\" and SOLUTION-LIKE, -->\n        <!-- or just bare content for a statement           -->\n        <xsl:otherwise>\n            <xsl:apply-templates select=\".\" mode=\"exercise-components\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                <xsl:with-param name=\"b-has-statement\" select=\"true()\"/>\n                <xsl:with-param name=\"b-has-hint\"      select=\"true()\"/>\n                <xsl:with-param name=\"b-has-answer\"    select=\"true()\"/>\n                <xsl:with-param name=\"b-has-solution\"  select=\"true()\"/>\n            </xsl:apply-templates>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- Subexercises -->\n<!-- A pseudo-division, implemented more like an \"exercisegroup\" -->\n\n<!-- Never born-hidden, does not make sense -->\n<xsl:template match=\"subexercises\" mode=\"is-hidden\">\n    <xsl:text>false</xsl:text>\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<!-- Natural HTML element      -->\n<xsl:template match=\"subexercises\" mode=\"body-element\">\n    <xsl:text>article</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"subexercises\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n</xsl:template>\n\n<!-- When born use this heading         -->\n<!-- Never hidden, never gets a heading -->\n<xsl:template match=\"subexercises\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-title\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<!-- Not knowlizable, more like a division      -->\n<xsl:template match=\"subexercises\" mode=\"heading-xref-knowl\"/>\n\n<!-- Primary content of generic \"body\" template   -->\n<!-- Pass along b-original flag                   -->\n<!-- Simply process contents, could restrict here -->\n<!-- Mirror changes here into \"solutions\" below   -->\n<xsl:template match=\"subexercises\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\"/>\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\"introduction\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n    <xsl:apply-templates select=\"exercise|exercisegroup\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n    <xsl:apply-templates select=\"conclusion\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- For solutions divisions, we mimic and reuse some of the above -->\n<!-- The generic driver in pretext-common.xsl decides if anything -->\n<!-- appears at all, and renders the items; the wrapping here      -->\n<xsl:template match=\"subexercises\" mode=\"present-solutions-container\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:param name=\"b-has-statement\"/>\n    <xsl:param name=\"content\"/>\n\n    <article class=\"subexercises\">\n        <xsl:apply-templates select=\".\" mode=\"heading-title\">\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n        <xsl:if test=\"$b-has-statement\">\n            <xsl:apply-templates select=\"introduction\">\n                <xsl:with-param name=\"b-original\" select=\"false()\" />\n            </xsl:apply-templates>\n        </xsl:if>\n        <xsl:copy-of select=\"$content\"/>\n        <xsl:if test=\"$b-has-statement\">\n            <xsl:apply-templates select=\"conclusion\">\n                <xsl:with-param name=\"b-original\" select=\"false()\" />\n            </xsl:apply-templates>\n        </xsl:if>\n    </article>\n</xsl:template>\n\n<!-- Exercise Group -->\n<!-- A very simple block with just an enclosing div -->\n\n<!-- Never born-hidden, does not make sense -->\n<xsl:template match=\"exercisegroup\" mode=\"is-hidden\">\n    <xsl:text>false</xsl:text>\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<!-- Natural HTML element      -->\n<xsl:template match=\"exercisegroup\" mode=\"body-element\">\n    <xsl:text>div</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"exercisegroup\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n</xsl:template>\n\n<!-- When born use this heading         -->\n<!-- Never hidden, never gets a heading -->\n<xsl:template match=\"exercisegroup\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-title\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"exercisegroup\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Primary content of generic \"body\" template   -->\n<!-- Pass along b-original flag                   -->\n<!-- Simply process contents, could restrict here -->\n<!-- Mirror changes here into \"solutions\" below   -->\n<xsl:template match=\"exercisegroup\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\"introduction\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n    <div>\n        <xsl:attribute name=\"class\">\n            <xsl:text>exercisegroup-exercises</xsl:text>\n            <xsl:variable name=\"cols-class-name\">\n                <!-- HTML-specific, but in pretext-common.xsl -->\n                <xsl:apply-templates select=\".\" mode=\"number-cols-CSS-class\"/>\n            </xsl:variable>\n            <xsl:if test=\"not($cols-class-name = '')\">\n                <xsl:text> </xsl:text>\n                <xsl:value-of select=\"$cols-class-name\"/>\n            </xsl:if>\n        </xsl:attribute>\n        <xsl:apply-templates select=\"exercise\">\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n    </div>\n    <xsl:apply-templates select=\"conclusion\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- For solutions divisions, we mimic and reuse some of the above; -->\n<!-- the generic driver in pretext-common.xsl renders the items     -->\n<xsl:template match=\"exercisegroup\" mode=\"present-solutions-container\">\n    <xsl:param name=\"b-has-statement\"/>\n    <xsl:param name=\"content\"/>\n\n    <div class=\"exercisegroup\">\n        <xsl:if test=\"$b-has-statement\">\n            <xsl:apply-templates select=\"introduction\">\n                <xsl:with-param name=\"b-original\" select=\"false()\" />\n            </xsl:apply-templates>\n        </xsl:if>\n        <div>\n            <xsl:attribute name=\"class\">\n                <xsl:text>exercisegroup-exercises</xsl:text>\n                <xsl:variable name=\"cols-class-name\">\n                    <!-- HTML-specific, but in pretext-common.xsl -->\n                    <xsl:apply-templates select=\".\" mode=\"number-cols-CSS-class\"/>\n                </xsl:variable>\n                <xsl:if test=\"not($cols-class-name = '')\">\n                    <xsl:text> </xsl:text>\n                    <xsl:value-of select=\"$cols-class-name\"/>\n                </xsl:if>\n            </xsl:attribute>\n            <xsl:copy-of select=\"$content\"/>\n        </div>\n        <xsl:if test=\"$b-has-statement\">\n            <xsl:apply-templates select=\"conclusion\">\n                <xsl:with-param name=\"b-original\" select=\"false()\" />\n            </xsl:apply-templates>\n        </xsl:if>\n    </div>\n</xsl:template>\n\n<!-- Exercise -->\n<!-- Inline and divisional, with appendages -->\n\n<!-- Born-hidden behavior is configurable   -->\n<!-- Note match first on inline first, override if divisional -->\n<xsl:template match=\"exercise\" mode=\"is-hidden\">\n    <xsl:value-of select=\"$knowl-exercise-inline = 'yes'\"/>\n</xsl:template>\n<xsl:template match=\"exercises//exercise\" mode=\"is-hidden\">\n    <xsl:value-of select=\"$knowl-exercise-divisional = 'yes'\"/>\n</xsl:template>\n<xsl:template match=\"worksheet//exercise\" mode=\"is-hidden\">\n    <xsl:value-of select=\"$knowl-exercise-worksheet = 'yes'\"/>\n</xsl:template>\n<xsl:template match=\"reading-questions//exercise\" mode=\"is-hidden\">\n    <xsl:value-of select=\"$knowl-exercise-readingquestion = 'yes'\"/>\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"exercise\" mode=\"body-element\">\n    <xsl:text>article</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"exercise\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n    <xsl:text> exercise-like</xsl:text>\n</xsl:template>\n\n<!-- When born use this heading -->\n<!-- Note match first on inline, then divisional -->\n<xsl:template match=\"exercise[boolean(&INLINE-EXERCISE-FILTER;)]\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n<xsl:template match=\"exercises//exercise|worksheet//exercise|reading-questions//exercise\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-divisional-exercise-serial\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Used when headings are created in solutions sections, to make them backlinks -->\n<xsl:template match=\"exercise[boolean(&INLINE-EXERCISE-FILTER;)]\" mode=\"heading-solutions\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"b-make-link\" select=\"true()\"/>\n    </xsl:apply-templates>\n</xsl:template>\n<xsl:template match=\"exercises//exercise|worksheet//exercise|reading-questions//exercise\" mode=\"heading-solutions\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-divisional-exercise\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"b-make-link\" select=\"true()\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content  -->\n<!-- Note match first on inline, then divisional -->\n<xsl:template match=\"exercise[boolean(&INLINE-EXERCISE-FILTER;)]\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n<xsl:template match=\"exercises//exercise|worksheet//exercise|reading-questions//exercise\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-divisional-exercise-typed\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- An \"exercise\" or PROJECT-LIKE authored with a \"webwork\" element -->\n<!-- is always interactive, but for straight HTML output, it has one -->\n<!-- look and for hosting on Runestone it has a slightly different   -->\n<!-- look.  This template isolates this distinction for the core, or -->\n<!-- interior, of such an exercise.                                  -->\n<xsl:template match=\"exercise|&PROJECT-LIKE;\" mode=\"webwork-core\">\n    <xsl:param name=\"b-original\"/>\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:choose>\n        <xsl:when test=\"$b-host-runestone\">\n            <div class=\"ptx-runestone-container\">\n                <div class=\"runestone\" data-component=\"webwork\">\n                    <!-- Note that this id gets a suffix on div.exercise-wrapper, -->\n                    <!-- so Runestone can coordinate the outer exercise and the   -->\n                    <!-- inner webwork                                            -->\n                    <xsl:attribute name=\"id\">\n                        <xsl:apply-templates select=\".\" mode=\"runestone-id\"/>\n                    </xsl:attribute>\n                    <xsl:apply-templates select=\"introduction|webwork-reps|conclusion\">\n                        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                    </xsl:apply-templates>\n                </div>\n            </div>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\"introduction|webwork-reps|conclusion\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- Primary content of generic \"body\" template  -->\n<!-- Pass along b-original flag                  -->\n<!-- Potentially knowled, may have statement     -->\n<!-- with Sage, so pass block type               -->\n<!-- Process according to structure              -->\n<!-- Mirror changes here into \"solutions\" below  -->\n<xsl:template match=\"exercise\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:choose>\n        <!-- webwork case -->\n        <xsl:when test=\"webwork-reps\">\n            <xsl:apply-templates select=\".\" mode=\"webwork-core\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- MyOpenMath case -->\n        <xsl:when test=\"myopenmath\">\n            <xsl:apply-templates select=\"introduction|myopenmath|conclusion\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- STACK case -->\n        <xsl:when test=\"stack\">\n            <xsl:apply-templates select=\"introduction|stack|conclusion\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- structured by \"task\" so let templates for tasks work -->\n        <!-- down to terminal task with SOLUTION-LIKE appendages  -->\n        <xsl:when test=\"task\">\n            <!-- An \"exercise\" structured by task may electively be presented  -->\n            <!-- by a \"tabbed\" interface from Runestone components.            -->\n            <!-- *  Never for a \"worksheet\" - too messy for printing           -->\n            <!-- *  Not hitting PROJECT-LIKE here, see elsewhere               -->\n            <xsl:variable name=\"b-tabbed-tasks\" select=\"\n                (@pi:exercise-customization = 'divisional' and $b-html-tabbed-tasks-divisional) or\n                (@pi:exercise-customization = 'inline' and $b-html-tabbed-tasks-inline) or\n                (@pi:exercise-customization = 'reading' and $b-html-tabbed-tasks-reading)\"/>\n            <xsl:choose>\n                <xsl:when test=\"$b-tabbed-tasks\">\n                    <!-- Use tabbed viewer from Runestone Components -->\n                    <xsl:apply-templates select=\".\"  mode=\"tabbed-tasks\">\n                        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                    </xsl:apply-templates>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:apply-templates select=\"introduction|task|conclusion\">\n                        <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                        <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n                        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                    </xsl:apply-templates>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!--  -->\n        <!-- structured with \"statement\" and SOLUTION-LIKE, -->\n        <!-- or just bare content for a statement           -->\n        <!--  -->\n        <!-- inline                                        -->\n        <!-- only possibility to be knowled, so only time  -->\n        <!-- we pass block-type for Sage cells to react to -->\n        <xsl:when test=\"boolean(&INLINE-EXERCISE-FILTER;)\">\n            <xsl:apply-templates select=\".\"  mode=\"exercise-components\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                <xsl:with-param name=\"b-has-statement\" select=\"true()\" />\n                <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-inline-hint\" />\n                <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-inline-answer\" />\n                <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-inline-solution\" />\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- divisional -->\n        <xsl:when test=\"ancestor::exercises\">\n            <xsl:apply-templates select=\".\"  mode=\"exercise-components\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                <xsl:with-param name=\"b-has-statement\" select=\"true()\" />\n                <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-divisional-hint\" />\n                <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-divisional-answer\" />\n                <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-divisional-solution\" />\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- worksheet -->\n        <xsl:when test=\"ancestor::worksheet\">\n            <xsl:apply-templates select=\".\"  mode=\"exercise-components\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                <xsl:with-param name=\"b-has-statement\" select=\"true()\" />\n                <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-worksheet-hint\" />\n                <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-worksheet-answer\" />\n                <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-worksheet-solution\" />\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- reading -->\n        <xsl:when test=\"ancestor::reading-questions\">\n            <xsl:apply-templates select=\".\"  mode=\"exercise-components\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                <xsl:with-param name=\"b-has-statement\" select=\"true()\" />\n                <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-reading-hint\" />\n                <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-reading-answer\" />\n                <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-reading-solution\" />\n            </xsl:apply-templates>\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Project-LIKE -->\n<!-- A complex block, possibly structured with task -->\n\n<!-- Born-hidden behavior is configurable -->\n<xsl:template match=\"&PROJECT-LIKE;\" mode=\"is-hidden\">\n    <xsl:value-of select=\"$knowl-project = 'yes'\" />\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"&PROJECT-LIKE;\" mode=\"body-element\">\n    <xsl:text>article</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<!-- A project acting as a standalone printout is marked as such, so the -->\n<!-- stylesheet can treat it as the printable thing it is (for one, its   -->\n<!-- title gets a line of its own rather than running into the text).     -->\n<xsl:template match=\"&PROJECT-LIKE;\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n    <xsl:text> project-like</xsl:text>\n    <xsl:variable name=\"b-standalone-printout\">\n        <xsl:apply-templates select=\".\" mode=\"is-standalone-printout\"/>\n    </xsl:variable>\n    <xsl:if test=\"$b-standalone-printout = 'true'\">\n        <xsl:text> standalone-printout</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<!-- When born use this heading -->\n<!-- A standalone printout earns a print preview icon.  Unlike a printout, -->\n<!-- whose icon lives inside its heading, a project's icon is a sibling    -->\n<!-- following the heading: a project's title is a styled thing in its own -->\n<!-- right in several themes (a boxed legend, a filled bar), and the icon  -->\n<!-- has no business inside that.  As a floated sibling it lands just      -->\n<!-- below the title at the right, clear of the title's decoration.        -->\n<!-- NB: a project born hidden as a knowl (the publisher's knowl-project)  -->\n<!-- also comes through here, putting the icon in the knowl's \"summary\",   -->\n<!-- the only place it is visible while the knowl is closed.  The preview  -->\n<!-- javascript (\"flattenKnowledPrintout\") knows how to unpack that.       -->\n<xsl:template match=\"&PROJECT-LIKE;\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n    <xsl:variable name=\"b-standalone-printout\">\n        <xsl:apply-templates select=\".\" mode=\"is-standalone-printout\"/>\n    </xsl:variable>\n    <xsl:if test=\"$b-standalone-printout = 'true'\">\n        <xsl:apply-templates select=\".\" mode=\"standalone-printout-links\"/>\n    </xsl:if>\n</xsl:template>\n\n<!-- When used in solutions -->\n<xsl:template match=\"&PROJECT-LIKE;\" mode=\"heading-solutions\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"b-make-link\" select=\"true()\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"&PROJECT-LIKE;\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Primary content of generic \"body\" template  -->\n<!-- Pass along b-original flag                  -->\n<!-- Potentially knowled, may have statement    -->\n<!-- with Sage, so pass block type              -->\n<!-- Process according to structure              -->\n<!-- Mirror changes here into \"solutions\" below  -->\n<!-- NB: we explicitly ignore \"prelude\" and      -->\n<!-- \"postlude\" by being very careful about what -->\n<!-- we process.  A more general template will   -->\n<!-- pick them up *only* when it is original     -->\n<!-- content, and place outside the block.       -->\n<xsl:template match=\"&PROJECT-LIKE;\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:choose>\n        <!-- webwork case -->\n        <xsl:when test=\"webwork-reps\">\n            <xsl:apply-templates select=\".\" mode=\"webwork-core\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:when test=\"task\">\n            <!-- An \"PROJECT-LIKE\" structured by task may electively  -->\n            <!-- be presented by a \"tabbed\" interface from Runestone  -->\n            <!-- components. Note: this test is simpler than for  -->\n            <!-- \"exercise\" since we know we have a PROJECT-LIKE and  -->\n            <!-- do not need to consult @pi:exercise-customization.   -->\n            <xsl:choose>\n                <xsl:when test=\"$b-html-tabbed-tasks-project\">\n                    <!-- Use tabbed viewer from Runestone Components -->\n                    <xsl:apply-templates select=\".\"  mode=\"tabbed-tasks\">\n                        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                    </xsl:apply-templates>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:apply-templates select=\"introduction|task|conclusion\">\n                        <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                        <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n                        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                    </xsl:apply-templates>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\".\"  mode=\"exercise-components\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                <xsl:with-param name=\"b-has-statement\" select=\"true()\" />\n                <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-project-hint\" />\n                <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-project-answer\" />\n                <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-project-solution\" />\n            </xsl:apply-templates>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- For solutions divisions, we mimic and reuse some of the above -->\n<xsl:template match=\"exercise|&PROJECT-LIKE;\" mode=\"solutions\">\n    <xsl:param name=\"admit\"/>\n    <xsl:param name=\"heading-level\" />\n    <xsl:param name=\"b-has-statement\" />\n    <xsl:param name=\"b-has-hint\" />\n    <xsl:param name=\"b-has-answer\" />\n    <xsl:param name=\"b-has-solution\" />\n\n    <!-- we check for content, subject to selection of switches          -->\n    <!-- if there is no content, then we will not output anything at all -->\n     <xsl:variable name=\"dry-run\">\n        <xsl:apply-templates select=\".\" mode=\"dry-run\">\n            <xsl:with-param name=\"admit\" select=\"$admit\"/>\n            <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\" />\n            <xsl:with-param name=\"b-has-hint\" select=\"$b-has-hint\" />\n            <xsl:with-param name=\"b-has-answer\" select=\"$b-has-answer\" />\n            <xsl:with-param name=\"b-has-solution\" select=\"$b-has-solution\" />\n        </xsl:apply-templates>\n    </xsl:variable>\n\n    <xsl:if test=\"not($dry-run = '')\">\n        <!-- incongruities here are historical, -->\n        <!-- keeping the diff low-impact        -->\n        <!-- newline inserted to encourage formatted output -->\n        <xsl:text>&#xa;</xsl:text>\n        <xsl:element name=\"article\">\n            <xsl:attribute name=\"class\">\n                <xsl:choose>\n                    <xsl:when test=\"self::exercise\">\n                        <xsl:text>exercise-like</xsl:text>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:text>project-like</xsl:text>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:attribute>\n            <!-- A variety of headings -->\n            <xsl:apply-templates select=\".\" mode=\"heading-solutions\">\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n\n            <xsl:choose>\n                <!-- A native structured version (with \"task\") is handled  -->\n                <!-- by the generic drivers, in the \"otherwise\" below.     -->\n                <!-- WeBWorK static representations have their tasks and   -->\n                <!-- stages below \"webwork-reps/static\", out of reach of   -->\n                <!-- the drivers' selections, so they are handled here.    -->\n                <xsl:when test=\"webwork-reps/static/task\">\n                    <xsl:if test=\"$b-has-statement\">\n                        <xsl:apply-templates select=\"webwork-reps/static/introduction\">\n                            <xsl:with-param name=\"b-original\" select=\"false()\" />\n                            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                        </xsl:apply-templates>\n                    </xsl:if>\n                    <xsl:apply-templates select=\"webwork-reps/static/task\" mode=\"solutions\">\n                        <xsl:with-param name=\"b-original\" select=\"false()\" />\n                        <xsl:with-param name=\"heading-level\"   select=\"$heading-level + 1\"/>\n                        <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\" />\n                        <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-hint\" />\n                        <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-answer\" />\n                        <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-solution\" />\n                    </xsl:apply-templates>\n                    <xsl:if test=\"$b-has-statement\">\n                        <xsl:apply-templates select=\"webwork-reps/static/conclusion\">\n                            <xsl:with-param name=\"b-original\" select=\"false()\" />\n                            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                        </xsl:apply-templates>\n                    </xsl:if>\n                </xsl:when>\n                <!-- webwork with stages -->\n                <xsl:when test=\"webwork-reps/static/stage\">\n                    <xsl:apply-templates select=\"webwork-reps/static/stage\" mode=\"exercise-components\">\n                        <xsl:with-param name=\"b-original\" select=\"false()\" />\n                        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                        <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\" />\n                        <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-hint\" />\n                        <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-answer\" />\n                        <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-solution\" />\n                    </xsl:apply-templates>\n                </xsl:when>\n                <!-- webwork without tasks or stages -->\n                <xsl:when test=\"webwork-reps/static\">\n                    <xsl:apply-templates select=\"webwork-reps/static\" mode=\"exercise-components\">\n                        <xsl:with-param name=\"b-original\" select=\"false()\" />\n                        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                        <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\" />\n                        <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-hint\" />\n                        <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-answer\" />\n                        <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-solution\" />\n                    </xsl:apply-templates>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:apply-templates select=\".\"  mode=\"exercise-components\">\n                        <xsl:with-param name=\"b-original\" select=\"false()\" />\n                        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                        <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\" />\n                        <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-hint\" />\n                        <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-answer\" />\n                        <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-solution\" />\n                    </xsl:apply-templates>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:element>\n    </xsl:if>\n</xsl:template>\n\n<!-- Task -->\n<!-- A division of a PROJECT-LIKE, with appendages -->\n\n<!-- Born-hidden behavior is configurable -->\n<xsl:template match=\"task\" mode=\"is-hidden\">\n    <xsl:value-of select=\"$knowl-task = 'yes'\" />\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"task\" mode=\"body-element\">\n    <xsl:text>article</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"task\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n    <xsl:text> exercise-like</xsl:text>\n</xsl:template>\n\n<!-- When born use this heading -->\n<xsl:template match=\"task\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-list-number\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"task\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Primary content of generic \"body\" template   -->\n<!-- Pass along b-original flag                   -->\n<!-- Potentially knowled, may have statement      -->\n<!-- with Sage, so pass block type                -->\n<!-- Process according to structure               -->\n<!-- Mirror changes here into \"solutions\" below  -->\n<xsl:template match=\"task\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n\n    <!-- There are two types of \"task\".  Those in \"exercise\", PROJECT-LIKE, -->\n    <!-- or EXAMPLE-LIKE, have appendages that are SOLUTION-LIKE, with      -->\n    <!-- variable behavior.  Those in OPENPROBLEM-LIKE have appendages that -->\n    <!-- are DISCUSSION-LIKE with very predictable behavior.  Easier to     -->\n    <!-- switch on being inside OPENPROBLEM-LIKE.                           -->\n    <xsl:variable name=\"openproblem-container\" select=\"ancestor::*[&OPENPROBLEM-FILTER;]\"/>\n\n    <xsl:choose>\n        <!-- structured by \"task\" so let templates for tasks work down to   -->\n        <!-- terminal task with SOLUTION-LIKE or DISCUSSION-LIKE appendages -->\n        <xsl:when test=\"task\">\n            <xsl:apply-templates select=\"introduction|task|conclusion\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- then terminal task, may have DISCUSSION-LIKE to display -->\n        <!-- we do not entertain bare content as a \"statement\" here  -->\n        <xsl:when test=\"$openproblem-container\">\n            <xsl:apply-templates select=\"statement|&DISCUSSION-LIKE;\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- then terminal task, may have solutions to optionally display -->\n        <!--                                                              -->\n        <!-- NB: a \"task\" rediscovers its context in order to decide      -->\n        <!-- if SOLUTION-LIKE appendages are displayed at birth or not.   -->\n        <!-- A refactor could examine attributes placed by the            -->\n        <!-- pre-processor/assembly pass.                                 -->\n        <!--                                                              -->\n        <!-- It is tempting to think the context could be passed down     -->\n        <!-- through parameters, but each level of \"task\" goes through a  -->\n        <!-- default template, a \"body\" template, and a \"wrapped-content\" -->\n        <!-- template, which would require cluttering those with four     -->\n        <!-- *-has-* parameters, which are not relevant most of the time. -->\n        <xsl:otherwise>\n            <!-- We identify the container, in order to classify the    -->\n            <!-- group of switches that will control visibility of      -->\n            <!-- solutions.  Exactly one of these three is a singleton, -->\n            <!-- the other two are empty.                               -->\n            <xsl:variable name=\"exercise-container\" select=\"ancestor::exercise\"/>\n            <xsl:variable name=\"project-container\" select=\"ancestor::*[&PROJECT-FILTER;]\"/>\n            <xsl:variable name=\"example-container\" select=\"ancestor::*[&EXAMPLE-FILTER;]\"/>\n            <!-- Now booleans for exercises or projects, exercises below -->\n            <xsl:variable name=\"project\" select=\"boolean($project-container)\"/>\n            <xsl:variable name=\"example\" select=\"boolean($example-container)\"/>\n            <!-- We classify the four types of exercises further based -->\n            <!-- on location.  Inline is \"everything else\".            -->\n            <xsl:variable name=\"divisional\" select=\"$exercise-container and $exercise-container/ancestor::exercises\"/>\n            <xsl:variable name=\"worksheet\" select=\"$exercise-container and $exercise-container/ancestor::worksheet\"/>\n            <xsl:variable name=\"reading\" select=\"$exercise-container and $exercise-container/ancestor::reading-questions\"/>\n            <xsl:variable name=\"inline\" select=\"$exercise-container and not($divisional or $worksheet or $reading)\"/>\n            <!-- We have six booleans, exactly one is true, thus  -->\n            <!-- classifying a \"task\" by its employment/location. -->\n            <!-- We now form a set of three booleans, appropriate -->\n            <!-- for setting the task finds itself in.  There are -->\n            <!-- five author-supplied switches and an \"example\"   -->\n            <!-- *always* shows its solutions (not an \"exercise). -->\n            <xsl:variable name=\"b-has-hint\"\n                select=\"($inline and $b-has-inline-hint)  or\n                        ($project and $b-has-project-hint)  or\n                        ($divisional and $b-has-divisional-hint) or\n                        ($worksheet and $b-has-worksheet-hint)  or\n                        ($reading and $b-has-reading-hint)  or\n                         $example\"/>\n            <xsl:variable name=\"b-has-answer\"\n                select=\"($inline and $b-has-inline-answer)  or\n                        ($project and $b-has-project-answer)  or\n                        ($divisional and $b-has-divisional-answer) or\n                        ($worksheet and $b-has-worksheet-answer)  or\n                        ($reading and $b-has-reading-answer)  or\n                         $example\"/>\n            <xsl:variable name=\"b-has-solution\"\n                select=\"($inline and $b-has-inline-solution)  or\n                        ($project and $b-has-project-solution)  or\n                        ($divisional and $b-has-divisional-solution) or\n                        ($worksheet and $b-has-worksheet-solution)  or\n                        ($reading and $b-has-reading-solution)  or\n                         $example\"/>\n            <xsl:apply-templates select=\".\"  mode=\"exercise-components\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                <xsl:with-param name=\"b-has-statement\" select=\"true()\" />\n                <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-hint\" />\n                <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-answer\" />\n                <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-solution\" />\n            </xsl:apply-templates>\n        </xsl:otherwise>\n   </xsl:choose>\n</xsl:template>\n\n<!-- For solutions divisions, we mimic and reuse some of the above -->\n<xsl:template match=\"task\" mode=\"solutions\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:param name=\"b-has-statement\" />\n    <xsl:param name=\"b-has-hint\" />\n    <xsl:param name=\"b-has-answer\" />\n    <xsl:param name=\"b-has-solution\" />\n\n    <!-- we check for content, subject to selection of switches          -->\n    <!-- if there is no content, then we will not output anything at all -->\n     <xsl:variable name=\"dry-run\">\n        <xsl:apply-templates select=\".\" mode=\"dry-run\">\n            <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\" />\n            <xsl:with-param name=\"b-has-hint\" select=\"$b-has-hint\" />\n            <xsl:with-param name=\"b-has-answer\" select=\"$b-has-answer\" />\n            <xsl:with-param name=\"b-has-solution\" select=\"$b-has-solution\" />\n        </xsl:apply-templates>\n    </xsl:variable>\n\n    <xsl:if test=\"not($dry-run = '')\">\n        <article class=\"exercise-like\">\n            <xsl:apply-templates select=\".\" mode=\"duplicate-heading\">\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                <xsl:with-param name=\"b-make-link\" select=\"true()\"/>\n            </xsl:apply-templates>\n\n            <!-- the generic drivers dispatch a terminal task versus -->\n            <!-- one structured by further (nested) \"task\"            -->\n            <xsl:apply-templates select=\".\"  mode=\"exercise-components\">\n                <xsl:with-param name=\"b-original\" select=\"false()\" />\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\" />\n                <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-hint\" />\n                <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-answer\" />\n                <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-solution\" />\n            </xsl:apply-templates>\n        </article>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- SOLUTION-LIKE -->\n<!-- A simple item hanging off others -->\n\n<!-- Always born-hidden, by design -->\n<xsl:template match=\"&SOLUTION-LIKE;\" mode=\"is-hidden\">\n    <xsl:choose>\n        <xsl:when test=\"($knowl-example-solution = 'no') and ancestor::*[&EXAMPLE-FILTER;]\">\n            <xsl:text>false</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>true</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"&SOLUTION-LIKE;\" mode=\"body-element\">\n    <xsl:text>div</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"&SOLUTION-LIKE;\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n    <xsl:text> solution-like</xsl:text>\n</xsl:template>\n\n<!-- When born use this heading -->\n<xsl:template match=\"&SOLUTION-LIKE;\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <!-- consult the single \"heading-birth-is-h\" predicate, so the -->\n    <!-- \"body\" heading-level increment cannot disagree with this  -->\n    <xsl:variable name=\"heads-with-h\">\n        <xsl:apply-templates select=\".\" mode=\"heading-birth-is-h\"/>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$heads-with-h = 'yes'\">\n            <xsl:apply-templates select=\".\" mode=\"heading-non-singleton-number\">\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\".\" mode=\"heading-simple\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"&SOLUTION-LIKE;\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Primary content of generic \"body\" template   -->\n<!-- Pass along b-original flag                   -->\n<!-- Potentially knowled, may have statement      -->\n<!-- with Sage, so pass block type                -->\n<!-- Simply process contents, could restrict here -->\n<xsl:template match=\"&SOLUTION-LIKE;\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:apply-templates select=\"*\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n        <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n\n<!-- DISCUSSION-LIKE -->\n<!-- A simple item hanging off others -->\n\n<!-- Always born-hidden, by design -->\n<xsl:template match=\"&DISCUSSION-LIKE;\" mode=\"is-hidden\">\n    <xsl:text>false</xsl:text>\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"&DISCUSSION-LIKE;\" mode=\"body-element\">\n    <xsl:text>div</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"&DISCUSSION-LIKE;\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n    <xsl:text> discussion-like</xsl:text>\n</xsl:template>\n\n<!-- When born use this heading -->\n<xsl:template match=\"&DISCUSSION-LIKE;\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"&DISCUSSION-LIKE;\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Primary content of generic \"body\" template   -->\n<!-- Pass along b-original flag                   -->\n<!-- Potentially knowled, may have statement      -->\n<!-- with Sage, so pass block type                -->\n<!-- Simply process contents, could restrict here -->\n<xsl:template match=\"&DISCUSSION-LIKE;\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:apply-templates select=\"*\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n        <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- The decision procedure for which components appear, and in which  -->\n<!-- order, is the generic \"exercise-components\" driver pair in        -->\n<!-- pretext-common.xsl; the \"present-*\" hooks below supply the HTML   -->\n<!-- realization.  Runestone interactive exercises are entirely        -->\n<!-- HTML-specific, so they are matched here, ahead of the drivers.    -->\n\n<!-- Select -->\n<!-- Largely a Runestone/database operation referencing -->\n<!-- existing questions supplied by the manifest,       -->\n<!-- so we go straight to an HTML version               -->\n<xsl:template match=\"*[@pi:exercise-interactive = 'select']\" mode=\"exercise-components\">\n    <xsl:apply-templates select=\".\" mode=\"runestone-to-interactive\"/>\n</xsl:template>\n\n<!-- True/False        -->\n<!-- Multiple Choice   -->\n<!-- Parson problems   -->\n<!-- Matching problems -->\n<!-- Clickable Area    -->\n<!-- Fill-In (Basic)   -->\n<!-- Coding Exercise   -->\n<!-- Dual Form Exercise-->\n<!-- Short Answer      -->\n<!-- The \"runestone-to-interactive\" templates will combine a   -->\n<!-- \"regular\" PreTeXt statement together with some additional -->\n<!-- interactive material to make a hybrid \"statement\"         -->\n<xsl:template match=\"*[(@pi:exercise-interactive = 'truefalse') or\n                       (@pi:exercise-interactive = 'multiplechoice') or\n                       (@pi:exercise-interactive = 'parson') or\n                       (@pi:exercise-interactive = 'parson-horizontal') or\n                       (@pi:exercise-interactive = 'cardsort') or\n                       (@pi:exercise-interactive = 'matching') or\n                       (@pi:exercise-interactive = 'clickablearea') or\n                       (@pi:exercise-interactive = 'fillin-basic') or\n                       (@pi:exercise-interactive = 'coding') or\n                       (@pi:exercise-interactive = 'dual') or\n                       (@pi:exercise-interactive = 'shortanswer')]\" mode=\"exercise-components\">\n    <xsl:param name=\"b-original\"/>\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n    <xsl:param name=\"b-has-statement\" />\n    <xsl:param name=\"b-has-hint\" />\n    <xsl:param name=\"b-has-answer\" />\n    <xsl:param name=\"b-has-solution\" />\n\n    <xsl:if test=\"$b-has-statement\">\n        <xsl:apply-templates select=\".\" mode=\"runestone-to-interactive\"/>\n    </xsl:if>\n    <xsl:apply-templates select=\".\" mode=\"solutions-div\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n        <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"b-has-hint\"  select=\"$b-has-hint\"/>\n        <xsl:with-param name=\"b-has-answer\"  select=\"$b-has-answer\"/>\n        <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-solution\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Dynamic fillin is broken out separately because the test for -->\n<!-- correctness as well as feedback is dynamically chosen.       -->\n<xsl:template match=\"*[@pi:exercise-interactive = 'fillin']\" mode=\"exercise-components\">\n    <xsl:param name=\"b-original\"/>\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n    <xsl:param name=\"b-has-statement\" />\n    <xsl:param name=\"b-has-hint\" />\n\n    <xsl:if test=\"$b-has-statement\">\n        <xsl:apply-templates select=\".\" mode=\"runestone-to-interactive\"/>\n    </xsl:if>\n    <!-- Include hints. Solution/answer get special handling       -->\n    <xsl:apply-templates select=\".\" mode=\"solutions-div\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n        <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"b-has-hint\"  select=\"$b-has-hint\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Now the hooks for the generic drivers -->\n\n<xsl:template match=\"*\" mode=\"present-exercise-statement\">\n    <xsl:param name=\"b-original\"/>\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:apply-templates select=\"statement\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n        <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- no explicit \"statement\", so all content is the statement -->\n<!-- the \"dry-run\" templates should prevent an empty shell    -->\n<xsl:template match=\"*\" mode=\"present-exercise-statement-bare\">\n    <xsl:param name=\"b-original\"/>\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:apply-templates select=\"*\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n        <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n    <!-- no separator, since no trailing components -->\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"present-exercise-solutions\">\n    <xsl:param name=\"b-original\"/>\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n    <xsl:param name=\"b-has-hint\"/>\n    <xsl:param name=\"b-has-answer\"/>\n    <xsl:param name=\"b-has-solution\"/>\n\n    <xsl:apply-templates select=\".\" mode=\"solutions-div\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n        <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"b-has-hint\"  select=\"$b-has-hint\"/>\n        <xsl:with-param name=\"b-has-answer\"  select=\"$b-has-answer\"/>\n        <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-solution\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- An \"introduction\", a \"task\" that survived its dry-run, and a  -->\n<!-- \"conclusion\" are simply processed as if encountered normally, -->\n<!-- reproducing the wholesale processing that preceded the        -->\n<!-- generic drivers.                                              -->\n\n<xsl:template match=\"*\" mode=\"present-tasks-introduction\">\n    <xsl:param name=\"b-has-statement\"/>\n    <xsl:param name=\"b-original\"/>\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:if test=\"$b-has-statement\">\n        <xsl:apply-templates select=\"introduction\">\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n            <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n    </xsl:if>\n</xsl:template>\n\n<xsl:template match=\"task\" mode=\"present-task-item\">\n    <xsl:param name=\"b-original\"/>\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n    <xsl:param name=\"b-has-statement\"/>\n    <xsl:param name=\"b-has-hint\"/>\n    <xsl:param name=\"b-has-answer\"/>\n    <xsl:param name=\"b-has-solution\"/>\n\n    <xsl:choose>\n        <!-- where born, the task is processed as if encountered normally -->\n        <xsl:when test=\"$b-original\">\n            <xsl:apply-templates select=\".\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- in a \"solutions\" division, a heading that links back to the -->\n        <!-- original, then the chosen components, one level deeper      -->\n        <xsl:otherwise>\n            <xsl:apply-templates select=\".\" mode=\"solutions\">\n                <xsl:with-param name=\"heading-level\"   select=\"$heading-level + 1\"/>\n                <xsl:with-param name=\"b-has-statement\" select=\"$b-has-statement\" />\n                <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-hint\" />\n                <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-answer\" />\n                <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-solution\" />\n            </xsl:apply-templates>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"present-tasks-conclusion\">\n    <xsl:param name=\"b-has-statement\"/>\n    <xsl:param name=\"b-original\"/>\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:if test=\"$b-has-statement\">\n        <xsl:apply-templates select=\"conclusion\">\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n            <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n    </xsl:if>\n</xsl:template>\n\n<!-- \"exercise\", EXAMPLE-LIKE, PROJECT-LIKE, \"task\", and more have a  -->\n<!-- div.solutions full of SOLUTION-LIKE hanging off them.  But we    -->\n<!-- don't want the div if there is nothing to go into it, and        -->\n<!-- EXAMPLE-LIKE is presentational, so we don't have knowls to       -->\n<!-- package, we just lay them out right after the example.           -->\n<!-- N.B. match could be improved, just being more lazy than careful  -->\n<xsl:template match=\"*\" mode=\"solutions-div\">\n    <xsl:param name=\"b-original\"/>\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n    <!-- no \"statement\" here -->\n    <xsl:param name=\"b-has-hint\"/>\n    <xsl:param name=\"b-has-answer\"/>\n    <xsl:param name=\"b-has-solution\"/>\n\n    <!-- nothing to do if there is nothing so show -->\n    <xsl:if test=\"(hint and $b-has-hint) or (answer and $b-has-answer) or (solution and $b-has-solution)\">\n        <!-- collect all the hint, answer, solution in a variable -->\n        <xsl:variable name=\"all-solutions\">\n            <xsl:if test=\"$b-has-hint\">\n                <xsl:apply-templates select=\"hint\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                    <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n                    <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                </xsl:apply-templates>\n            </xsl:if>\n            <xsl:if test=\"$b-has-answer\">\n                <xsl:apply-templates select=\"answer\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                    <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n                    <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                </xsl:apply-templates>\n            </xsl:if>\n            <xsl:if test=\"$b-has-solution\">\n                <xsl:apply-templates select=\"solution\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                    <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n                    <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                </xsl:apply-templates>\n            </xsl:if>\n        </xsl:variable>\n        <!-- If this is an EXAMPLE-LIKE and we are unknowling its solutions,   -->\n        <!-- then just show them.  Otherwise, we use a div to layout knowls    -->\n        <!-- like a sentence: horiziontal flow, with wrapping.                 -->\n        <!-- NB: context here could be an EXAMPLE-LIKE or it might be a \"task\" -->\n        <!-- with an EXAMPLE-LIKE ancestor, thus the ancestor-or-self:: axis   -->\n        <xsl:choose>\n            <xsl:when test=\"($knowl-example-solution = 'no') and ancestor-or-self::*[&EXAMPLE-FILTER;]\">\n                <xsl:copy-of select=\"$all-solutions\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <div class=\"solutions\">\n                    <xsl:copy-of select=\"$all-solutions\"/>\n                </div>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:if>\n</xsl:template>\n\n<!-- All of the items matching the template two above (except perhaps  -->\n<!-- the WW exercises) can appear in a printout with some room to      -->\n<!-- work a problem given by a @workspace attribute.  (But we are not  -->\n<!-- careful with the match, given the limited reach here.)  The \"div\" -->\n<!-- we drop here is controlled by the Javascript - on a \"normal\" page -->\n<!-- displaying a printout it is ineffective, and on a printable,      -->\n<!-- standalone page it produces space that is visually apparent, but  -->\n<!-- prints invisible.  No @workspace attribute, nothing is added.     -->\n<!-- We rely on a template in -common to error-check the value of      -->\n<!-- the attribute.                                                    -->\n<xsl:template match=\"*\" mode=\"workspace\">\n    <xsl:variable name=\"vertical-space\">\n        <xsl:apply-templates select=\".\" mode=\"sanitize-workspace\"/>\n    </xsl:variable>\n    <xsl:if test=\"not($vertical-space = '')\">\n        <div class=\"workspace\" data-space=\"{$vertical-space}\"/>\n    </xsl:if>\n</xsl:template>\n\n<!-- The next few implementions support theorems,       -->\n<!-- which may have knowls containing PROOF-LIKE        -->\n<!-- hanging  off them.  A PROOF-LIKE can be a block in -->\n<!-- its own right (a \"detached\" PROOF-LIKE).           -->\n\n\n<!-- THEOREM-LIKE, AXIOM-LIKE -->\n<!-- Similar blocks, former may have a PROOF-LIKE appendage -->\n\n<!-- Born-hidden behavior is configurable -->\n<xsl:template match=\"&THEOREM-LIKE;|&AXIOM-LIKE;\" mode=\"is-hidden\">\n    <xsl:value-of select=\"$knowl-theorem = 'yes'\" />\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"&THEOREM-LIKE;|&AXIOM-LIKE;\" mode=\"body-element\">\n    <xsl:text>article</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"&THEOREM-LIKE;|&AXIOM-LIKE;\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n    <xsl:text> theorem-like</xsl:text>\n</xsl:template>\n\n<!-- When born use this heading -->\n<xsl:template match=\"&THEOREM-LIKE;|&AXIOM-LIKE;\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"&THEOREM-LIKE;|&AXIOM-LIKE;\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Primary content of generic \"body\" template  -->\n<!-- Pass along b-original flag                  -->\n<!-- Potentially knowled, may have statement     -->\n<!-- with Sage, so pass block type              -->\n<!-- Simply process contents, could restict here -->\n<xsl:template match=\"&THEOREM-LIKE;|&AXIOM-LIKE;\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n\n    <!-- Alternative: Locate first \"PROOF-LIKE\", select only preceding:: ? -->\n    <xsl:apply-templates select=\"*[not(&PROOF-FILTER;)]\" >\n        <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n        <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n\n<!-- PROOF-LIKE -->\n<!-- A fairly simple block, though configurable -->\n\n<!-- Born-hidden behavior is configurable -->\n<xsl:template match=\"&PROOF-LIKE;\" mode=\"is-hidden\">\n    <xsl:value-of select=\"$knowl-proof = 'yes'\" />\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"&PROOF-LIKE;\" mode=\"body-element\">\n    <xsl:text>article</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<!-- Only subsidiary item that is configurable -->\n<!-- as visible or hidden in a knowl           -->\n<xsl:template match=\"&PROOF-LIKE;\" mode=\"body-css-class\">\n    <xsl:choose>\n        <xsl:when test=\"$knowl-proof = 'yes'\">\n            <xsl:text>hiddenproof</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>proof</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- When born use this heading -->\n<!-- Optionally titled          -->\n<xsl:template match=\"&PROOF-LIKE;\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-no-number\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<!-- Optionally titled                          -->\n<xsl:template match=\"&PROOF-LIKE;\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:choose>\n        <xsl:when test=\"title\">\n            <xsl:apply-templates select=\".\" mode=\"heading-title\">\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\".\" mode=\"heading-type\">\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- Primary content of generic \"body\" template  -->\n<!-- Pass along b-original flag                  -->\n<!-- Potentially knowled, may have statement    -->\n<!-- with Sage, so pass block type              -->\n<!-- Simply process contents, could restict here -->\n<xsl:template match=\"&PROOF-LIKE;\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:apply-templates select=\"*\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n        <xsl:with-param name=\"block-type\" select=\"$block-type\"/>\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n\n<!-- Case (of a PROOF-LIKE) -->\n<!-- A simple block with an inline heading -->\n\n<!-- Never born-hidden, does not make sense -->\n<xsl:template match=\"case\" mode=\"is-hidden\">\n    <xsl:text>false</xsl:text>\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<!-- Natural HTML element      -->\n<xsl:template match=\"case\" mode=\"body-element\">\n    <xsl:text>article</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"case\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n</xsl:template>\n\n<!-- When born use this specialized heading -->\n<xsl:template match=\"case\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-case\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"case\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-case\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Primary content of generic \"body\" template   -->\n<!-- Pass along b-original flag                   -->\n<!-- Simply process contents, could restrict here -->\n<xsl:template match=\"case\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\"*\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n\n<!-- Next few implementations fit into general -->\n<!-- framework, but have some one-off flavor   -->\n\n\n<!-- Footnotes -->\n<!-- A bit unusual, as inline with minimal appearance -->\n\n<!-- Always born-hidden, by design -->\n<xsl:template match=\"fn\" mode=\"is-hidden\">\n    <xsl:text>true</xsl:text>\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"fn\" mode=\"body-element\">\n    <xsl:text>div</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"fn\" mode=\"body-css-class\">\n    <xsl:text>ptx-footnote__contents</xsl:text>\n</xsl:template>\n\n<!-- When born use this heading -->\n<!-- This could move to headings, but is one-off -->\n<xsl:template match=\"fn\" mode=\"heading-birth\">\n    <xsl:element name=\"sup\">\n        <xsl:text>&#x2009;</xsl:text>\n        <xsl:apply-templates select=\".\" mode=\"serial-number\" />\n        <xsl:text>&#x2009;</xsl:text>\n    </xsl:element>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"fn\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Primary content of generic \"body\" template   -->\n<!-- Pass along b-original flag                   -->\n<!-- Simply process contents, could restrict here -->\n<!-- Schema is TextLong, so need to process mixed -->\n<xsl:template match=\"fn\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:apply-templates>\n        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n    </xsl:apply-templates>\n</xsl:template>\n\n\n<!-- Contributor -->\n<!-- A block with no subsidiary elements, no duplication -->\n\n<!-- Never born-hidden, does not make sense -->\n<xsl:template match=\"contributor\" mode=\"is-hidden\">\n    <xsl:text>false</xsl:text>\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<!-- Natural HTML element      -->\n<xsl:template match=\"contributor\" mode=\"body-element\">\n    <xsl:text>div</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"contributor\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n</xsl:template>\n\n<!-- Heading is not needed -->\n<xsl:template match=\"contributor\" mode=\"heading-birth\" />\n\n<!-- xref-knowl content makes it obvious-->\n<xsl:template match=\"contributor\" mode=\"heading-xref-knowl\" />\n\n<!-- Primary content of generic \"body\" template   -->\n<!-- Pass along b-original flag                   -->\n<!-- Simply process contents, could restrict here -->\n<xsl:template match=\"contributor\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <!-- not interpreting duplication flag here -->\n    <div class=\"contributor-name\">\n        <xsl:apply-templates select=\"personname\" />\n    </div>\n    <div class=\"contributor-info\">\n        <xsl:if test=\"affiliation\">\n            <xsl:apply-templates select=\"affiliation\"/>\n            <xsl:if test=\"affiliation/following-sibling::*\">\n                <br/>\n            </xsl:if>\n        </xsl:if>\n        <xsl:if test=\"email\">\n            <xsl:apply-templates select=\"email\" />\n            <xsl:if test=\"email/following-sibling::*\">\n                <br />\n            </xsl:if>\n        </xsl:if>\n    </div>\n</xsl:template>\n\n\n<!-- Defined Terms (of a Glossary) -->\n\n<!-- Never born-hidden, always in \"glossary\" -->\n<xsl:template match=\"gi\" mode=\"is-hidden\">\n    <xsl:text>false</xsl:text>\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"gi\" mode=\"body-element\">\n    <xsl:text>article</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"gi\" mode=\"body-css-class\">\n    <xsl:value-of select=\"local-name()\"/>\n</xsl:template>\n\n<!-- When born use this heading -->\n<xsl:template match=\"gi\" mode=\"heading-birth\" />\n\n<!-- Heading for interior of xref-knowl content -->\n<!-- Not necessary, obvious by appearance       -->\n<xsl:template match=\"gi\" mode=\"heading-xref-knowl\" />\n\n<!-- Glossary defined terms have more structure -->\n<!-- The id is placed on the title as a target  -->\n<xsl:template match=\"gi\" mode=\"body\">\n    <xsl:param name=\"block-type\" />\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n    <xsl:choose>\n        <xsl:when test=\"$block-type = 'xref'\">\n            <article class=\"li\">\n                <!-- \"title\" of item is replicated in heading -->\n                <xsl:apply-templates select=\".\" mode=\"heading-xref-knowl\">\n                    <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                </xsl:apply-templates>\n                <!-- a run of paragraphs, conceivably, title is killed -->\n                <xsl:apply-templates select=\"*\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                </xsl:apply-templates>\n                <!-- Insert permalink -->\n                <xsl:apply-templates select=\".\" mode=\"permalink\"/>\n            </article>\n        </xsl:when>\n        <xsl:otherwise>\n            <dt>\n                <!-- label original -->\n                <xsl:if test=\"$b-original\">\n                    <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n                </xsl:if>\n                <xsl:apply-templates select=\".\" mode=\"title-full\" />\n                <!-- Insert permalink -->\n                <xsl:apply-templates select=\".\" mode=\"permalink\"/>\n            </dt>\n            <dd>\n                <xsl:apply-templates select=\"*\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                </xsl:apply-templates>\n            </dd>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Bibliographic Entries -->\n<!-- An obvious use for knowls, but occur inline -->\n\n<!-- Never born-hidden, always in references -->\n<xsl:template match=\"biblio\" mode=\"is-hidden\">\n    <xsl:text>false</xsl:text>\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"biblio\" mode=\"body-element\">\n    <xsl:text>article</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<xsl:template match=\"biblio\" mode=\"body-css-class\">\n    <xsl:text>bib</xsl:text>\n</xsl:template>\n\n<!-- When born use this heading -->\n<xsl:template match=\"biblio\" mode=\"heading-birth\" />\n\n<!-- Heading for interior of xref-knowl content -->\n<!-- Not necessary, obvious by appearance       -->\n<xsl:template match=\"biblio\" mode=\"heading-xref-knowl\" />\n\n<!-- Primary content of generic \"body\" template   -->\n<!-- Pass along b-original flag                   -->\n<!-- Simply process contents, could restrict here -->\n<!-- Schema is TextLong, so need to process mixed -->\n<xsl:template match=\"biblio\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <!-- ignoring original flag at first, -->\n    <!-- nothing interior gets duplicated -->\n    <div class=\"bibitem\">\n        <xsl:choose>\n            <!-- CSL not active, PreTeXt numbers and brackets -->\n            <xsl:when test=\"not(@numeric)\">\n                <xsl:text>[</xsl:text>\n                <xsl:apply-templates select=\".\" mode=\"serial-number\" />\n                <xsl:text>]</xsl:text>\n            </xsl:when>\n            <!-- CSL provided, with formatting -->\n            <xsl:otherwise>\n                <xsl:value-of select=\"@numeric\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </div>\n    <div class=\"bibentry\">\n        <xsl:choose>\n            <xsl:when test=\"@type = 'raw'\">\n                <!-- mixed content, include text nodes -->\n                <xsl:apply-templates select=\"text()|*[not(self::note)]\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                </xsl:apply-templates>\n            </xsl:when>\n            <xsl:when test=\"@type = 'bibtex'\">\n                <!-- structured, document order -->\n                <xsl:apply-templates select=\"*[not(self::note)]\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                </xsl:apply-templates>\n            </xsl:when>\n            <xsl:when test=\"not(@type = 'raw') and not(@type = 'bibtex')\">\n                <!-- structured, document order -->\n                <xsl:apply-templates select=\"*[not(self::note)]\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                </xsl:apply-templates>\n            </xsl:when>\n        </xsl:choose>\n        <xsl:if test=\"note\">\n            <xsl:apply-templates select=\"note\">\n                <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n            </xsl:apply-templates>\n        </xsl:if>\n    </div>\n</xsl:template>\n\n<!-- Bibliographic Note -->\n<!-- A simple item hanging off others -->\n\n<!-- Always born-hidden, by design -->\n<xsl:template match=\"biblio/note|interactive/instructions\" mode=\"is-hidden\">\n    <xsl:text>true</xsl:text>\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"biblio/note|interactive/instructions\" mode=\"body-element\">\n    <xsl:text>div</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<!-- This is a temporary hack, which should go away -->\n<xsl:template match=\"biblio/note|interactive/instructions\" mode=\"body-css-class\">\n    <xsl:text>solution-like</xsl:text>\n</xsl:template>\n\n<!-- When born use this heading -->\n<xsl:template match=\"biblio/note\" mode=\"heading-birth\">\n    <xsl:apply-templates select=\".\" mode=\"heading-simple\" />\n</xsl:template>\n<xsl:template match=\"interactive/instructions\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-no-number\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"biblio/note\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n<xsl:template match=\"interactive/instructions\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-no-number\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n\n<!-- Primary content of generic \"body\" template   -->\n<!-- Pass along b-original flag                   -->\n<!-- Simply process contents, could restrict here -->\n<!-- Schema says just paragraphs, \"p\"             -->\n<xsl:template match=\"biblio/note|interactive/instructions\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\"p\" >\n        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Fragment (literate programming) -->\n<!-- A simple item hanging off others -->\n\n<!-- Always born-hidden, by design -->\n<xsl:template match=\"fragment\" mode=\"is-hidden\">\n    <xsl:text>false</xsl:text>\n</xsl:template>\n\n<!-- Overall enclosing element -->\n<xsl:template match=\"fragment\" mode=\"body-element\">\n    <xsl:text>div</xsl:text>\n</xsl:template>\n\n<!-- And its CSS class -->\n<!-- This is a temporary hack, which should go away -->\n<xsl:template match=\"fragment\" mode=\"body-css-class\">\n    <xsl:text>fragment</xsl:text>\n</xsl:template>\n\n<!-- When born use this heading -->\n<xsl:template match=\"fragment\" mode=\"heading-birth\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-generic\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        <xsl:with-param name=\"heading-title\">\n            <xsl:call-template name=\"character\">\n                <xsl:with-param name=\"name\" select=\"'langle'\"/>\n            </xsl:call-template>\n            <xsl:apply-templates select=\".\" mode=\"number\"/>\n            <xsl:text> </xsl:text>\n            <xsl:apply-templates select=\".\" mode=\"title-full\"/>\n            <xsl:call-template name=\"character\">\n                <xsl:with-param name=\"name\" select=\"'rangle'\"/>\n            </xsl:call-template>\n            <!--  U+2261 ≡ IDENTICAL TO -->\n            <xsl:text> &#x2261;</xsl:text>\n        </xsl:with-param>\n    </xsl:apply-templates>\n    <xsl:if test=\"@filename\">\n        <xsl:text>Root of file: </xsl:text>\n        <xsl:value-of select=\"@filename\"/>\n        <br/>\n    </xsl:if>\n</xsl:template>\n\n<!-- Heading for interior of xref-knowl content -->\n<xsl:template match=\"fragment\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Primary content of generic \"body\" template -->\n<!-- Pass along b-original flag                 -->\n<xsl:template match=\"fragment\" mode=\"wrapped-content\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <pre>\n        <xsl:apply-templates select=\"code|fragref\"/>\n    </pre>\n</xsl:template>\n\n<!-- All of the implementations above use the same   -->\n<!-- template for their body, it relies on various   -->\n<!-- templates but most of the work comes via the    -->\n<!-- \"wrapped-content\" template.  Here is that       -->\n<!-- \"body\" template.  The items in the \"match\"      -->\n<!-- are in the order presented above: simple first, -->\n<!-- and top-down when components are also knowled.  -->\n\n<!-- Does a block's \"heading-birth\" emit an actual \"h\" at its     -->\n<!-- level?  Consulted by the \"body\" increment and the \"solution\" -->\n<!-- heading-birth so their notion of an \"h\" heading stays one.   -->\n<xsl:template match=\"*\" mode=\"heading-birth-is-h\">\n    <xsl:text>yes</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"&FIGURE-LIKE;\" mode=\"heading-birth-is-h\">\n    <xsl:text>no</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"&SOLUTION-LIKE;\" mode=\"heading-birth-is-h\">\n    <xsl:choose>\n        <!-- an example's solution, shown un-knowled, is a numbered \"h\" -->\n        <xsl:when test=\"($knowl-example-solution = 'no') and ancestor::*[&EXAMPLE-FILTER;]\">\n            <xsl:text>yes</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>no</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n\n<xsl:template match=\"&REMARK-LIKE;|&COMPUTATION-LIKE;|&DEFINITION-LIKE;|&ASIDE-LIKE;|poem|&FIGURE-LIKE;|assemblage|blockquote|paragraphs|&GOAL-LIKE;|&OPENPROBLEM-LIKE;|&EXAMPLE-LIKE;|subexercises|exercisegroup|exercise|&PROJECT-LIKE;|task|&SOLUTION-LIKE;|&DISCUSSION-LIKE;|&THEOREM-LIKE;|&AXIOM-LIKE;|&PROOF-LIKE;|case|fn|contributor|biblio|biblio/note|interactive/instructions|fragment\" mode=\"body\">\n    <xsl:param name=\"b-original\" select=\"true()\"/>\n    <xsl:param name=\"block-type\"/>\n    <xsl:param name=\"heading-level\"/>\n\n    <!-- prelude beforehand, when original -->\n    <xsl:if test=\"$b-original\">\n        <xsl:apply-templates select=\"prelude\">\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n        </xsl:apply-templates>\n    </xsl:if>\n    <xsl:variable name=\"body-elt\">\n        <xsl:apply-templates select=\".\" mode=\"body-element\" />\n    </xsl:variable>\n    <!-- newlines inserted to encourage formatted output -->\n    <xsl:text>&#xa;</xsl:text>\n    <xsl:element name=\"{$body-elt}\">\n        <xsl:attribute name=\"class\">\n            <xsl:apply-templates select=\".\" mode=\"body-css-class\" />\n            <xsl:if test=\"$block-type = 'hidden'\">\n                <xsl:text> knowl__content</xsl:text>\n            </xsl:if>\n        </xsl:attribute>\n        <!-- Label original, but not if embedded            -->\n        <!-- Then id goes onto the knowl text, so locatable -->\n        <xsl:if test=\"$b-original and not($block-type = 'hidden')\">\n            <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n        </xsl:if>\n        <!-- Both are empty unless this block is a standalone printout, -->\n        <!-- ie a PROJECT-LIKE with workspace outside of any printout.  -->\n        <xsl:apply-templates select=\".\" mode=\"page-margins-attribute\"/>\n        <xsl:apply-templates select=\".\" mode=\"page-header-footer-attributes\"/>\n        <!-- If visible, heading interior to article -->\n        <xsl:if test=\"$block-type = 'visible'\">\n            <xsl:apply-templates select=\".\" mode=\"heading-birth\">\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:if>\n        <!-- If xref-knowl, heading interior to article -->\n        <xsl:if test=\"$block-type = 'xref'\">\n            <xsl:apply-templates select=\".\" mode=\"heading-xref-knowl\">\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n        </xsl:if>\n        <!-- After the heading, and before the actual guts, we      -->\n        <!-- sometimes annotate with the source                     -->\n        <!-- of the current element.  This calls a stub, unless     -->\n        <!-- a separate stylesheet is used to define the template,  -->\n        <!-- and the method is defined there.  An \"fn\" necessarily  -->\n        <!-- comes through here, but it is a silly thing to         -->\n        <!-- annotate.  We skip it promptly on the receiving end,   -->\n        <!-- instead of adding clutter here.                        -->\n        <xsl:apply-templates select=\".\" mode=\"view-source-widget\"/>\n        <!-- Then actual content, respecting b-original flag  -->\n        <!-- Pass $block-type for Sage cells to know environs -->\n        <!-- Descendant blocks step down a heading level, unless -->\n        <!-- this block heads with something other than an \"h\";  -->\n        <!-- the \"heading-birth-is-h\" predicate decides.         -->\n        <xsl:variable name=\"heads-with-h\">\n            <xsl:apply-templates select=\".\" mode=\"heading-birth-is-h\"/>\n        </xsl:variable>\n        <xsl:apply-templates select=\".\" mode=\"wrapped-content\">\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n            <xsl:with-param name=\"block-type\" select=\"$block-type\" />\n            <xsl:with-param name=\"heading-level\">\n                <xsl:choose>\n                    <xsl:when test=\"$heads-with-h = 'no'\">\n                        <xsl:value-of select=\"$heading-level\"/>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:value-of select=\"$heading-level + 1\"/>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:with-param>\n        </xsl:apply-templates>\n        <!-- Apply workspace div (but not in project, exercises or tasks, -->\n        <!-- since they get them applied in their exercise-content        -->\n        <!-- template). Unless the element is in a worksheet or handout,  -->\n        <!-- this div will be killed by the sanatize-workspace template.  -->\n        <!--<xsl:if test=\"not(&PROJECT-FILTER; or self::exercise or self::task)\">-->\n            <xsl:apply-templates select=\".\" mode=\"workspace\"/>\n        <!--</xsl:if>-->\n        <!-- Insert a permalink as the last child of the block, but only   -->\n        <!-- if not FIGURE-LIKE (these get their permalink on the caption) -->\n        <xsl:if test=\"not(&FIGURE-FILTER;)\">\n            <xsl:apply-templates select=\".\" mode=\"permalink\"/>\n        </xsl:if>\n    <xsl:text>&#xa;</xsl:text>\n    </xsl:element>\n    <!-- Extraordinary: PROOF-LIKE are not displayed within their-->\n    <!-- parent theorem, but as a sibling, following.  It might  -->\n    <!-- be a hidden knowl, it might just be the PROOF-LIKE      -->\n    <!-- visible. The conditional simply prevents abuse.         -->\n    <xsl:if test=\"(&THEOREM-FILTER;)\">\n        <xsl:apply-templates select=\"&PROOF-LIKE;\">\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n    </xsl:if>\n    <!-- postlude afterward, when original -->\n    <xsl:if test=\"$b-original\">\n        <xsl:apply-templates select=\"postlude\">\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n        </xsl:apply-templates>\n    </xsl:if>\n</xsl:template>\n\n<!-- The following feed into the same framework,   -->\n<!-- but have their own specific \"body\" templates  -->\n<!-- due to their unique characteristics.  We have -->\n<!-- paragraphs (\"p\"), list items (\"li\"), webwork  -->\n<!-- exercises (\"webwork-reps\"), and numbered      -->\n<!-- mathematics (\"md[mrow]\")                      -->\n\n\n<!-- Paragraph -->\n<!-- These are never born hidden.  They are     -->\n<!-- often xref targets (such as in the index). -->\n<!-- Because we bust up some paragraphs into    -->\n<!-- smaller ones, interleaved with displays    -->\n<!-- (lists, math, code display), and because   -->\n<!-- they do not have titles or heading,        -->\n<!-- we process everything in the body.         -->\n\n<xsl:template match=\"p\" mode=\"is-hidden\">\n    <xsl:text>false</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"p\" mode=\"body-element\" />\n\n<xsl:template match=\"p\" mode=\"body-css-class\" />\n\n<xsl:template match=\"p\" mode=\"heading-birth\" />\n\n<xsl:template match=\"p\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-type\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Paragraphs, without lists within   -->\n<xsl:template match=\"p\" mode=\"body\">\n    <xsl:param name=\"block-type\" />\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n    <xsl:if test=\"$block-type = 'xref'\">\n        <xsl:apply-templates select=\".\" mode=\"heading-xref-knowl\">\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n    </xsl:if>\n    <!-- newline inserted to encourage formatted output -->\n    <xsl:text>&#xa;</xsl:text>\n    <div>\n        <xsl:attribute name=\"class\">\n            <xsl:text>para</xsl:text>\n            <!-- acknowledge prelude/interlude/postlude parents -->\n            <xsl:apply-templates select=\".\" mode=\"add-lude-parent-class\"/>\n        </xsl:attribute>\n        <!-- label original -->\n        <xsl:if test=\"$b-original\">\n            <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n        </xsl:if>\n        <xsl:apply-templates>\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n        <!-- Insert workspace (will only apply to p inside worksheet or handout) -->\n        <xsl:apply-templates select=\".\" mode=\"workspace\"/>\n        <!-- Insert permalink -->\n        <xsl:apply-templates select=\".\" mode=\"permalink\"/>\n    </div>\n</xsl:template>\n\n<!-- Paragraphs, with displays within                    -->\n<!-- Later, so a higher priority match                   -->\n<!-- Lists and display math are HTML blocks              -->\n<!-- and so should not be within an HTML paragraph.      -->\n<!-- We bust them out, and put the id for the paragraph  -->\n<!-- on the first one, even if empty.                    -->\n<xsl:template match=\"p[ol|ul|dl|md[mrow]|cd]\" mode=\"body\">\n    <xsl:param name=\"block-type\" />\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n    <xsl:if test=\"$block-type = 'xref'\">\n        <xsl:apply-templates select=\".\" mode=\"heading-xref-knowl\">\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n    </xsl:if>\n    <!-- newline inserted to encourage formatted output -->\n    <xsl:text>&#xa;</xsl:text>\n    <!-- will later loop over displays within paragraph -->\n    <xsl:variable name=\"displays\" select=\"ul|ol|dl|md[mrow]|cd\" />\n    <!-- content prior to first display is exceptional, but if empty,   -->\n    <!-- as indicated by $initial, we do not produce an empty paragraph -->\n    <!--                                                                -->\n    <!-- all interesting nodes of paragraph, before first display       -->\n    <xsl:variable name=\"initial\" select=\"$displays[1]/preceding-sibling::*|$displays[1]/preceding-sibling::text()\" />\n    <xsl:variable name=\"initial-content\">\n        <xsl:apply-templates select=\"$initial\">\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <div class=\"para logical\">\n        <xsl:if test=\"$b-original\">\n            <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n        </xsl:if>\n        <!-- INDENT FOLLOWING ON A WHITESPACE COMMIT -->\n    <!-- XSLT 1.0: RTF is just a string if not converted to node set -->\n    <!-- This comparison might improve with a normalize-space()      -->\n    <xsl:if test=\"not($initial-content='')\">\n        <div>\n            <xsl:attribute name=\"class\">\n                <xsl:text>para</xsl:text>\n            </xsl:attribute>\n            <xsl:copy-of select=\"$initial-content\" />\n        </div>\n    </xsl:if>\n    <!-- for each display, output the display, plus trailing content -->\n    <xsl:for-each select=\"$displays\">\n        <!-- do the display proper -->\n        <xsl:apply-templates select=\".\">\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n        <!-- look through remainder, all element and text nodes, and the next display -->\n        <xsl:variable name=\"rightward\" select=\"following-sibling::*|following-sibling::text()\" />\n        <xsl:variable name=\"next-display\" select=\"following-sibling::*[self::ul or self::ol or self::dl or self::md[mrow] or self::cd][1]\" />\n        <xsl:choose>\n            <xsl:when test=\"$next-display\">\n                <xsl:variable name=\"leftward\" select=\"$next-display/preceding-sibling::*|$next-display/preceding-sibling::text()\" />\n                <!-- device below forms set intersection -->\n                <xsl:variable name=\"common\" select=\"$rightward[count(. | $leftward) = count($leftward)]\" />\n                <!-- Common content could be just a \"pi:intertext\"  -->\n                <!-- as a result of the \"intertext-exploder\" mode    -->\n                <!-- in -assembly.  This situation is recorded here. -->\n                <xsl:variable name=\"b-common-is-intertext\" select=\"$common[self::pi:intertext]\"/>\n                <!-- No id on these, as the first \"p\" got that    -->\n                <!-- Careful, punctuation after display math      -->\n                <!-- gets absorbed into display and so is a node  -->\n                <!-- that produces no content (cannot just count) -->\n                <xsl:variable name=\"common-content\">\n                    <xsl:apply-templates select=\"$common\">\n                        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                    </xsl:apply-templates>\n                </xsl:variable>\n                <!-- XSLT 1.0: RTF is just a string if not converted to node set -->\n                <!-- This comparison might improve with a normalize-space()      -->\n                <!-- When the intervening material aries from an authored        -->\n                <!-- \"intertext\", we mark the paragraph we create here as such   -->\n                <!-- for styling purposes.                                       -->\n                <xsl:if test=\"not($common-content = '')\">\n                    <div>\n                        <xsl:attribute name=\"class\">\n                            <xsl:text>para</xsl:text>\n                            <xsl:if test=\"$b-common-is-intertext\">\n                                <xsl:text> intertext</xsl:text>\n                            </xsl:if>\n                        </xsl:attribute>\n                        <xsl:copy-of select=\"$common-content\" />\n                    </div>\n                </xsl:if>\n            </xsl:when>\n            <xsl:otherwise>\n                <!-- finish the trailing content, if nonempty    -->\n                <!-- Note: impossible for this to be \"intertext\" -->\n                <xsl:variable name=\"common-content\">\n                    <xsl:apply-templates select=\"$rightward\">\n                        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                    </xsl:apply-templates>\n                </xsl:variable>\n                <!-- XSLT 1.0: RTF is just a string if not converted to node set -->\n                <!-- This comparison might improve with a normalize-space()      -->\n                <xsl:if test=\"not($common-content = '')\">\n                    <div class=\"para\">\n                        <xsl:copy-of select=\"$common-content\" />\n                    </div>\n                </xsl:if>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:for-each>\n        <!-- INDENT ABOVE ON A WHITESPACE COMMIT -->\n    <!-- Insert workspace (will only apply to p inside worksheet or handout) -->\n    <xsl:apply-templates select=\".\" mode=\"workspace\"/>\n    <!-- Insert permalink -->\n    <xsl:apply-templates select=\".\" mode=\"permalink\"/>\n    </div>\n</xsl:template>\n\n\n<!-- List Items -->\n<!-- A list item can be the target of a        -->\n<!-- cross-reference, so we need to make       -->\n<!-- a xref-knowl for that scenario.  Also,    -->\n<!-- we produce the original versions here     -->\n<!-- too.  The \"ol, \"ul\", \"dl\" are pure        -->\n<!-- containers and are implemented elsewhere. -->\n\n<!-- Not applicable -->\n<xsl:template match=\"li\" mode=\"is-hidden\" />\n\n<xsl:template match=\"li\" mode=\"body-element\">\n    <xsl:text>article</xsl:text>\n</xsl:template>\n\n<!-- not yet supported, change this? -->\n<xsl:template match=\"li\" mode=\"body-css-class\">\n    <xsl:text>li</xsl:text>\n</xsl:template>\n\n<!-- Not applicable -->\n<xsl:template match=\"li\" mode=\"heading-birth\" />\n\n<xsl:template match=\"li\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-full\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- For a description list, the title alone is enough -->\n<xsl:template match=\"dl/li\" mode=\"heading-xref-knowl\">\n    <xsl:param name=\"heading-level\"/>\n    <xsl:apply-templates select=\".\" mode=\"heading-title\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Pass-through regular list items    -->\n<!-- Allow paragraphs in larger items,  -->\n<!-- or just snippets for smaller items -->\n<!-- radically diffferent looks if part -->\n<!-- of overall list versus being a     -->\n<!-- standalone display of one item     -->\n<!-- var may be a multiple choice list  -->\n<!-- container from a webwork-reps      -->\n<xsl:template match=\"ol/li|ul/li|var/li\" mode=\"body\">\n    <xsl:param name=\"block-type\" />\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n    <xsl:choose>\n        <xsl:when test=\"$block-type = 'xref'\">\n            <article class=\"li\">\n                <xsl:apply-templates select=\".\" mode=\"heading-xref-knowl\">\n                    <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                </xsl:apply-templates>\n                <xsl:apply-templates>\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                    <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                </xsl:apply-templates>\n            </article>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- newline inserted to encourage formatted output -->\n            <xsl:text>&#xa;</xsl:text>\n            <xsl:element name=\"li\">\n                <!-- label original -->\n                <xsl:if test=\"$b-original\">\n                    <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n                </xsl:if>\n                <!-- \"title\" only possible for structured version of a list item -->\n                <xsl:if test=\"title\">\n                    <span class=\"heading li--heading\">\n                        <span class=\"title li--heading-title\">\n                            <xsl:apply-templates select=\".\" mode=\"title-full\"/>\n                        </span>\n                    </span>\n                </xsl:if>\n                <!-- Unstructured list items will be output as an HTML \"p\"     -->\n                <!-- within the \"li\", much like a structured list item could   -->\n                <!-- have a single \"p\" as its structured content.  This is     -->\n                <!-- meant to help with authoring tools based on HTML content  -->\n                <!-- and for CSS withing Kindle versions.  A \"dl/li\" is always -->\n                <!-- structured, so we can do this here.                       -->\n                <xsl:choose>\n                    <!-- Any of these children is an indicator of a structured  -->\n                    <!-- list item, according to the schema, as of 2021-07-03   -->\n                    <xsl:when test=\"p|blockquote|pre|image|video|program|console|tabular|&FIGURE-LIKE;|&ASIDE-LIKE;|sidebyside|sbsgroup|sage\">\n                        <xsl:apply-templates>\n                            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                        </xsl:apply-templates>\n                    </xsl:when>\n                    <!-- No good test for unstructured? -->\n                    <xsl:otherwise>\n                        <div class=\"para\">\n                            <!-- Create a derived id, if original.  Somewhat  -->\n                            <!-- contrived so it doesn't collide with another. -->\n                            <xsl:if test=\"$b-original\">\n                                <xsl:attribute name=\"id\">\n                                    <xsl:text>p-derived-</xsl:text>\n                                    <xsl:apply-templates select=\".\" mode=\"html-id\" />\n                                </xsl:attribute>\n                            </xsl:if>\n                            <xsl:apply-templates>\n                                <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                            </xsl:apply-templates>\n                        </div>\n                    </xsl:otherwise>\n                </xsl:choose>\n                <!-- Insert workspace (will only apply if in worksheet or handout) -->\n                <xsl:apply-templates select=\".\" mode=\"workspace\"/>\n                <!-- Insert permalink -->\n                <xsl:apply-templates select=\".\" mode=\"permalink\"/>\n            </xsl:element>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Description list items have more structure -->\n<!-- The id is placed on the title as a target  -->\n<xsl:template match=\"dl/li\" mode=\"body\">\n    <xsl:param name=\"block-type\" />\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n    <xsl:choose>\n        <xsl:when test=\"$block-type = 'xref'\">\n            <article class=\"li\">\n                <!-- \"title\" of item is replicated in heading -->\n                <xsl:apply-templates select=\".\" mode=\"heading-xref-knowl\">\n                    <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                </xsl:apply-templates>\n                <!-- a run of paragraphs, conceivably, title is killed -->\n                <xsl:apply-templates>\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                </xsl:apply-templates>\n            </article>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- newline inserted to encourage formatted output -->\n            <xsl:text>&#xa;</xsl:text>\n            <xsl:element name=\"dt\">\n                <!-- label original -->\n                <xsl:if test=\"$b-original\">\n                    <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n                </xsl:if>\n                <xsl:apply-templates select=\".\" mode=\"title-full\" />\n                <!-- Insert permalink -->\n                <xsl:apply-templates select=\".\" mode=\"permalink\"/>\n            </xsl:element>\n            <!-- newline inserted to encourage formatted output -->\n            <xsl:text>&#xa;</xsl:text>\n            <xsl:element name=\"dd\">\n                <xsl:apply-templates>\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                </xsl:apply-templates>\n                <!-- Insert workspace -->\n                <xsl:apply-templates select=\".\" mode=\"workspace\"/>\n            </xsl:element>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- ########### -->\n<!-- Mathematics -->\n<!-- ########### -->\n\n<!-- Mathematics authored in LaTeX syntax should be       -->\n<!-- independent of output format.  Despite MathJax's     -->\n<!-- broad array of capabilities, there are still some    -->\n<!-- differences which we need to accomodate via abstract -->\n<!-- templates.                                           -->\n\n<!-- See the -common stylesheet for manipulations of math elements      -->\n<!-- and subsequent text nodes that lead with punctuation.  Basically,  -->\n<!-- punctuation can migrate from the start of the text node and into   -->\n<!-- the math, wrapped in a \\text{}.  We do this to display math as a   -->\n<!-- service to authors.  But for HTML/MathJax we avoid bad line-breaks -->\n<!-- if we do this routinely for inline math also.  If MathJax ever     -->\n<!-- gets better at this, then we can set this switch to 'display',     -->\n<!-- as for LaTeX.                                                      -->\n<xsl:variable name=\"math.punctuation.include\" select=\"'all'\"/>\n\n<!-- Inline Mathematics (\"m\") -->\n\n<!-- Never labeled, so not ever knowled,        -->\n<!-- and so no need for a duplicate template    -->\n<!-- Asymmetric LaTeX delimiters \\( and \\) need -->\n<!-- to be part of MathJax configuration, but   -->\n<!-- also free up the dollar sign               -->\n\n\n<!-- This template wraps inline math in delimiters -->\n<xsl:template name=\"inline-math-wrapper\">\n    <xsl:param name=\"math\"/>\n\n    <span class=\"process-math\">\n        <xsl:text>\\(</xsl:text>\n        <xsl:value-of select=\"$math\"/>\n        <xsl:text>\\)</xsl:text>\n    </span>\n</xsl:template>\n\n<!-- Displayed Single-Line Math (\"me\", \"men\") -->\n\n<!-- All displayed mathematics is wrapped by a div,    -->\n<!-- motivated in part by the need to sometimes put an -->\n<!-- HTML id on the first item of an exploded logical  -->\n<!-- paragraph into several HTML block level items     -->\n<!-- NB: displaymath might have an intertext           -->\n<!-- becoming \"p\", thus the necessity of \"copy-of\"     -->\n<xsl:template match=\"md[mrow]\" mode=\"display-math-wrapper\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"content\" />\n\n    <div class=\"displaymath process-math\">\n        <xsl:apply-templates select=\".\" mode=\"knowl-urls\"/>\n        <!-- Following is overkill.  Not every bit of math needs -->\n        <!-- to be referenced, but we err on the side of always  -->\n        <!-- supplying an HTML @id attribute.  Amending the test -->\n        <!-- by \"and mrow[(@pi:numbered = 'yes') or @tag]\" seems -->\n        <!-- to be fairly accurate, without being gross excess.  -->\n        <xsl:if test=\"$b-original\">\n            <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n        </xsl:if>\n        <xsl:copy-of select=\"$content\" />\n    </div>\n</xsl:template>\n\n<xsl:template match=\"md[mrow]\" mode=\"knowl-urls\">\n    <xsl:variable name=\"display-math-cross-references\" select=\"..//xref\"/>\n    <!-- don't add such an attribute if there is nothing happening -->\n    <xsl:if test=\"$display-math-cross-references\">\n        <xsl:attribute name=\"data-contains-math-knowls\">\n            <xsl:for-each select=\"$display-math-cross-references\">\n                <!-- space before all, except first -->\n                <xsl:if test=\"position() != 1\">\n                    <xsl:text> </xsl:text>\n                </xsl:if>\n                <xsl:apply-templates select=\"id(@ref)\" mode=\"knowl-filename\">\n                    <xsl:with-param name=\"origin\" select=\"'xref'\"/>\n                </xsl:apply-templates>\n            </xsl:for-each>\n        </xsl:attribute>\n    </xsl:if>\n</xsl:template>\n\n<!-- No \"%\" like on the LaTeX side -->\n<xsl:template name=\"display-math-visual-blank-line\">\n    <xsl:text>&#xa;</xsl:text>\n</xsl:template>\n\n<!-- Manual Number Tagging -->\n<!-- We do \"tag\" numbered equations in MathJax output, -->\n<!-- because we want to control and duplicate the way  -->\n<!-- numbers are generated and assigned by LaTeX       -->\n<!-- \"me\" is never numbered/tagged, \"men\" always is    -->\n<!-- This is the MathJax hard-coded technique          -->\n<!-- Local tag preempts a hard-coded number, and we    -->\n<!-- need to also take care with the numbering. \\tag{} -->\n<!-- is what a reader sees, usually the number         -->\n<!-- computed in -common, but sometimes symbols        -->\n<!-- generated by mrow/@tag. These are purely visual.  -->\n<!-- Identification and cross-references are managed   -->\n<!-- by HTML id on enclosing HTML elements.            -->\n\n<xsl:template match=\"mrow\" mode=\"tag\">\n    <xsl:text>\\tag{</xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"number\" />\n    <xsl:text>}</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"mrow[@tag]\" mode=\"tag\">\n    <xsl:text>\\tag{</xsl:text>\n    <xsl:apply-templates select=\"@tag\" mode=\"tag-symbol\" />\n    <xsl:text>}</xsl:text>\n</xsl:template>\n\n<!-- We need a few templates for knowl production, -->\n<!-- but generally they do nothing                 -->\n\n<!-- always visible -->\n<xsl:template match=\"md[mrow]\" mode=\"is-hidden\">\n    <xsl:text>false</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"md[mrow]\" mode=\"body-element\" />\n<xsl:template match=\"md[mrow]\" mode=\"body-css-class\" />\n\n<!-- No title; type and number obvious from content -->\n<xsl:template match=\"md[mrow]\" mode=\"heading-xref-knowl\" />\n\n<!-- Once upon a time, we broke up markup meant for MathJax that occured   -->\n<!-- outside of what we know is a mathematical context (\"accidental        -->\n<!-- mathematics\").   We did this by breaking up strings with a zero-width -->\n<!-- space (U+200B), but a better device is wrapping a delimiter in a span -->\n<!-- (see this technique in the \"text-processing\" template in the Jupyter  -->\n<!-- conversion).  However, MathJax 3 lets us target/ignore specific       -->\n<!-- locations for its translation.  So the \"text-processing\" template     -->\n<!-- that was once here is now gone.  But now it is back, to upgrade a     -->\n<!-- keyboard \"plain\" apostrophe to a Unicode \"curly\" apostrophe.          -->\n\n<xsl:template name=\"text-processing\">\n    <xsl:param name=\"text\"/>\n\n    <!-- 'RIGHT SINGLE QUOTATION MARK' (U+2019) -->\n    <xsl:variable name=\"apostophe-fixed\" select=\"str:replace($text, $apos, '&#x2019;')\"/>\n\n    <xsl:value-of select=\"$apostophe-fixed\"/>\n</xsl:template>\n\n<!-- We cruise knowled content for necessity of hidden knowls -->\n<xsl:template match=\"*\" mode=\"is-hidden\">\n    <xsl:text>false</xsl:text>\n</xsl:template>\n\n<!-- ############################# -->\n<!-- End: Block Production, Knowls -->\n<!-- ############################# -->\n\n\n<!-- #################### -->\n<!-- Components of Blocks -->\n<!-- #################### -->\n\n<!-- Introductions and Conclusions -->\n<!-- As components of blocks.      -->\n<!-- NB: self::page for inside printouts -->\n<xsl:template match=\"introduction[not(parent::*[&STRUCTURAL-FILTER; or self::page])]|conclusion[not(parent::*[&STRUCTURAL-FILTER; or self::page])]\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n    <!-- newline inserted to encourage formatted output -->\n    <xsl:text>&#xa;</xsl:text>\n    <xsl:element name=\"div\">\n        <xsl:attribute name=\"class\">\n            <xsl:value-of select=\"local-name(.)\" />\n        </xsl:attribute>\n        <xsl:if test=\"$b-original\">\n            <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n        </xsl:if>\n        <xsl:if test=\"title\">\n            <xsl:apply-templates select=\".\" mode=\"heading-generic\">\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                <xsl:with-param name=\"heading-title\">\n                    <xsl:apply-templates select=\".\" mode=\"title-full\" />\n                    <span> </span>\n                </xsl:with-param>\n            </xsl:apply-templates>\n        </xsl:if>\n        <xsl:apply-templates select=\"*\">\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n    </xsl:element>\n</xsl:template>\n\n<!-- A \"headnote\" prefaces the list of a list-like division: a -->\n<!-- \"glossary\", a \"references\", an \"index\", an \"appendix\"     -->\n<!-- that is a notation list.  Below is modeled on block       -->\n<!-- introductions (just above), but with no \"title\".          -->\n<xsl:template match=\"glossary/headnote|references/headnote|index/headnote|appendix/headnote\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <section class=\"headnote\">\n        <xsl:if test=\"$b-original\">\n            <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n        </xsl:if>\n        <xsl:apply-templates select=\"*\">\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n        </xsl:apply-templates>\n    </section>\n</xsl:template>\n\n<!-- Prelude, Interlude, Postlude -->\n<!-- Very simple containiers, to help with movement, use -->\n<xsl:template match=\"prelude|interlude|postlude\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <!-- assume these containers are structured -->\n    <xsl:apply-templates select=\"*\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Indicate if a routine element/object is from a LUDE-LIKE, -->\n<!-- by looking to the parent.  This is meant for use where an -->\n<!-- HTML element is already placing a @class attribute, so a  -->\n<!-- space is included to separate it away.                    -->\n<!-- NB: look to schema for all allowed elements within a \"prelude\", -->\n<!-- etc. and extend implementation beyond just \"p\" if desired.      -->\n<xsl:template match=\"p\" mode=\"add-lude-parent-class\">\n    <xsl:if test=\"parent::prelude|parent::interlude|parent::postlude\">\n        <!-- space off from existing class name(s) -->\n        <xsl:text> </xsl:text>\n        <!-- class name is parent PTX name -->\n        <xsl:value-of select=\"local-name(parent::*)\"/>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- ########### -->\n<!-- HTML Markup -->\n<!-- ########### -->\n\n<!-- ##### -->\n<!-- Lists -->\n<!-- ##### -->\n\n<!-- Utility templates to translate PTX              -->\n<!-- enumeration style to HTML list-style-type       -->\n<xsl:template match=\"ol|ol-marker\" mode=\"html-list-class\">\n    <xsl:variable name=\"ptx-format-code\" select=\"./@pi:format-code\" />\n    <xsl:choose>\n        <xsl:when test=\"$ptx-format-code = '0'\">decimal</xsl:when>\n        <xsl:when test=\"$ptx-format-code = '1'\">decimal</xsl:when>\n        <xsl:when test=\"$ptx-format-code = 'a'\">lower-alpha</xsl:when>\n        <xsl:when test=\"$ptx-format-code = 'A'\">upper-alpha</xsl:when>\n        <xsl:when test=\"$ptx-format-code = 'i'\">lower-roman</xsl:when>\n        <xsl:when test=\"$ptx-format-code = 'I'\">upper-roman</xsl:when>\n        <xsl:otherwise>\n            <xsl:message>PTX:BUG: bad ordered list label format code in HTML conversion</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"ul\" mode=\"html-list-class\">\n    <xsl:variable name=\"ptx-format-code\" select=\"./@pi:format-code\"/>\n    <xsl:choose>\n        <xsl:when test=\"$ptx-format-code = 'disc'\">disc</xsl:when>\n        <xsl:when test=\"$ptx-format-code = 'circle'\">circle</xsl:when>\n        <xsl:when test=\"$ptx-format-code = 'square'\">square</xsl:when>\n        <xsl:when test=\"$ptx-format-code = 'none'\">no-marker</xsl:when>\n        <xsl:otherwise>\n            <xsl:message>PTX:BUG: bad unordered list label format code in HTML conversion</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Lists themselves -->\n<!-- Hard-code the list style, trading -->\n<!-- on match in label templates.      -->\n<!-- Tunnel duplication flag to list items -->\n<xsl:template match=\"ol|ul\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n    <xsl:variable name=\"ptx-format-code\" select=\"./@pi:format-code\"/>\n    <!-- newline inserted to encourage formatted output -->\n    <xsl:text>&#xa;</xsl:text>\n    <xsl:element name=\"{local-name(.)}\">\n        <xsl:attribute name=\"class\">\n            <xsl:apply-templates select=\".\" mode=\"html-list-class\" />\n            <xsl:variable name=\"ol-marker-class\">\n                <xsl:apply-templates select=\".\" mode=\"ol-marker-class\" />\n            </xsl:variable>\n            <xsl:if test=\"not($ol-marker-class = '')\">\n                <xsl:text> </xsl:text>\n                <xsl:value-of select=\"$ol-marker-class\"/>\n            </xsl:if>\n            <xsl:variable name=\"cols-class-name\">\n                <!-- HTML-specific, but in pretext-common.xsl -->\n                <xsl:apply-templates select=\".\" mode=\"number-cols-CSS-class\"/>\n            </xsl:variable>\n            <xsl:if test=\"not($cols-class-name = '')\">\n                <xsl:text> </xsl:text>\n                <xsl:value-of select=\"$cols-class-name\"/>\n            </xsl:if>\n        </xsl:attribute>\n        <xsl:attribute name=\"id\">\n            <xsl:apply-templates select=\".\" mode=\"html-id\" />\n        </xsl:attribute>\n        <xsl:if test=\"$ptx-format-code = '0'\">\n            <xsl:attribute name=\"start\">\n                <xsl:text>0</xsl:text>\n            </xsl:attribute>\n        </xsl:if>\n        <xsl:apply-templates select=\"li\">\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n    </xsl:element>\n</xsl:template>\n\n<xsl:template match=\"ol[@marker]\" mode=\"ol-marker-class\">\n    <xsl:variable name=\"marker-value\" select=\"./@marker\" />\n    <xsl:for-each select=\"exsl:node-set($ol-markers)\">\n        <!-- Should be only one match since ol marker -->\n        <!-- index node set contains no duplicates    -->\n        <xsl:value-of select=\"key('marker-key', $marker-value)[1]/@classname\"/>\n    </xsl:for-each >\n</xsl:template>\n\n<xsl:template match=\"ol[not(@marker) and @pi:format-code = 'a' and @pi:ordered-list-level = '1']\" mode=\"ol-marker-class\">\n    <xsl:text>lower-alpha-level-1</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"ol|ul\" mode=\"ol-marker-class\"/>\n\n<xsl:template match=\"ol[@marker]\" mode=\"ol-markers\">\n    <xsl:element name=\"ol-marker\">\n        <xsl:copy-of select=\"@pi:format-code\"/>\n        <xsl:copy-of select=\"@marker\"/>\n        <xsl:copy-of select=\"@pi:marker-prefix\"/>\n        <xsl:copy-of select=\"@pi:marker-suffix\"/>\n        <xsl:attribute name=\"classname\">\n            <xsl:text>ol-marker-</xsl:text>\n            <xsl:value-of select=\"position()\" />\n        </xsl:attribute>\n    </xsl:element>\n</xsl:template>\n\n<!-- Creates custom formatting for each unique ol/@marker -->\n<xsl:template match=\"ol-marker\" mode=\"ol-marker-style\">\n    <!-- format child li elements according to marker prefix/code/suffix -->\n    <xsl:text>ol.</xsl:text>\n    <xsl:value-of select=\"./@classname\"/>\n    <xsl:text> &gt; li::marker { content: &quot;</xsl:text>\n    <xsl:value-of select=\"./@pi:marker-prefix\" />\n    <xsl:text>&quot;counter(list-item,</xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"html-list-class\" />\n    <xsl:text>)&quot;</xsl:text>\n    <xsl:value-of select=\"./@pi:marker-suffix\" />\n    <xsl:text> &quot;; }&#xa;</xsl:text>\n</xsl:template>\n\n<!-- CSS file for custom ol markers -->\n<xsl:template name=\"ol-marker-styles\">\n    <!-- We don't produce a file if it will be empty. This would  -->\n    <!-- \"naturally\" be the case, but we have a boolean anyway.   -->\n    <xsl:if test=\"$b-needs-custom-marker-css\">\n        <xsl:variable name=\"ol-marker-nodes\" select=\"exsl:node-set($ol-markers)\" />\n        <exsl:document href=\"{$html.css.dir}/ol-markers.css\" method=\"text\">\n            <xsl:apply-templates select=\"$ol-marker-nodes//ol-marker\" mode=\"ol-marker-style\" />\n        </exsl:document>\n    </xsl:if>\n</xsl:template>\n\n<!-- We let CSS react to narrow titles for dl -->\n<!-- But no support for multiple columns      -->\n<!-- tunnel duplication flag to list items -->\n<xsl:template match=\"dl\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n    <dl>\n        <xsl:attribute name=\"class\">\n            <xsl:choose>\n                <xsl:when test=\"@width = 'narrow'\">\n                    <xsl:text>description-list narrow</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"@width = 'wide'\">\n                    <xsl:text>description-list wide</xsl:text>\n                </xsl:when>\n                <!-- 'medium' and any typo (let DTD check) -->\n                <xsl:otherwise>\n                    <xsl:text>description-list</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:attribute>\n        <xsl:apply-templates select=\"li\">\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n    </dl>\n</xsl:template>\n\n<!-- ###### -->\n<!-- Images -->\n<!-- ###### -->\n\n<!-- A bare image, or an image in a PTX \"figure\" that is not part  -->\n<!-- of a panel of a \"sidebyside\", can be given horizontal layout  -->\n<!-- control.  This is placed on a constraining \"div.image-box\"    -->\n<!-- via the \"@style\" attribute.  The image simply \"grows\" to      -->\n<!-- fill this box horizontally, with necessary vertical dimension -->\n<!-- to preserve the aspect ratio.  This div is also used to       -->\n<!-- provide vertical spacing from its surroundings.               -->\n<xsl:template match=\"image[not(ancestor::sidebyside)]\">\n    <xsl:variable name=\"rtf-layout\">\n        <xsl:apply-templates select=\".\" mode=\"layout-parameters\" />\n    </xsl:variable>\n    <xsl:variable name=\"layout\" select=\"exsl:node-set($rtf-layout)\" />\n    <!-- div is constraint/positioning for contained image -->\n    <div class=\"image-box\">\n        <xsl:attribute name=\"style\">\n            <xsl:text>width: </xsl:text>\n            <xsl:value-of select=\"$layout/width\"/>\n            <xsl:text>%;</xsl:text>\n            <xsl:text> margin-left: </xsl:text>\n            <xsl:value-of select=\"$layout/left-margin\"/>\n            <xsl:text>%;</xsl:text>\n            <xsl:text> margin-right: </xsl:text>\n            <xsl:value-of select=\"$layout/right-margin\"/>\n            <xsl:text>%;</xsl:text>\n        </xsl:attribute>\n        <xsl:apply-templates select=\".\" mode=\"image-inclusion\"/>\n    </div>\n</xsl:template>\n\n<xsl:template match=\"mermaid[ancestor::image]\" mode=\"image-inclusion\">\n    <pre class=\"mermaid\">\n        <xsl:value-of select=\".\" />\n    </pre>\n</xsl:template>\n\n<!-- The div for a panel of a sidebyside will provide  -->\n<!-- the constraint/positioning of the contained image -->\n<!-- If the panel is a PTX \"figure\" then there will be -->\n<!-- an intermediate HTML \"figure\" which will not      -->\n<!-- interfere with the panel's constraints            -->\n<xsl:template match=\"image[ancestor::sidebyside]\">\n    <div class=\"image-box\">\n        <xsl:apply-templates select=\".\" mode=\"image-inclusion\" />\n    </div>\n</xsl:template>\n\n<!-- With a @source attribute, without an extension, -->\n<!--   we presume an SVG has been manufactured       -->\n<!-- With a @source attribute, with an extension,    -->\n<!--   we write an HTML \"img\" tag with attributes    -->\n<xsl:template match=\"image[@source|@pi:generated]\" mode=\"image-inclusion\">\n    <!-- condition on file extension -->\n    <!-- no period, lowercase'ed     -->\n    <xsl:variable name=\"extension\">\n        <xsl:call-template name=\"file-extension\">\n            <xsl:with-param name=\"filename\">\n                <xsl:choose>\n                    <xsl:when test=\"@pi:generated\">\n                        <xsl:value-of select=\"@pi:generated\"/>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:value-of select=\"@source\"/>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:with-param>\n        </xsl:call-template>\n    </xsl:variable>\n    <!-- location of image, based on configured directory in publisher file -->\n    <xsl:variable name=\"location\">\n        <xsl:choose>\n            <xsl:when test=\"@pi:generated\">\n                <xsl:value-of select=\"$generated-directory\"/>\n                <xsl:value-of select=\"@pi:generated\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <!-- empty when not using managed directories -->\n                <xsl:value-of select=\"$external-directory\"/>\n                <xsl:value-of select=\"@source\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:choose>\n        <!-- no extension, presume SVG provided as external image -->\n        <xsl:when test=\"$extension=''\">\n            <xsl:apply-templates select=\".\" mode=\"svg-png-wrapper\">\n                <xsl:with-param name=\"image-filename\">\n                    <xsl:value-of select=\"$location\"/>\n                    <xsl:text>.svg</xsl:text>\n                </xsl:with-param>\n            </xsl:apply-templates>\n            <!-- possibly annotate with archive links -->\n            <xsl:apply-templates select=\".\" mode=\"archive\">\n                <xsl:with-param name=\"base-pathname\" select=\"$location\"/>\n            </xsl:apply-templates>\n            <!-- possibly give a long description -->\n            <xsl:apply-templates select=\".\" mode=\"description\"/>\n        </xsl:when>\n        <!-- with extension, just include it -->\n        <xsl:otherwise>\n            <img>\n                <xsl:attribute name=\"src\">\n                    <xsl:value-of select=\"$location\"/>\n                </xsl:attribute>\n                <xsl:attribute name=\"class\">\n                    <xsl:text>contained</xsl:text>\n                </xsl:attribute>\n                <!-- alt attribute for accessibility -->\n                <xsl:choose>\n                    <xsl:when test=\"@decorative = 'yes'\">\n                        <xsl:attribute name=\"alt\"/>\n                    </xsl:when>\n                    <xsl:when test=\"not(string(shortdescription) = '')\">\n                        <xsl:attribute name=\"alt\">\n                            <xsl:apply-templates select=\"shortdescription\" />\n                        </xsl:attribute>\n                    </xsl:when>\n                    <xsl:when test=\"description\">\n                        <xsl:attribute name=\"alt\">\n                            <xsl:text>described in detail following the image</xsl:text>\n                        </xsl:attribute>\n                        <xsl:attribute name=\"aria-describedby\">\n                            <xsl:apply-templates select=\".\" mode=\"describedby-id\"/>\n                        </xsl:attribute>\n                    </xsl:when>\n                </xsl:choose>\n                <xsl:if test=\"@rotate\">\n                    <xsl:attribute name=\"style\">\n                        <xsl:text>transform: rotate(</xsl:text>\n                        <xsl:value-of select=\"@rotate\"/>\n                        <xsl:text>deg)</xsl:text>\n                    </xsl:attribute>\n                </xsl:if>\n            </img>\n            <!-- possibly annotate with archive links -->\n            <xsl:apply-templates select=\".\" mode=\"archive\">\n                <xsl:with-param name=\"base-pathname\">\n                    <!-- empty when not using managed directories -->\n                    <xsl:value-of select=\"$external-directory\"/>\n                    <xsl:call-template name=\"substring-before-last\">\n                        <xsl:with-param name=\"input\" select=\"$location\" />\n                        <xsl:with-param name=\"substr\" select=\"'.'\" />\n                    </xsl:call-template>\n                </xsl:with-param>\n            </xsl:apply-templates>\n            <!-- possibly give a long description -->\n            <xsl:apply-templates select=\".\" mode=\"description\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- SVG's produced by pretext/pretext script -->\n<!-- Minor variations to be dual-purpose      -->\n<!--   LaTeX source code images               -->\n<!--   PreFigure source code images           -->\n<xsl:template match=\"image[latex-image]|image[pf:prefigure]\" mode=\"image-inclusion\">\n    <!-- $base-pathname needed later for archive links -->\n    <xsl:variable name=\"base-pathname\">\n        <xsl:value-of select=\"$generated-directory\"/>\n        <xsl:choose>\n            <xsl:when test=\"latex-image\">\n                <xsl:text>latex-image/</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"pf:prefigure\">\n                <xsl:text>prefigure/</xsl:text>\n            </xsl:when>\n        </xsl:choose>\n        <!-- NB: node-set in @select will have exactly -->\n        <!-- one (child) node, given @match above      -->\n        <xsl:apply-templates select=\"latex-image|pf:prefigure\" mode=\"image-source-basename\"/>\n    </xsl:variable>\n    <!-- Normally the \"svg-png-wrapper\" will create a \"standard\" HTML      -->\n    <!-- object to hold the image.  For an annotated PreFigure diagram     -->\n    <!-- we need a custom embedding for the diagcess JS to act on.  The    -->\n    <!-- two files (SVG image, XML annotations) are products of PreFigure. -->\n\n    <xsl:choose>\n        <xsl:when test=\"$b-portable-html and (latex-image|pf:prefigure[not(pf:diagram/pf:annotations)])\">\n            <xsl:apply-templates select=\".\" mode=\"svg-embedded\"/>\n        </xsl:when>\n        <xsl:when test=\"latex-image|pf:prefigure[not(pf:diagram/pf:annotations)]\">\n            <xsl:apply-templates select=\".\" mode=\"svg-png-wrapper\">\n                <xsl:with-param name=\"image-filename\" select=\"concat($base-pathname, '.svg')\" />\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:when test=\"pf:prefigure[pf:diagram/pf:annotations]\">\n            <div class=\"ChemAccess-element\">\n                <xsl:attribute name=\"data-src\">\n                    <xsl:value-of select=\"$base-pathname\"/>\n                    <xsl:text>-diagcess.svg</xsl:text>\n                </xsl:attribute>\n                <xsl:attribute name=\"data-cml\">\n                    <xsl:value-of select=\"$base-pathname\"/>\n                    <xsl:text>-annotations.xml</xsl:text>\n                </xsl:attribute>\n            </div>\n            <!-- a named template provides keyboard shortcuts for  -->\n            <!-- the library powering exploration of the PreFigure -->\n            <!-- diagram authored with annotations                 -->\n            <!-- We defer if we are inside a setting where we      -->\n            <!-- might get multiple instances of instructions      -->\n            <!-- right next to each other.  This test will include -->\n            <!-- being inside a \"subsgroup\" as well.               -->\n            <xsl:if test=\"not(ancestor::sidebyside)\">\n                <xsl:call-template name=\"diagacess-instructions\"/>\n            </xsl:if>\n        </xsl:when>\n        <!-- cases should be exhaustive, given match and tests-->\n        <xsl:otherwise/>\n    </xsl:choose>\n    <!-- possibly annotate with archive links -->\n    <xsl:apply-templates select=\".\" mode=\"archive\">\n        <xsl:with-param name=\"base-pathname\" select=\"$base-pathname\" />\n    </xsl:apply-templates>\n    <!-- possibly give a long description -->\n    <xsl:apply-templates select=\".\" mode=\"description\"/>\n</xsl:template>\n\n<xsl:template match=\"image[sageplot]\" mode=\"image-inclusion\">\n    <!-- $base-pathname needed later for archive links -->\n    <xsl:variable name=\"base-pathname\">\n        <xsl:value-of select=\"$generated-directory\"/>\n        <xsl:text>sageplot/</xsl:text>\n        <xsl:apply-templates select=\"sageplot\" mode=\"image-source-basename\"/>\n    </xsl:variable>\n    <!-- 2d are SVG, 3d are HTML -->\n    <xsl:choose>\n        <xsl:when test=\"not(sageplot/@variant) or (sageplot/@variant = '2d')\">\n            <!-- construct the \"img\" element -->\n            <xsl:apply-templates select=\".\" mode=\"svg-png-wrapper\">\n                <xsl:with-param name=\"image-filename\" select=\"concat($base-pathname, '.svg')\" />\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:when test=\"sageplot/@variant = '3d'\">\n            <iframe>\n                <xsl:apply-templates select=\".\" mode=\"size-pixels-attributes\" />\n                <xsl:attribute name=\"src\">\n                    <xsl:value-of select=\"$base-pathname\"/>\n                    <xsl:text>.html</xsl:text>\n                </xsl:attribute>\n            </iframe>\n        </xsl:when>\n        <!-- attribute errors found out in generation? -->\n        <xsl:otherwise/>\n    </xsl:choose>\n    <!-- possibly annotate with archive links -->\n    <xsl:apply-templates select=\".\" mode=\"archive\">\n        <xsl:with-param name=\"base-pathname\" select=\"$base-pathname\" />\n    </xsl:apply-templates>\n    <!-- possibly give a long description -->\n    <xsl:apply-templates select=\".\" mode=\"description\"/>\n</xsl:template>\n\n<!-- Asymptote graphics language -->\n<xsl:template match=\"image[asymptote]\" mode=\"image-inclusion\">\n    <!-- base-pathname needed later for archive link production. This   -->\n    <!-- is the location for eventual output, in contrast to juat below -->\n    <!-- for source analysis.                                           -->\n    <xsl:variable name=\"base-pathname\">\n        <xsl:value-of select=\"$generated-directory\"/>\n        <xsl:text>asymptote/</xsl:text>\n        <xsl:apply-templates select=\"asymptote\" mode=\"image-source-basename\"/>\n    </xsl:variable>\n    <xsl:variable name=\"html-filename\" select=\"concat($base-pathname, '.html')\" />\n    <!-- We also need a path to the *source* file, for examination -->\n    <!-- to determine the aspect ratio of the diagram, in order to -->\n    <!-- insert correctly as a scaled instance                     -->\n    <xsl:variable name=\"html-source-filename\">\n        <xsl:value-of select=\"$generated-directory-source\"/>\n        <xsl:text>asymptote/</xsl:text>\n        <xsl:apply-templates select=\"asymptote\" mode=\"image-source-basename\"/>\n        <xsl:text>.html</xsl:text>\n    </xsl:variable>\n    <!-- Assumes filename is relative to primary source file, -->\n    <!-- which must be specified with the original version,   -->\n    <!-- not the pre-processed, \"assembled\" version           -->\n    <xsl:variable name=\"image-xml\" select=\"document($html-source-filename, $original)\"/>\n\n    <!-- width first -->\n    <xsl:variable name=\"width\">\n        <xsl:choose>\n            <!-- 2-D diagram -->\n            <!-- note necessity of namespace for \"svg\" element -->\n            <xsl:when test=\"$image-xml/html/body/svg:svg\">\n                <xsl:variable name=\"wpt\" select=\"$image-xml/html/body/svg:svg/@width\"/>\n                <!-- Strip \"pt\" suffix -->\n                <xsl:value-of select=\"substring($wpt, 1, string-length($wpt) - 2)\"/>\n            </xsl:when>\n            <!-- 3-D diagram -->\n            <xsl:when test=\"$image-xml/html/body/canvas\">\n                <xsl:value-of select=\"$image-xml/html/body/canvas/@width\"/>\n            </xsl:when>\n            <!-- failure -->\n            <xsl:otherwise>\n                <xsl:message>PTX:FALLBACK:   the Asymptote diagram produced in \"<xsl:value-of select=\"$image-xml\"/>\" needs to be available relative to the primary source file, or if available it is perhaps ill-formed and its width cannot be determined (which you might report as a bug).  We might be able to proceed as if the diagram is square, but results can be unpredictable.</xsl:message>\n                <!-- reasonable guess at points/pixels -->\n                <xsl:text>400</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- now height, similarly -->\n    <xsl:variable name=\"height\">\n        <xsl:choose>\n            <!-- 2-D diagram -->\n            <!-- note necessity of namespace for \"svg\" element -->\n            <xsl:when test=\"$image-xml/html/body/svg:svg\">\n                <xsl:variable name=\"hpt\" select=\"$image-xml/html/body/svg:svg/@height\"/>\n                <!-- Strip \"pt\" suffix -->\n                <xsl:value-of select=\"substring($hpt, 1, string-length($hpt) - 2)\"/>\n            </xsl:when>\n            <!-- 3-D diagram -->\n            <xsl:when test=\"$image-xml/html/body/canvas\">\n                <xsl:value-of select=\"$image-xml/html/body/canvas/@height\"/>\n            </xsl:when>\n            <!-- failure -->\n            <xsl:otherwise>\n                <xsl:message>PTX:FALLBACK:   the Asymptote diagram produced in \"<xsl:value-of select=\"$image-xml\"/>\" needs to be available relative to the primary source file, or if available it is perhaps ill-formed and its height cannot be determined (which you might report as a bug).  We might be able to proceed as if the diagram is square, but results can be unpredictable.</xsl:message>\n                <!-- reasonable guess at points/pixels -->\n                <xsl:text>400</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- All that was to get an aspect-ratio for a responsive iframe embedding -->\n    <xsl:variable name=\"aspect-percent\" select=\"($height div $width) * 100\"/>\n\n    <!-- Surrounding/constraining \"image\", or \"sidebyside\" panel, or ...    -->\n    <!-- will provide an overall width.  The \"padding-top\" property is what -->\n    <!-- makes the right shape.  CSS provides some constant properties.     -->\n    <div class=\"asymptote-box\" style=\"padding-top: {$aspect-percent}%\">\n        <iframe src=\"{$html-filename}\" class=\"asymptote\">\n            <xsl:if test=\"shortdescription\">\n                <xsl:attribute name=\"title\">\n                    <xsl:value-of select=\"shortdescription\"/>\n                </xsl:attribute>\n            </xsl:if>\n        </iframe>\n    </div>\n    <!-- possibly annotate with archive links -->\n    <xsl:apply-templates select=\".\" mode=\"archive\">\n        <xsl:with-param name=\"base-pathname\" select=\"$base-pathname\" />\n    </xsl:apply-templates>\n    <!-- possibly provide link to full size image -->\n    <!-- need to set html/asymptote@links=\"yes\" in publisher file to enable -->\n    <xsl:if test=\"$b-asymptote-html-links\">\n      <xsl:variable name=\"image-html-url\">\n          <xsl:value-of select=\"$baseurl\"/>\n          <xsl:value-of select=\"$html-filename\"/>\n      </xsl:variable>\n      <div class=\"asymptote-fullsize-link\">\n        <a href=\"{$image-html-url}\">Link to full-sized image</a>\n      </div>\n    </xsl:if>\n    <!-- possibly give a long description -->\n    <xsl:apply-templates select=\".\" mode=\"description\"/>\n</xsl:template>\n\n<!-- The infrastructure for an SVG or PNG image      -->\n<!-- Parameters                                      -->\n<!--   image-filename: required, full relative path  -->\n<!-- NB: (2020-01-18) Prior, this was SVG specific,  -->\n<!-- and then PNG functionality was folded in (when  -->\n<!-- fallback for \"sageplot\" was no longer necessary -->\n<xsl:template match=\"image\" mode=\"svg-png-wrapper\">\n    <xsl:param name=\"image-filename\" />\n    <img>\n        <!-- source file attribute for img element, the SVG image -->\n        <xsl:attribute name=\"src\">\n            <xsl:value-of select=\"$image-filename\" />\n        </xsl:attribute>\n        <!-- For accessibility use an ARIA role, e.g so screen  -->\n        <!-- readers do not try to read the elements of the SVG -->\n        <!-- NB: if we write SVG into the page, put this        -->\n        <!-- attribute onto the \"svg\" element                   -->\n        <xsl:attribute name=\"role\">\n            <xsl:text>img</xsl:text>\n        </xsl:attribute>\n        <xsl:attribute name=\"class\">\n            <xsl:text>contained</xsl:text>\n        </xsl:attribute>\n        <!-- alt attribute for accessibility -->\n        <xsl:choose>\n            <xsl:when test=\"@decorative = 'yes'\">\n                <xsl:attribute name=\"alt\"/>\n            </xsl:when>\n            <xsl:when test=\"shortdescription\">\n                <xsl:attribute name=\"alt\">\n                    <xsl:apply-templates select=\"shortdescription\"/>\n                </xsl:attribute>\n            </xsl:when>\n            <xsl:when test=\"description\">\n                <xsl:attribute name=\"alt\">\n                    <xsl:text>described in detail following the image</xsl:text>\n                </xsl:attribute>\n                <xsl:attribute name=\"aria-describedby\">\n                    <xsl:apply-templates select=\".\" mode=\"describedby-id\"/>\n                </xsl:attribute>\n            </xsl:when>\n        </xsl:choose>\n    </img>\n</xsl:template>\n\n<!-- Instead of linking to an svg file as in the modal svg-png-wrapper above  -->\n<!-- we can include the svg directly in the html document, which is what      -->\n<!-- this does.  Used with b-portable-html is true, at least now (2025-03-04) -->\n<xsl:template match=\"image\" mode=\"svg-embedded\">\n    <!-- Get the filename of the generated svg file -->\n    <xsl:variable name=\"svg-source-filename\">\n        <xsl:value-of select=\"$generated-directory-source\" />\n        <xsl:choose>\n            <xsl:when test=\"latex-image\">\n                <xsl:text>latex-image/</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"pf:prefigure\">\n                <xsl:text>prefigure/</xsl:text>\n            </xsl:when>\n        </xsl:choose>\n        <xsl:apply-templates select=\"latex-image|pf:prefigure\" mode=\"image-source-basename\"/>\n        <xsl:text>.svg</xsl:text>\n    </xsl:variable>\n    <!-- Get the SVG file as an XML document -->\n    <xsl:variable name=\"image-svg-xml\" select=\"document($svg-source-filename, $original)\" />\n    <!-- Create an SVG element with the contents of the SVG file -->\n    <svg xmlns=\"http://www.w3.org/2000/svg\">\n        <xsl:copy-of select=\"$image-svg-xml/svg:svg/namespace::*\"/>\n        <xsl:copy-of select=\"$image-svg-xml/svg:svg/@version\"/>\n        <!-- Keep the viewbox, or create one based on the height and width -->\n        <xsl:choose>\n            <xsl:when test=\"$image-svg-xml/svg:svg/@viewBox\">\n                <xsl:attribute name=\"viewBox\">\n                    <xsl:value-of select=\"$image-svg-xml/svg:svg/@viewBox\"/>\n                </xsl:attribute>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:attribute name=\"viewBox\">\n                    <xsl:text>0 0 </xsl:text>\n                    <xsl:value-of select=\"$image-svg-xml/svg:svg/@width\"/>\n                    <xsl:text> </xsl:text>\n                    <xsl:value-of select=\"$image-svg-xml/svg:svg/@height\"/>\n                </xsl:attribute>\n            </xsl:otherwise>\n        </xsl:choose>\n        <xsl:copy-of select=\"$image-svg-xml/svg:svg/@viewBox\"/>\n        <xsl:attribute name=\"role\">\n            <xsl:text>img</xsl:text>\n        </xsl:attribute>\n        <xsl:attribute name=\"class\">\n            <xsl:text>contained</xsl:text>\n        </xsl:attribute>\n        <xsl:choose>\n            <xsl:when test=\"@decorative = 'yes'\">\n                <xsl:attribute name=\"aria-hidden\">\n                    <xsl:text>true</xsl:text>\n                </xsl:attribute>\n            </xsl:when>\n            <xsl:when test=\"shortdescription\">\n                <xsl:attribute name=\"aria-label\">\n                    <xsl:apply-templates select=\"shortdescription\"/>\n                </xsl:attribute>\n            </xsl:when>\n            <xsl:when test=\"description\">\n                <xsl:attribute name=\"aria-describedby\">\n                    <xsl:apply-templates select=\".\" mode=\"describedby-id\"/>\n                </xsl:attribute>\n            </xsl:when>\n            <xsl:otherwise/>\n        </xsl:choose>\n        <xsl:if test=\"shortdescription\">\n            <title>\n                <xsl:apply-templates select=\"shortdescription\"/>\n            </title>\n        </xsl:if>\n        <xsl:if test=\"description\">\n            <desc>\n                <xsl:apply-templates select=\"description\"/>\n            </desc>\n        </xsl:if>\n        <!-- Need to add unique ids to latex-image svgs (prefigure does this automatically) -->\n        <xsl:choose>\n            <xsl:when test=\"latex-image\">\n                <xsl:apply-templates select=\"$image-svg-xml/svg:svg/*\" mode=\"svg-unique-ids\">\n                    <xsl:with-param name=\"svg-unique-id\">\n                        <xsl:value-of select=\"@pi:unique-id\"/>\n                    </xsl:with-param>\n                </xsl:apply-templates>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:copy-of select=\"$image-svg-xml/svg:svg/*\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </svg>\n</xsl:template>\n\n<!-- When embedding multiple svgs in a single page, the ids used     -->\n<!-- to refer to svg elements can collide.  This recursively adds    -->\n<!-- a unique id (per svg) suffix to all id and xlink:href elements. -->\n\n<xsl:template match=\"node()|@*\" mode=\"svg-unique-ids\">\n    <xsl:param name=\"svg-unique-id\"/>\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"svg-unique-ids\">\n            <xsl:with-param name=\"svg-unique-id\" select=\"$svg-unique-id\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<xsl:template match=\"@id|@xlink:href\" mode=\"svg-unique-ids\">\n    <xsl:param name=\"svg-unique-id\"/>\n    <xsl:attribute name=\"{local-name()}\">\n        <xsl:value-of select=\".\"/>\n        <xsl:text>_</xsl:text>\n        <xsl:value-of select=\"$svg-unique-id\"/>\n    </xsl:attribute>\n</xsl:template>\n\n\n<xsl:template match=\"image|interactive[@platform|@desmos|@calcplot3d|@circuitjs|@iframe]\" mode=\"description\">\n    <xsl:if test=\"description\">\n        <!-- @aria-live means screenreaders will make announcements -->\n        <details class=\"image-description\" aria-live=\"polite\">\n            <summary title=\"details\">\n                <xsl:call-template name=\"insert-symbol\">\n                    <xsl:with-param name=\"name\" select=\"'info'\"/>\n                </xsl:call-template>\n            </summary>\n            <div>\n                <xsl:attribute name=\"id\">\n                    <xsl:apply-templates select=\".\" mode=\"describedby-id\"/>\n                </xsl:attribute>\n                <xsl:apply-templates select=\"description\"/>\n            </div>\n        </details>\n    </xsl:if>\n</xsl:template>\n\n<!-- Utility template so \"aria-describedby\" values are consistent -->\n<xsl:template match=\"image|interactive[@platform|@desmos|@calcplot3d|@circuitjs|@iframe]\" mode=\"describedby-id\">\n    <xsl:apply-templates select=\".\" mode=\"unique-id\"/>\n    <xsl:text>-description</xsl:text>\n</xsl:template>\n\n<!-- Diagacess Instructions -->\n\n<xsl:template name=\"diagacess-instructions\">\n    <details class=\"instructions diagcess__instructions\">\n        <summary>Diagram Exploration Keyboard Controls</summary>\n        <div class=\"diagcess-navigation-controls\">\n            <table>\n            <thead>\n            <tr>\n            <th>Key</th>\n            <th>Action</th>\n            </tr>\n            </thead>\n            <tbody>\n            <tr>\n            <td>Enter, A</td>\n            <td>Activate keyboard driven exploration</td>\n            </tr>\n            <tr>\n            <td>B</td>\n            <td>Activate menu driven exploration</td>\n            </tr>\n            <tr>\n            <td>Escape</td>\n            <td>Leave exploration mode</td>\n            </tr>\n            <tr>\n            <td>Cursor down</td>\n            <td>Explore next lower level</td>\n            </tr>\n            <tr>\n            <td>Cursor up</td>\n            <td>Explore next upper level</td>\n            </tr>\n            <tr>\n            <td>Cursor right</td>\n            <td>Explore next element on level</td>\n            </tr>\n            <tr>\n            <td>Cursor left</td>\n            <td>Explore previous element on level</td>\n            </tr>\n            <tr>\n            <td>X</td>\n            <td>Toggle expert mode</td>\n            </tr>\n            <tr>\n            <td>W</td>\n            <td>Extra details if available</td>\n            </tr>\n            <tr>\n            <td>Space</td>\n            <td>Repeat speech</td>\n            </tr>\n            <tr>\n            <td>M</td>\n            <td>Activate step magnification</td>\n            </tr>\n            <tr>\n            <td>Comma</td>\n            <td>Activate direct magnification</td>\n            </tr>\n            <tr>\n            <td>N</td>\n            <td>Deactivate magnification</td>\n            </tr>\n            <tr>\n            <td>Z</td>\n            <td>Toggle subtitles</td>\n            </tr>\n            <tr>\n            <td>C</td>\n            <td>Cycle contrast settings</td>\n            </tr>\n            <tr>\n            <td>T</td>\n            <td>Monochrome colours</td>\n            </tr>\n            <tr>\n            <td>L</td>\n            <td>Toggle language (if available)</td>\n            </tr>\n            <tr>\n            <td>K</td>\n            <td>Kill current sound</td>\n            </tr>\n            <tr>\n            <td>Y</td>\n            <td>Stop sound output</td>\n            </tr>\n            <tr>\n            <td>O</td>\n            <td>Start and stop sonification</td>\n            </tr>\n            <tr>\n            <td>P</td>\n            <td>Repeat sonification output</td>\n            </tr>\n            </tbody>\n            </table>\n        </div>\n    </details>\n</xsl:template>\n\n\n<!-- Image Archives -->\n<!-- Under an image provide a set of (download) links              -->\n<!-- for archival versions of the image in different formats       -->\n<!--                                                               -->\n<!-- 1.  @archive is a space-delimited list of file suffixes       -->\n<!-- 2.  Author must ensure the versions are next to file employed -->\n<!-- 3.  Formatting and case of suffixes is author's choice        -->\n<!-- 4.  Order in suffix list is respected in output               -->\n<!-- 5.  Per-image, with global spec in the publication file       -->\n<!--     (\"/publication/html/images/archive\"); the old location    -->\n<!--     within \"docinfo\" is honored while the former is silent    -->\n<!--                                                               -->\n<!-- The originating image template knows/computes the filename,   -->\n<!-- so this template accepts the filename, sans period and        -->\n<!-- extension, to transmit to the actual link production where    -->\n<!-- different extensions are added                                -->\n<!--                                                               -->\n<xsl:template match=\"image\" mode=\"archive\">\n    <xsl:param name=\"base-pathname\" />\n    <!-- Determine requested archive links            -->\n    <!-- Local request on image overrides global      -->\n    <!-- If $formats ends empty, then nothing happens -->\n    <xsl:variable name=\"formats\">\n        <xsl:choose>\n            <!-- local, given on image, including suppression -->\n            <xsl:when test=\"@archive\">\n                <xsl:value-of select=\"normalize-space(@archive)\" />\n            </xsl:when>\n            <!-- semi-local, semi-global via subtree specification     -->\n            <!-- last in list that contains the image wins             -->\n            <!-- Documented heavily as first \"mid-range\" specification -->\n            <!-- A single @from puts us in mid-range mode              -->\n            <xsl:when test=\"$image-archives[@from]\">\n                <!-- An \"archive\" node may live in the publication file,  -->\n                <!-- so the id() lookup for its @from must be evaluated   -->\n                <!-- with the context switched into the (assembled)       -->\n                <!-- source, where the present \"image\" lives.             -->\n                <xsl:variable name=\"the-image\" select=\".\" />\n                <!-- Test each \"archive\" with @from, in document order:     -->\n                <!-- Form two subtrees of all descendant nodes, rooted at   -->\n                <!--   (1) the image node                                   -->\n                <!--   (2) the node pointed to by @from                     -->\n                <!-- The pipe forms a union of the nodes in the subtrees    -->\n                <!-- \"image\" is on the subtree @from iff union is no larger -->\n                <!-- Each containing \"archive\" records its formats, so the  -->\n                <!-- effective (last) one can be read off the collection.   -->\n                <xsl:variable name=\"containing-archives-rtf\">\n                    <xsl:for-each select=\"$image-archives[@from]\">\n                        <xsl:variable name=\"the-formats\" select=\"string(.)\"/>\n                        <xsl:variable name=\"the-from\" select=\"string(@from)\"/>\n                        <xsl:for-each select=\"$the-image\">\n                            <xsl:if test=\"count($the-image/descendant-or-self::node()|id($the-from)/descendant-or-self::node())=count(id($the-from)/descendant-or-self::node())\">\n                                <pi:archive-formats>\n                                    <xsl:value-of select=\"$the-formats\"/>\n                                </pi:archive-formats>\n                            </xsl:if>\n                        </xsl:for-each>\n                    </xsl:for-each>\n                </xsl:variable>\n                <!-- We mimic XSL and the last applicable \"archive\" is effective -->\n                <!-- This way, big subtrees go first, included subtrees refine   -->\n                <!-- @from can be an empty string and turn off the behavior      -->\n                <!-- We grab the content of the last \"archive\" to be the formats -->\n                <xsl:value-of select=\"exsl:node-set($containing-archives-rtf)/pi:archive-formats[last()]\" />\n            </xsl:when>\n            <!-- global, presumes one only, ignores subtree versions -->\n            <xsl:when test=\"$image-archives[not(@from)]\">\n                <xsl:value-of select=\"normalize-space($image-archives)\" />\n            </xsl:when>\n            <!-- nothing begets nothing -->\n            <xsl:otherwise />\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:if test=\"not($formats = '')\">\n        <!-- Build the links with recursion through formats    -->\n        <!-- First wrap resulting links in overall styling div -->\n        <xsl:element name=\"div\">\n            <xsl:attribute name=\"class\">\n                <xsl:text>image-archive</xsl:text>\n            </xsl:attribute>\n            <!-- Add trailing space as marker for recursion finale -->\n            <xsl:call-template name=\"archive-links\">\n                <xsl:with-param name=\"base-pathname\" select=\"$base-pathname\" />\n                <xsl:with-param name=\"formats\" select=\"concat($formats, ' ')\" />\n            </xsl:call-template>\n        </xsl:element>\n    </xsl:if>\n</xsl:template>\n\n<!-- $base-pathname has no concluding -->\n<!-- period, so we add it here        -->\n<xsl:template name=\"archive-links\">\n    <xsl:param name=\"base-pathname\" />\n    <xsl:param name=\"formats\" />\n    <!-- stop recursion if empty (note extra space added in initial call) -->\n    <xsl:if test=\"not($formats = '')\">\n        <xsl:variable name=\"next-format\" select=\"substring-before($formats, ' ')\" />\n        <xsl:variable name=\"remaining-formats\" select=\"substring-after($formats, ' ')\" />\n        <!-- link to the file, author's responsibility  -->\n        <!-- add period, and the suffix to rest of path -->\n        <!-- text of link is the format suffix verbatim -->\n        <xsl:element name=\"a\">\n            <xsl:attribute name=\"href\">\n                <xsl:value-of select=\"$base-pathname\" />\n                <xsl:text>.</xsl:text>\n                <xsl:value-of select=\"$next-format\" />\n            </xsl:attribute>\n            <xsl:value-of select=\"$next-format\" />\n        </xsl:element>\n        <!-- recurse through remaining formats -->\n        <xsl:call-template name=\"archive-links\">\n            <xsl:with-param name=\"base-pathname\" select=\"$base-pathname\" />\n            <xsl:with-param name=\"formats\" select=\"$remaining-formats\" />\n        </xsl:call-template>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- ################## -->\n<!-- SideBySide Layouts -->\n<!-- ################## -->\n\n<!-- See xsl/pretext-common.xsl for descriptions of the  -->\n<!-- four modal templates which must be implemented here  -->\n<!-- The main templates for \"sidebyside\" and \"sbsgroup\"   -->\n<!-- are in xsl/pretext-common.xsl, as befits containers -->\n\n\n<xsl:template name=\"sbsgroup-wrapper\">\n    <xsl:param name=\"sbsgroup-content\"/>\n    <!-- newline inserted to encourage formatted output -->\n    <xsl:text>&#xa;</xsl:text>\n    <xsl:element name=\"div\">\n        <xsl:attribute name=\"class\">\n            <xsl:text>sbsgroup</xsl:text>\n        </xsl:attribute>\n        <xsl:copy-of select=\"$sbsgroup-content\"/>\n    </xsl:element>\n</xsl:template>\n\n<!-- When we use CSS margins (or padding), then percentage        -->\n<!-- widths are relative to the remaining space.  This utility    -->\n<!-- takes in a width relative to full-text-width and the margins -->\n<!-- (both with \"%\" attached) and returns the larger percentage   -->\n<!-- of the remaining space.                                      -->\n<xsl:template name=\"relative-width\">\n    <xsl:param name=\"width\" />\n    <xsl:param name=\"left-margin\" />\n    <xsl:param name=\"right-margin\" />\n    <xsl:value-of select=\"(100 * substring-before($width, '%')) div (100 - substring-before($left-margin, '%') - substring-before($right-margin, '%'))\" />\n    <xsl:text>%</xsl:text>\n</xsl:template>\n\n<!-- generic \"panel-panel\" template            -->\n<!-- makes a \"sbspanel\" div of specified width -->\n<!-- calls modal \"panel-html-box\" for contents -->\n<!-- fixed-width class is additional           -->\n<xsl:template match=\"*\" mode=\"panel-panel\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"heading-level\"/>\n\n    <xsl:param name=\"width\" />\n    <xsl:param name=\"left-margin\" />\n    <xsl:param name=\"right-margin\" />\n    <xsl:param name=\"valign\" />\n    <!-- newline inserted to encourage formatted output -->\n    <xsl:text>&#xa;</xsl:text>\n    <xsl:element name=\"div\">\n        <xsl:attribute name=\"class\">\n            <xsl:text>sbspanel</xsl:text>\n            <xsl:if test=\"self::table or self::tabular\">\n                <xsl:text> fixed-width</xsl:text>\n            </xsl:if>\n            <!-- assumes \"sbspanel\" class set vertical direction -->\n            <!-- the CSS class equals the source attribute, but that may change -->\n            <xsl:choose>\n                <xsl:when test=\"$valign = 'top'\">\n                    <xsl:text> sbspanel--top top</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$valign = 'middle'\">\n                    <xsl:text> sbspanel--middle middle</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$valign = 'bottom'\">\n                    <xsl:text> sbspanel--bottom bottom</xsl:text>\n                </xsl:when>\n            </xsl:choose>\n        </xsl:attribute>\n        <xsl:attribute name=\"style\">\n            <xsl:if test=\"$sbsdebug\">\n                <xsl:text>box-sizing: border-box;</xsl:text>\n                <xsl:text>-moz-box-sizing: border-box;</xsl:text>\n                <xsl:text>-webkit-box-sizing: border-box;</xsl:text>\n                <xsl:text>border: 2px solid black;</xsl:text>\n            </xsl:if>\n        </xsl:attribute>\n        <!-- Realize each panel's object -->\n        <xsl:apply-templates select=\".\">\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n            <xsl:with-param name=\"width\" select=\"$width\" />\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n    </xsl:element>\n</xsl:template>\n\n<!-- The finished panels arrive as one opaque fragment and are      -->\n<!-- copied, untouched, into a \"sidebyside\" div holding a single    -->\n<!-- \"sbsrow\" grid div.  All layout (margins, column widths, column -->\n<!-- gap) is declared as CSS on the containers, so wrapping the     -->\n<!-- panels as a unit is exactly the right granularity.  Purely a   -->\n<!-- container, never a target, so no xml:id in source, no HTML id  -->\n<!-- on the div.                                                    -->\n<xsl:template match=\"sidebyside\" mode=\"compose-panels\">\n    <xsl:param name=\"layout\" />\n    <xsl:param name=\"panels\" />\n\n    <xsl:variable name=\"left-margin\"  select=\"$layout/left-margin\" />\n    <xsl:variable name=\"right-margin\" select=\"$layout/right-margin\" />\n\n    <xsl:variable name=\"column-widths\">\n        <xsl:for-each select=\"$layout/width\">\n            <xsl:call-template name=\"relative-width\">\n                <xsl:with-param name=\"width\" select=\".\" />\n                <xsl:with-param name=\"left-margin\"  select=\"$left-margin\" />\n                <xsl:with-param name=\"right-margin\" select=\"$right-margin\" />\n            </xsl:call-template>\n            <xsl:if test=\"following-sibling::width\">\n                <xsl:text> </xsl:text>\n            </xsl:if>\n        </xsl:for-each>\n    </xsl:variable>\n\n    <!-- A \"sidebyside\" div, to contain headers, -->\n    <!-- panels, captions rows as \"sbsrow\" divs  -->\n    <!-- newline inserted to encourage formatted output -->\n    <xsl:text>&#xa;</xsl:text>\n    <xsl:element name=\"div\">\n        <xsl:attribute name=\"class\">\n            <xsl:text>sidebyside</xsl:text>\n        </xsl:attribute>\n        <xsl:if test=\"$sbsdebug\">\n            <xsl:attribute name=\"style\">\n                <xsl:text>box-sizing: border-box;</xsl:text>\n                <xsl:text>-moz-box-sizing: border-box;</xsl:text>\n                <xsl:text>-webkit-box-sizing: border-box;</xsl:text>\n                <xsl:text>border: 2px solid purple;</xsl:text>\n            </xsl:attribute>\n        </xsl:if>\n\n        <!-- Panels in an \"sbsrow\" div, always -->\n        <!-- newline inserted to encourage formatted output -->\n        <xsl:text>&#xa;</xsl:text>\n        <xsl:element name=\"div\">\n            <xsl:attribute name=\"class\">\n                <xsl:text>sbsrow</xsl:text>\n            </xsl:attribute>\n            <!-- margins are custom from source -->\n            <xsl:attribute name=\"style\">\n                <xsl:text>margin-left:</xsl:text>\n                <xsl:value-of select=\"$left-margin\" />\n                <xsl:text>;</xsl:text>\n                <xsl:text>margin-right:</xsl:text>\n                <xsl:value-of select=\"$right-margin\" />\n                <xsl:text>;</xsl:text>\n                <xsl:text>grid-template-columns:</xsl:text>\n                <xsl:value-of select=\"$column-widths\" />\n                <xsl:text>;</xsl:text>\n                <xsl:text>column-gap:</xsl:text>\n                <xsl:value-of select=\"$layout/space-width\" />\n                <xsl:text>;</xsl:text>\n                <xsl:if test=\"$sbsdebug\">\n                    <xsl:text>box-sizing: border-box;</xsl:text>\n                    <xsl:text>-moz-box-sizing: border-box;</xsl:text>\n                    <xsl:text>-webkit-box-sizing: border-box;</xsl:text>\n                    <xsl:text>border: 2px solid green;</xsl:text>\n                    <xsl:text>background: LightGray;</xsl:text>\n                    <xsl:text>background-clip: content-box;</xsl:text>\n                </xsl:if>\n            </xsl:attribute>\n            <xsl:copy-of select=\"$panels\" />\n        </xsl:element>\n\n    </xsl:element>\n</xsl:template>\n\n<!-- We do not want a proliferation of instructions for keyboard        -->\n<!-- shortciuts for exploring PreFigure diagrams with the diagacess     -->\n<!-- library.  See hooks for \"sidebyside\" and \"sbsgroup\" explained      -->\n<!-- in pretext-common.xsl.  Logic here is to follow a \"sidebyside\"     -->\n<!-- with any one panel holding an explorable diagram, unless it is     -->\n<!-- a constituent of a \"sbsgroup\".  Once at the conclusion of a        -->\n<!-- \"sbsgroup\" it is time to present instructions.  Note that these    -->\n<!-- instructions are routinely held up right after a diagram in        -->\n<!-- these scenarios.                                                   -->\n<!-- NB: we tried to add these instructions after an \"apply-imports\"    -->\n<!-- in new templates overriding those in -common, but it appears we    -->\n<!-- cannot pass parameters in, so duplicate content inside             -->\n<!-- \"sidebyside\" (such as formulated for xref knowls) ended up getting -->\n<!-- duplicate HTML id.  So we had to resort to specialty hooks.        -->\n\n<xsl:template match=\"sidebyside\" mode=\"post-sidebyside\">\n    <xsl:if test=\".//pf:annotations and not(parent::sbsgroup)\">\n        <xsl:call-template name=\"diagacess-instructions\"/>\n    </xsl:if>\n</xsl:template>\n\n<xsl:template match=\"sbsgroup\" mode=\"post-sbsgroup\">\n    <xsl:if test=\".//pf:annotations\">\n        <xsl:call-template name=\"diagacess-instructions\"/>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- ############# -->\n<!-- Audio & Video -->\n<!-- ############# -->\n\n<!-- Audio and video are similar enough that we share    -->\n<!-- some routines under the general heading of \"media\", -->\n<!-- or else we present them here alongside, due to the  -->\n<!-- similarities.                                       -->\n\n<xsl:template match=\"video\">\n    <!-- This is an RTF of the object, it is important that it returns -->\n    <!-- 100% width as default, so when the object is in an enclosing  -->\n    <!-- \"sidebyside\" only the @aspect is on the object and hence a    -->\n    <!-- $layout/height is computed properly.                          -->\n    <xsl:variable name=\"rtf-layout\">\n        <xsl:apply-templates select=\".\" mode=\"layout-parameters\">\n            <xsl:with-param name=\"default-aspect\" select=\"'16:9'\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <xsl:variable name=\"layout\" select=\"exsl:node-set($rtf-layout)\" />\n    <!-- div is constraint/positioning for contained video   -->\n    <!-- Use of \"padding-top\" for responsive iframes is from -->\n    <!-- https://davidwalsh.name/responsive-iframes          -->\n    <div class=\"video-box\">\n        <xsl:attribute name=\"style\">\n            <xsl:text>width: </xsl:text>\n            <xsl:value-of select=\"$layout/width\"/>\n            <xsl:text>%;</xsl:text>\n            <!-- surrogate for height, except on Runestone -->\n            <xsl:if test=\"not($b-host-runestone and @youtube)\">\n                <xsl:text>padding-top: </xsl:text>\n                <xsl:value-of select=\"$layout/height\"/>\n                <xsl:text>%;</xsl:text>\n            </xsl:if>\n            <xsl:text> margin-left: </xsl:text>\n            <xsl:value-of select=\"$layout/left-margin\"/>\n            <xsl:text>%;</xsl:text>\n            <xsl:text> margin-right: </xsl:text>\n            <xsl:value-of select=\"$layout/right-margin\"/>\n            <xsl:text>%;</xsl:text>\n        </xsl:attribute>\n        <xsl:choose>\n            <xsl:when test=\"$b-host-runestone and @youtube\">\n                <!-- we compute pixels in the parameter value, which become   -->\n                <!-- YT-specific attributes, so we can't use general template -->\n                <!-- providing standard attributes                            -->\n                <xsl:apply-templates select=\".\" mode=\"runestone-youtube-embed\">\n                    <xsl:with-param name=\"width\" select=\"($layout/width * $design-width) div 100\"/>\n                    <xsl:with-param name=\"height\" select=\"($layout/height * $design-width) div 100\"/>\n                </xsl:apply-templates>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:apply-templates select=\".\" mode=\"media-embed\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </div>\n    <!-- Always build a standalone page, PDF links to these -->\n    <!-- The only exception is when building portable html  -->\n    <xsl:if test=\"not($b-portable-html)\">\n        <xsl:apply-templates select=\".\" mode=\"media-standalone-page\" />\n    </xsl:if>\n</xsl:template>\n\n<xsl:template match=\"audio\">\n    <!-- This is an RTF of the object, it is important that it returns -->\n    <!-- 100% width as default, so when the object is in an enclosing  -->\n    <!-- \"sidebyside\" it fills the panel.                              -->\n    <!-- Note: we may want to support images as posters, so we may  -->\n    <!-- want to support an aspect-ratio, or perhaps the image will -->\n    <!-- define the size?                                           -->\n    <xsl:variable name=\"rtf-layout\">\n        <xsl:apply-templates select=\".\" mode=\"layout-parameters\"/>\n    </xsl:variable>\n    <xsl:variable name=\"layout\" select=\"exsl:node-set($rtf-layout)\" />\n    <!-- div is constraint/positioning for contained audio -->\n    <div class=\"audio-box\">\n        <xsl:attribute name=\"style\">\n            <xsl:text>width: </xsl:text>\n            <xsl:value-of select=\"$layout/width\"/>\n            <xsl:text>%;</xsl:text>\n            <xsl:text> margin-left: </xsl:text>\n            <xsl:value-of select=\"$layout/left-margin\"/>\n            <xsl:text>%;</xsl:text>\n            <xsl:text> margin-right: </xsl:text>\n            <xsl:value-of select=\"$layout/right-margin\"/>\n            <xsl:text>%;</xsl:text>\n        </xsl:attribute>\n        <xsl:apply-templates select=\".\" mode=\"media-embed\"/>\n    </div>\n    <!-- Always build a standalone page, PDF links to these -->\n    <!-- (except when building portable html)               -->\n    <xsl:if test=\"not($b-portable-html)\">\n        <xsl:apply-templates select=\".\" mode=\"media-standalone-page\" />\n    </xsl:if>\n</xsl:template>\n\n<!-- Formerly a \"pop-out\" page, now a \"standalone\" page     -->\n<!-- Has autoplay on since a reader has elected to go there -->\n<!-- TODO: override preview, since it just plays, pass 'default -->\n<xsl:template match=\"audio|video\" mode=\"media-standalone-page\">\n    <xsl:apply-templates select=\".\" mode=\"standalone-page\">\n        <xsl:with-param name=\"content\">\n            <!-- display preview, and enable autoplay  -->\n            <!-- since reader has elected this page    -->\n            <div style=\"text-align: center;\">Reloading this page will reset a start location</div>\n            <div>\n                <xsl:attribute name=\"class\">\n                    <xsl:choose>\n                        <xsl:when test=\"self::audio\">\n                            <xsl:text>audio-box</xsl:text>\n                        </xsl:when>\n                        <xsl:when test=\"self::video\">\n                            <xsl:text>video-box</xsl:text>\n                        </xsl:when>\n                    </xsl:choose>\n                </xsl:attribute>\n                <xsl:attribute name=\"style\">\n                    <xsl:text>width: </xsl:text>\n                    <xsl:text>100%;</xsl:text>\n                    <xsl:if test=\"self::video\">\n                        <xsl:variable name=\"rtf-layout\">\n                            <xsl:apply-templates select=\".\" mode=\"layout-parameters\">\n                                <xsl:with-param name=\"default-aspect\" select=\"'16:9'\"/>\n                            </xsl:apply-templates>\n                        </xsl:variable>\n                        <xsl:variable name=\"layout\" select=\"exsl:node-set($rtf-layout)\" />\n                        <!-- get back the aspect ratio via height and width of layout, -->\n                        <!-- which are both defined for a video (but not an audio)     -->\n                        <!-- Pairs with 100% width above                               -->\n                        <xsl:variable name=\"height-percent\" select=\"100 * ($layout/height div $layout/width)\"/>\n                        <xsl:text>padding-top: </xsl:text>\n                        <xsl:value-of select=\"$height-percent\"/>\n                        <xsl:text>%;</xsl:text>\n                    </xsl:if>\n                </xsl:attribute>\n                <xsl:apply-templates select=\".\" mode=\"media-embed\">\n                    <xsl:with-param name=\"preview\" select=\"'false'\" />\n                    <xsl:with-param name=\"autoplay\" select=\"'true'\" />\n                </xsl:apply-templates>\n            </div>\n        </xsl:with-param>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- A \"Standalone\" Page -->\n<!-- Formerly a \"pop-out\" page, now a \"standalone\" page    -->\n<!-- (A bit rough - this could be improved, consolidated)  -->\n<!-- no extra libraries, no sidebar                        -->\n<!-- 840px available (~900 - 2*30)                         -->\n<!-- Page's  filename comes from modal template on context -->\n<!-- TODO:  one page template, super-parameterized      -->\n<!-- TODO:  trash navigation further in masthead        -->\n<!-- TODO:  replace libraries by hooks to add some back -->\n<xsl:template match=\"*\" mode=\"standalone-page\">\n    <xsl:param name=\"content\" select=\"''\" />\n    <xsl:variable name=\"filename\">\n        <xsl:apply-templates select=\".\" mode=\"standalone-filename\" />\n    </xsl:variable>\n    <exsl:document href=\"{$filename}\" method=\"html\" indent=\"yes\" encoding=\"UTF-8\" doctype-system=\"about:legacy-compat\">\n        <xsl:call-template name=\"converter-blurb-html-no-date\"/>\n        <html>\n            <xsl:call-template name=\"language-attributes\"/>\n            <xsl:call-template name=\"pretext-advertisement-and-style\"/>\n            <!-- Open Graph Protocol only in \"meta\" elements, within \"head\" -->\n            <head xmlns:og=\"http://ogp.me/ns#\" xmlns:book=\"https://ogp.me/ns/book#\">\n                <title>\n                    <!-- Leading with initials is useful for small tabs -->\n                    <xsl:if test=\"$docinfo/initialism\">\n                        <xsl:apply-templates select=\"$docinfo/initialism\" />\n                        <xsl:text> </xsl:text>\n                    </xsl:if>\n                    <xsl:apply-templates select=\".\" mode=\"title-plain\" />\n                </title>\n                <!-- canonical link for better SEO -->\n                <xsl:call-template name=\"canonical-link\">\n                    <xsl:with-param name=\"filename\" select=\"$filename\"/>\n                </xsl:call-template>\n                <!-- grab the contents every page gets -->\n                <xsl:copy-of select=\"$file-wrap-basic-head-cache\"/>\n                <!-- now do anything that is or could be page-specific and comes after cache -->\n                <xsl:apply-templates select=\".\" mode=\"knowl\" />\n            </head>\n            <body>\n                <!-- potential document-id per-page -->\n                <xsl:call-template name=\"document-id\"/>\n                <!-- React flag -->\n                <xsl:call-template name=\"react-in-use-flag\"/>\n                <!-- the first class controls the default icon -->\n                <xsl:attribute name=\"class\">\n                    <xsl:choose>\n                        <xsl:when test=\"$root/book\">pretext book</xsl:when>\n                        <xsl:when test=\"$root/article\">pretext article</xsl:when>\n                    </xsl:choose>\n                    <!-- ignore MathJax signals everywhere, then enable selectively -->\n                    <xsl:text> ignore-math</xsl:text>\n                    <xsl:text> standalone-page</xsl:text>\n                </xsl:attribute>\n                <!-- assistive \"Skip to main content\" link    -->\n                <!-- this *must* be first for maximum utility -->\n                <xsl:call-template name=\"skip-to-content-link\" />\n                <xsl:apply-templates select=\".\" mode=\"latex-macros\" />\n                <header id=\"ptx-masthead\" class=\"ptx-masthead\" role=\"banner\">\n                    <div class=\"ptx-banner\">\n                        <xsl:call-template name=\"brand-logo\" />\n                        <div class=\"title-container\">\n                            <div class=\"heading ptx-banner-heading\">\n                                <xsl:variable name=\"root-filename\">\n                                    <xsl:apply-templates select=\"$document-root\" mode=\"containing-filename\" />\n                                </xsl:variable>\n                                <a href=\"{$root-filename}\">\n                                    <xsl:variable name=\"b-has-subtitle\" select=\"boolean($document-root/subtitle)\"/>\n                                    <span class=\"title\">\n                                        <!-- Do not use shorttitle in masthead,  -->\n                                        <!-- which is much like cover of a book  -->\n                                        <xsl:apply-templates select=\"$document-root\" mode=\"title-simple\" />\n                                    </span>\n                                    <xsl:if test=\"$b-has-subtitle and $b-html-banner-subtitle\">\n                                        <xsl:text> </xsl:text>\n                                        <span class=\"subtitle\">\n                                            <xsl:apply-templates select=\"$document-root\" mode=\"subtitle\" />\n                                        </span>\n                                    </xsl:if>\n                                </a>\n                            </div>\n                            <!-- Serial list of authors/editors -->\n                            <xsl:if test=\"$b-html-banner-byline\">\n                                <p class=\"byline\">\n                                    <xsl:apply-templates select=\"$bibinfo/author\" mode=\"name-list\"/>\n                                    <xsl:apply-templates select=\"$bibinfo/editor\" mode=\"name-list\"/>\n                                </p>\n                            </xsl:if>\n                        </div>  <!-- title-container -->\n                    </div> <!-- banner -->\n                </header> <!-- masthead -->\n                <div class=\"ptx-page\">\n                    <!-- With sidebars killed, this stuff is extraneous     -->\n                    <!-- <xsl:apply-templates select=\".\" mode=\"sidebars\" /> -->\n                    <main class=\"ptx-main\">\n                        <div id=\"ptx-content\">\n                            <!-- This is content passed in as a parameter -->\n                            <xsl:copy-of select=\"$content\" />\n                        </div>\n                    </main>\n                </div>\n                <xsl:copy-of select=\"$file-wrap-basic-endbody-cache\"/>\n            </body>\n        </html>\n    </exsl:document>\n</xsl:template>\n\n<xsl:template name=\"generic-preview-svg\">\n    <!-- viewbox was square (0,0), 96x96, now clipped 14 above and below                   -->\n    <!-- preserveAspectRatio=\"none\" makes it amenable to matching video it hides           -->\n    <!-- SVG scaling, comprehensive: https://css-tricks.com/scale-svg/                     -->\n    <!-- Accessed: 2017-08-08                                                              -->\n    <!-- Page: https://commons.wikimedia.org/wiki/File:YouTube_Play_Button.svg             -->\n    <!-- File: https://upload.wikimedia.org/wikipedia/commons/d/d1/YouTube_Play_Button.svg -->\n    <!-- License text:  This image only consists of simple geometric shapes or text.       -->\n    <!-- It does not meet the threshold of originality needed for copyright protection,    -->\n    <!-- and is therefore in the public domain.                                            -->\n    <!-- See  xsl/support/play-button/README.md  for a description of the static version   -->\n    <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 14 96 68\" style=\"cursor:pointer; position: absolute; top: 0; left: 0; width: 100%; height: 100%;\" preserveAspectRatio=\"none\">\n        <path fill=\"#e62117\" d=\"M94.98,28.84c0,0-0.94-6.6-3.81-9.5c-3.64-3.81-7.72-3.83-9.59-4.05c-13.4-0.97-33.52-0.85-33.52-0.85s-20.12-0.12-33.52,0.85c-1.87,0.22-5.95,0.24-9.59,4.05c-2.87,2.9-3.81,9.5-3.81,9.5S0.18,36.58,0,44.33v7.26c0.18,7.75,1.14,15.49,1.14,15.49s0.93,6.6,3.81,9.5c3.64,3.81,8.43,3.69,10.56,4.09c7.53,0.72,31.7,0.89,32.54,0.9c0.01,0,20.14,0.03,33.54-0.94c1.87-0.22,5.95-0.24,9.59-4.05c2.87-2.9,3.81-9.5,3.81-9.5s0.96-7.75,1.02-15.49v-7.26C95.94,36.58,94.98,28.84,94.98,28.84z M38.28,61.41v-27l25.74,13.5L38.28,61.41z\"/>\n    </svg>\n</xsl:template>\n\n<!-- Take <svg> element above, remove width and height attributes  -->\n<!-- (not ever needed???), compact to one long string.             -->\n<!-- URL encode via: https://meyerweb.com/eric/tools/dencoder/     -->\n<!-- Then add a bit of voodoo, and this may be used as the value   -->\n<!-- of the HTML5 video/@poster attribute (and other places?)      -->\n<xsl:variable name=\"generic-preview-svg-data-uri\">\n    <xsl:text>data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%2014%2096%2068%22%20style%3D%22cursor%3Apointer%3B%22%20preserveAspectRatio%3D%22none%22%3E%3Cpath%20fill%3D%22%23e62117%22%20d%3D%22M94.98%2C28.84c0%2C0-0.94-6.6-3.81-9.5c-3.64-3.81-7.72-3.83-9.59-4.05c-13.4-0.97-33.52-0.85-33.52-0.85s-20.12-0.12-33.52%2C0.85c-1.87%2C0.22-5.95%2C0.24-9.59%2C4.05c-2.87%2C2.9-3.81%2C9.5-3.81%2C9.5S0.18%2C36.58%2C0%2C44.33v7.26c0.18%2C7.75%2C1.14%2C15.49%2C1.14%2C15.49s0.93%2C6.6%2C3.81%2C9.5c3.64%2C3.81%2C8.43%2C3.69%2C10.56%2C4.09c7.53%2C0.72%2C31.7%2C0.89%2C32.54%2C0.9c0.01%2C0%2C20.14%2C0.03%2C33.54-0.94c1.87-0.22%2C5.95-0.24%2C9.59-4.05c2.87-2.9%2C3.81-9.5%2C3.81-9.5s0.96-7.75%2C1.02-15.49v-7.26C95.94%2C36.58%2C94.98%2C28.84%2C94.98%2C28.84z%20M38.28%2C61.41v-27l25.74%2C13.5L38.28%2C61.41z%22%2F%3E%3C%2Fsvg%3E</xsl:text>\n</xsl:variable>\n\n<!-- LaTeX watermark uses default 5cm font which is then scaled by watermark.scale -->\n<!-- We copy that here. We also copy the 45 degree angle.                          -->\n<!-- Color rgb(204,204,204) matches LaTeX 80% grayscale.                           -->\n<xsl:variable name=\"watermark-svg\">\n    <svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" height=\"600\" width=\"600\">\n        <text x=\"50%\" y=\"50%\" text-anchor=\"middle\" transform=\"rotate(-45,300,300)\" fill=\"rgb(204,204,204)\" style=\"font-family:sans-serif; font-size:{5*$watermark-scale}cm;\">\n            <xsl:value-of select=\"$watermark-text\"/>\n        </text>\n    </svg>\n</xsl:variable>\n\n<xsl:variable name=\"watermark-css\">\n    <xsl:text>background-image:url('data:image/svg+xml;charset=utf-8,</xsl:text>\n    <xsl:apply-templates select=\"exsl:node-set($watermark-svg)\" mode=\"xml-to-string\">\n        <!-- as-authored-source to preserve namespace on svg -->\n        <xsl:with-param name=\"as-authored-source\" select=\"true()\"/>\n    </xsl:apply-templates>\n    <xsl:text>');</xsl:text>\n    <xsl:text>background-position:center top;background-repeat:repeat-y;</xsl:text>\n</xsl:variable>\n\n<!-- NB: here, and elesewhere, references -->\n<!-- to \"video\" should become \"media\"     -->\n<xsl:template match=\"audio[@source|@href]\" mode=\"media-embed\">\n    <xsl:param name=\"preview\" select=\"'false'\" />\n    <xsl:param name=\"autoplay\" select=\"'false'\" />\n\n    <xsl:variable name=\"location\">\n        <xsl:choose>\n            <xsl:when test=\"@href\">\n                <xsl:value-of select=\"@href\"/>\n            </xsl:when>\n            <!-- Now, must have a @source. For backwards -->\n            <!-- compatibility, consider a @source that  -->\n            <!-- really appears to be a @href. Might be  -->\n            <!-- http or https.                          -->\n            <xsl:when test=\"substring(@source,1,4) = 'http'\">\n                <xsl:value-of select=\"@source\"/>\n            </xsl:when>\n            <!-- else a local filename in @source -->\n            <xsl:otherwise>\n                <!-- empty when not using managed directories -->\n                <xsl:value-of select=\"$external-directory\"/>\n                <xsl:value-of select=\"@source\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n\n    <xsl:element name=\"audio\">\n        <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n        <xsl:attribute name=\"class\">\n            <xsl:text>audio</xsl:text>\n        </xsl:attribute>\n        <!-- empty forms work as boolean switches -->\n        <xsl:attribute name=\"controls\"/>\n        <xsl:if test=\"$autoplay = 'true'\">\n            <xsl:attribute name=\"autoplay\" />\n        </xsl:if>\n        <!-- @poster, or equivalent does not seem trivial -->\n        <!-- Construct the HTML5 source URL(s)                  -->\n        <!-- If this gets refactored, it could be best to form  -->\n        <!-- base, extension, query, fragment strings/variables -->\n        <!-- First, grab extension of source URL in PTX @source -->\n        <xsl:variable name=\"extension\">\n            <xsl:call-template name=\"file-extension\">\n                <xsl:with-param name=\"filename\" select=\"$location\" />\n            </xsl:call-template>\n        </xsl:variable>\n        <!-- \"source\" elements, children of HTML5 audio -->\n        <!-- no extension suggests hosting has multiple -->\n        <!-- versions for browser to sort through       -->\n        <!-- More open formats first!  ;-)              -->\n        <xsl:if test=\"$extension = '' or $extension = 'ogg'\">\n            <xsl:element name=\"source\">\n                <xsl:attribute name=\"src\">\n                    <xsl:value-of select=\"$location\"/>\n                    <!-- augment no-extension form -->\n                    <xsl:if test=\"$extension = ''\">\n                        <xsl:text>.ogg</xsl:text>\n                    </xsl:if>\n                    <xsl:apply-templates select=\".\" mode=\"temporal-fragment\"/>\n                </xsl:attribute>\n                <xsl:attribute name=\"type\">\n                    <xsl:text>audio/ogg</xsl:text>\n                </xsl:attribute>\n            </xsl:element>\n        </xsl:if>\n        <xsl:if test=\"$extension = '' or $extension = 'mp3'\">\n            <xsl:element name=\"source\">\n                <xsl:attribute name=\"src\">\n                    <xsl:value-of select=\"$location\"/>\n                    <!-- augment no-extension form -->\n                    <xsl:if test=\"$extension = ''\">\n                        <xsl:text>.mp3</xsl:text>\n                    </xsl:if>\n                    <xsl:apply-templates select=\".\" mode=\"temporal-fragment\"/>\n                </xsl:attribute>\n                <xsl:attribute name=\"type\">\n                    <xsl:text>audio/mp3</xsl:text>\n                </xsl:attribute>\n            </xsl:element>\n        </xsl:if>\n        <xsl:if test=\"$extension = '' or $extension = 'wav'\">\n            <xsl:element name=\"source\">\n                <xsl:attribute name=\"src\">\n                    <xsl:value-of select=\"$location\"/>\n                    <!-- augment no-extension form -->\n                    <xsl:if test=\"$extension = ''\">\n                        <xsl:text>.wav</xsl:text>\n                    </xsl:if>\n                    <xsl:apply-templates select=\".\" mode=\"temporal-fragment\"/>\n                </xsl:attribute>\n                <xsl:attribute name=\"type\">\n                    <xsl:text>audio/wav</xsl:text>\n                </xsl:attribute>\n            </xsl:element>\n        </xsl:if>\n        <!-- failure to perform -->\n        <xsl:text>Your browser does not support the &lt;audio&gt; tag.</xsl:text>\n    </xsl:element>\n</xsl:template>\n\n<!-- create a \"video\" element for author-hosted   -->\n<!-- dimensions and autoplay as parameters        -->\n<!-- Normally $preview is true, and not passed in -->\n<!-- 'false' is an override for standalone pages  -->\n<xsl:template match=\"video[@source|@href]\" mode=\"media-embed\">\n    <xsl:param name=\"preview\" select=\"'true'\" />\n    <xsl:param name=\"autoplay\" select=\"'false'\" />\n\n    <xsl:variable name=\"location\">\n        <xsl:choose>\n            <xsl:when test=\"@href\">\n                <xsl:value-of select=\"@href\"/>\n            </xsl:when>\n            <!-- Now, must have a @source. For backwards -->\n            <!-- compatibility, consider a @source that  -->\n            <!-- really appears to be a @href. Might be  -->\n            <!-- http or https.                          -->\n            <xsl:when test=\"substring(@source,1,4) = 'http'\">\n                <xsl:value-of select=\"@source\"/>\n            </xsl:when>\n            <!-- else a local filename in @source -->\n            <xsl:otherwise>\n                <!-- empty when not using managed directories -->\n                <xsl:value-of select=\"$external-directory\"/>\n                <xsl:value-of select=\"@source\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n\n\n    <!-- we need to build the element, since @autoplay is optional -->\n    <xsl:element name=\"video\">\n        <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n        <xsl:attribute name=\"class\">\n            <xsl:text>video</xsl:text>\n        </xsl:attribute>\n        <!-- empty forms work as boolean switches -->\n        <xsl:attribute name=\"controls\" />\n        <xsl:if test=\"$autoplay = 'true'\">\n            <xsl:attribute name=\"autoplay\" />\n        </xsl:if>\n        <!-- Optionally cover up with HTML5 @poster via PTX @preview -->\n        <xsl:if test=\"($preview = 'true') and @preview and not(@preview = 'default')\">\n            <xsl:attribute name=\"poster\">\n                <xsl:choose>\n                    <xsl:when test=\"@preview = 'generic'\">\n                        <xsl:value-of select=\"$generic-preview-svg-data-uri\" />\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <!-- empty when not using managed directories -->\n                        <xsl:value-of select=\"$external-directory\"/>\n                        <xsl:value-of select=\"@preview\" />\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:attribute>\n        </xsl:if>\n        <!-- Construct the HTML5 source URL(s)                  -->\n        <!-- If this gets refactored, it could be best to form  -->\n        <!-- base, extension, query, fragment strings/variables -->\n        <!-- First, grab extension of source URL in PTX @source -->\n        <xsl:variable name=\"extension\">\n            <xsl:call-template name=\"file-extension\">\n                <xsl:with-param name=\"filename\" select=\"$location\" />\n            </xsl:call-template>\n        </xsl:variable>\n        <!-- \"source\" elements, children of HTML5 video -->\n        <!-- no extension suggests hosting has multiple -->\n        <!-- versions for browser to sort through       -->\n        <!-- More open formats first!  ;-)              -->\n        <xsl:if test=\"$extension = '' or $extension = 'ogv'\">\n            <xsl:element name=\"source\">\n                <xsl:attribute name=\"src\">\n                    <xsl:value-of select=\"$location\"/>\n                    <!-- augment no-extension form -->\n                    <xsl:if test=\"$extension = ''\">\n                        <xsl:text>.ogv</xsl:text>\n                    </xsl:if>\n                    <xsl:apply-templates select=\".\" mode=\"temporal-fragment\"/>\n                </xsl:attribute>\n                <xsl:attribute name=\"type\">\n                    <xsl:text>video/ogg</xsl:text>\n                </xsl:attribute>\n            </xsl:element>\n        </xsl:if>\n        <xsl:if test=\"$extension = '' or $extension = 'webm'\">\n            <xsl:element name=\"source\">\n                <xsl:attribute name=\"src\">\n                    <xsl:value-of select=\"$location\"/>\n                    <!-- augment no-extension form -->\n                    <xsl:if test=\"$extension = ''\">\n                        <xsl:text>.webm</xsl:text>\n                    </xsl:if>\n                    <xsl:apply-templates select=\".\" mode=\"temporal-fragment\"/>\n                </xsl:attribute>\n                <xsl:attribute name=\"type\">\n                    <xsl:text>video/webm</xsl:text>\n                </xsl:attribute>\n            </xsl:element>\n        </xsl:if>\n        <xsl:if test=\"$extension = '' or $extension = 'mp4'\">\n            <xsl:element name=\"source\">\n                <xsl:attribute name=\"src\">\n                    <xsl:value-of select=\"$location\"/>\n                    <!-- augment no-extension form -->\n                    <xsl:if test=\"$extension = ''\">\n                        <xsl:text>.mp4</xsl:text>\n                    </xsl:if>\n                    <xsl:apply-templates select=\".\" mode=\"temporal-fragment\"/>\n                </xsl:attribute>\n                <xsl:attribute name=\"type\">\n                    <xsl:text>video/mp4</xsl:text>\n                </xsl:attribute>\n            </xsl:element>\n        </xsl:if>\n        <!-- 2007: *.oog officially replaced by *.ogv    -->\n        <!-- 2018-04-01: we supported *.oog for video at -->\n        <!--    91028991e081d2c933d46d3ce5d4d1cb6759c0bf -->\n        <!-- 2020-07-05: demoted, but continue support   -->\n        <xsl:if test=\"$extension = '' or $extension = 'oog'\">\n            <xsl:element name=\"source\">\n                <xsl:attribute name=\"src\">\n                    <xsl:value-of select=\"$location\"/>\n                    <!-- augment no-extension form -->\n                    <xsl:if test=\"$extension = ''\">\n                        <xsl:text>.ogg</xsl:text>\n                    </xsl:if>\n                    <xsl:apply-templates select=\".\" mode=\"temporal-fragment\"/>\n                </xsl:attribute>\n                <xsl:attribute name=\"type\">\n                    <xsl:text>video/ogg</xsl:text>\n                </xsl:attribute>\n            </xsl:element>\n        </xsl:if>\n        <!-- failure to perform -->\n        <xsl:text>Your browser does not support the &lt;video&gt; tag.</xsl:text>\n        <xsl:apply-templates select=\"track\"/>\n    </xsl:element>\n</xsl:template>\n\n\n<!-- This an optional component of an author-hosted video, -->\n<!-- and the markup closely tracks the generated HTML.     -->\n<!-- The exception being our @listing; @label is taken.    -->\n<!-- The HTML @default attribute functions simply by being -->\n<!-- present, so we do not provide a value.                -->\n<xsl:template match=\"track\">\n    <xsl:variable name=\"location\">\n        <!-- empty when not using managed directories -->\n        <xsl:value-of select=\"$external-directory\"/>\n        <xsl:value-of select=\"@source\"/>\n    </xsl:variable>\n\n    <track>\n        <xsl:if test=\"@default='yes'\">\n            <xsl:attribute name=\"default\"/>\n        </xsl:if>\n        <xsl:attribute name=\"label\">\n            <xsl:value-of select=\"@listing\"/>\n        </xsl:attribute>\n        <xsl:attribute name=\"kind\">\n            <xsl:value-of select=\"@kind\"/>\n        </xsl:attribute>\n        <xsl:attribute name=\"srclang\">\n            <xsl:value-of select=\"@xml:lang\"/>\n        </xsl:attribute>\n        <xsl:attribute name=\"src\">\n            <xsl:value-of select=\"$location\"/>\n        </xsl:attribute>\n    </track>\n</xsl:template>\n\n<!-- HTML5 Media Fragment URI (shared for audio, video)       -->\n<!-- start/end times (read both, see 4.1, 4.2.1 at w3.org)    -->\n<!-- Media Fragment URI: https://www.w3.org/TR/media-frags/   -->\n<!-- Javascript: https://stackoverflow.com/questions/11212715 -->\n<!-- return is possibly empty, so no harm using that later    -->\n<!-- This portion of URL should follow any query string       -->\n<xsl:template match=\"audio|video\" mode=\"temporal-fragment\">\n    <xsl:if test=\"@start or @end\">\n        <xsl:text>#t=</xsl:text>\n    </xsl:if>\n    <xsl:if test=\"@start\">\n        <xsl:value-of select=\"@start\" />\n    </xsl:if>\n    <!-- can lead with comma, implies 0,xx -->\n    <xsl:if test=\"@end\">\n        <xsl:text>,</xsl:text>\n        <xsl:value-of select=\"@end\" />\n    </xsl:if>\n</xsl:template>\n\n<!-- You Tube, Vimeo -->\n<!-- Better sizing would require CSS classes (16:9, 4:3?)                      -->\n<!-- https://css-tricks.com/NetMag/FluidWidthVideo/Article-FluidWidthVideo.php -->\n\n<!-- Configurable options, we are considering academic uses                       -->\n<!-- https://developers.google.com/youtube/player_parameters#Manual_IFrame_Embeds -->\n<!-- hl parameter for language seems superfluous, user settings override          -->\n<!-- something to do with cross-domain scripting security?                        -->\n<!-- <xsl:text>&amp;origin=http://example.com</xsl:text>                          -->\n<!-- start/end time parameters                                                    -->\n\n<!-- create iframe embedded video                     -->\n<!-- dimensions and autoplay as parameters            -->\n<!-- Normally $preview is true, and not passed in     -->\n<!-- 'false' is an override for standalone pages      -->\n<!-- Templates, on a per-service basis, supply a URL, -->\n<!-- and any attributes on the \"iframe\" element which -->\n<!-- are not shared                                   -->\n<xsl:template match=\"video[@youtube|@youtubeplaylist|@vimeo]\" mode=\"media-embed\">\n    <xsl:param name=\"preview\" select=\"'true'\" />\n    <xsl:param name=\"autoplay\" select=\"'false'\" />\n\n    <xsl:variable name=\"source-url\">\n        <xsl:apply-templates select=\".\" mode=\"video-embed-url\">\n            <xsl:with-param name=\"autoplay\" select=\"$autoplay\" />\n        </xsl:apply-templates>\n    </xsl:variable>\n    <xsl:variable name=\"source-url-autoplay-on\">\n        <xsl:apply-templates select=\".\" mode=\"video-embed-url\">\n            <xsl:with-param name=\"autoplay\">\n                <xsl:choose>\n                    <!-- the YouTube autoplay won't wait for the poster -->\n                    <!-- to be withdrawn, so two clicks are needed,     -->\n                    <!-- perhaps this is true of *all* services?        -->\n                    <xsl:when test=\"@youtube|@youtubeplaylist\">\n                        <xsl:text>false</xsl:text>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:text>true</xsl:text>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:with-param>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <!-- allowfullscreen is an iframe parameter,   -->\n    <!-- not a video-embedding parameter, but it's -->\n    <!-- use enables the \"full screen\" button      -->\n    <!-- http://w3c.github.io/test-results/html51/implementation-report.html -->\n    <xsl:choose>\n        <xsl:when test=\"($preview = 'true') and @preview and not(@preview = 'default')\">\n            <!-- hide behind a preview image, code from post at -->\n            <!-- https://stackoverflow.com/questions/7199624    -->\n            <div onclick=\"this.nextElementSibling.style.display='block'; this.style.display='none'\">\n                <xsl:choose>\n                    <xsl:when test=\"@preview = 'generic'\">\n                        <xsl:call-template name=\"generic-preview-svg\"/>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <img class=\"video-poster\" alt=\"Video cover image\">\n                            <xsl:attribute name=\"src\">\n                                <!-- empty when not using managed directories -->\n                                <xsl:value-of select=\"$external-directory\"/>\n                                <xsl:value-of select=\"@preview\"/>\n                            </xsl:attribute>\n                        </img>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </div>\n            <div class=\"hidden-content\">\n                <!-- Hidden content in here                   -->\n                <!-- Turn autoplay on, else two clicks needed -->\n                <iframe class=\"video\" allowfullscreen=\"\" src=\"{$source-url-autoplay-on}\">\n                    <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n                    <xsl:apply-templates select=\".\" mode=\"video-iframe-attributes\">\n                        <xsl:with-param name=\"autoplay\" select=\"'true'\"/>\n                    </xsl:apply-templates>\n                </iframe>\n            </div>\n        </xsl:when>\n        <xsl:otherwise>\n            <iframe class=\"video\" allowfullscreen=\"\" src=\"{$source-url}\">\n                <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n                <xsl:apply-templates select=\".\" mode=\"video-iframe-attributes\">\n                    <xsl:with-param name=\"autoplay\" select=\"$autoplay\"/>\n                </xsl:apply-templates>\n            </iframe>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Creates a YouTube URL for embedding for use in an iframe -->\n<!-- Autoplay option is conveyed in the URL query options     -->\n<!-- Autoplay is for popout, otherwise not                    -->\n<xsl:template match=\"video[@youtube|@youtubeplaylist]\" mode=\"video-embed-url\">\n    <xsl:param name=\"autoplay\" select=\"'false'\" />\n    <xsl:variable name=\"youtube\">\n        <xsl:choose>\n            <!-- forgive an author's leading or trailing space -->\n            <xsl:when test=\"@youtubeplaylist\">\n                <xsl:value-of select=\"normalize-space(@youtubeplaylist)\" />\n            </xsl:when>\n            <!-- replace commas with spaces then normalize space    -->\n            <!-- result is a trim space-separated list of video IDs -->\n            <xsl:otherwise>\n                <xsl:value-of select=\"normalize-space(str:replace(@youtube, ',', ' '))\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$b-video-privacy\">\n            <xsl:text>https://www.youtube-nocookie.com/embed</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>https://www.youtube.com/embed</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n    <xsl:choose>\n        <!-- playlist with a YouTube ID -->\n        <xsl:when test=\"@youtubeplaylist\">\n            <xsl:text>?listType=playlist&amp;list=</xsl:text>\n            <xsl:value-of select=\"$youtube\" />\n        </xsl:when>\n        <!-- if we get this far there must be a @youtube -->\n        <!-- and $youtube is one or more video IDs       -->\n        <xsl:when test=\"contains($youtube, ' ')\">\n            <xsl:text>?playlist=</xsl:text>\n            <xsl:value-of select=\"str:replace($youtube, ' ', ',')\" />\n        </xsl:when>\n        <!-- a single video ID -->\n        <xsl:otherwise>\n            <xsl:text>/</xsl:text>\n            <xsl:value-of select=\"$youtube\" />\n            <xsl:text>?</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n    <!-- use &amp; separator for remaining options -->\n    <xsl:text>&amp;modestbranding=1</xsl:text>\n    <!-- kill related videos at end -->\n    <xsl:text>&amp;rel=0</xsl:text>\n    <!-- start and end times; for a playlist these are applied to first video -->\n    <xsl:if test=\"@start\">\n        <xsl:text>&amp;start=</xsl:text>\n        <xsl:value-of select=\"@start\" />\n    </xsl:if>\n    <xsl:if test=\"@end\">\n        <xsl:text>&amp;end=</xsl:text>\n        <xsl:value-of select=\"@end\" />\n    </xsl:if>\n    <!-- default autoplay is 0, don't -->\n    <xsl:if test=\"$autoplay = 'true'\">\n        <xsl:text>&amp;autoplay=1</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<!-- For a YouTube video, no YT-specific options come in the attributes -->\n<xsl:template match=\"video[@youtube|@youtubeplaylist]\" mode=\"video-iframe-attributes\"/>\n\n<!-- Creates a Vimeo URL for embedding, typically in an iframe  -->\n<xsl:template match=\"video[@vimeo]\" mode=\"video-embed-url\">\n    <xsl:param name=\"autoplay\" select=\"'false'\" />\n    <xsl:text>https://player.vimeo.com/video/</xsl:text>\n    <xsl:value-of select=\"@vimeo\"/>\n    <xsl:text>?color=ffffff</xsl:text>\n    <!-- use &amp; separator for remaining options -->\n    <!-- default autoplay is 0, don't -->\n    <xsl:if test=\"$autoplay = 'true'\">\n        <xsl:text>&amp;autoplay=1</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<!-- These are additional attributes on the \"iframe\" which seem specific to Vimeo -->\n<!-- N.B. the autoplay seems ineffective                                          -->\n<xsl:template match=\"video[@vimeo]\" mode=\"video-iframe-attributes\">\n    <xsl:param name=\"autoplay\" select=\"'false'\" />\n\n    <xsl:attribute name=\"frameborder\">\n        <xsl:text>0</xsl:text>\n    </xsl:attribute>\n    <xsl:attribute name=\"allow\">\n        <xsl:if test=\"$autoplay = 'true'\">\n            <xsl:text>autoplay; </xsl:text>\n        </xsl:if>\n        <xsl:text>fullscreen</xsl:text>\n    </xsl:attribute>\n</xsl:template>\n\n<!-- ############ -->\n<!-- Music Scores -->\n<!-- ############ -->\n\n<!-- Embed an interactive score from MuseScore                          -->\n<!-- Flag: score element has two MuseScore-specific attributes          -->\n<!-- https://musescore.org/user/{usernumber}/scores/{scorenumber}/embed -->\n<!-- into an iframe with width and height (todo)                        -->\n<xsl:template match=\"score[@musescoreuser and @musescore]\">\n    <xsl:element name=\"iframe\">\n        <xsl:attribute name=\"width\">\n            <xsl:text>100%</xsl:text>\n        </xsl:attribute>\n        <xsl:attribute name=\"height\">\n            <xsl:text>500</xsl:text>\n        </xsl:attribute>\n        <!-- empty attribute, just switch -->\n        <xsl:attribute name=\"allowfullscreen\">\n            <xsl:text></xsl:text>\n        </xsl:attribute>\n        <xsl:attribute name=\"src\">\n            <xsl:text>https://musescore.com/user/</xsl:text>\n            <xsl:value-of select=\"@musescoreuser\" />\n            <xsl:text>/scores/</xsl:text>\n            <xsl:value-of select=\"@musescore\" />\n            <xsl:text>/embed</xsl:text>\n        </xsl:attribute>\n    </xsl:element>\n</xsl:template>\n\n<!-- ####### -->\n<!-- Tabular -->\n<!-- ####### -->\n\n<!-- Top-down organization -->\n\n<!-- A tabular layout, a naked table -->\n<!-- Allowed to be placed various locations, but gets no              -->\n<!-- vertical space etc, that is the container's responsibiility      -->\n<!-- A sequence of rows, we ignore column group in applying templates -->\n<!-- Realized as an HTML table                                        -->\n\n<xsl:template match=\"tabular[not(ancestor::sidebyside)]\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <!-- naked tabular carries its own width -->\n\n    <xsl:choose>\n        <xsl:when test=\"not(@margins) and (not(@width) or (@width = 'auto'))\">\n            <!-- the \"natural width\" case                       -->\n            <!-- 100% width allows paragraph cells to be widest -->\n            <div class=\"tabular-box natural-width\">\n                <xsl:apply-templates select=\".\" mode=\"tabular-inclusion\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n                    <xsl:with-param name=\"width\" select=\"'100%'\" />\n                </xsl:apply-templates>\n            </div>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:variable name=\"rtf-layout\">\n                <xsl:apply-templates select=\".\" mode=\"layout-parameters\"/>\n            </xsl:variable>\n            <xsl:variable name=\"layout\" select=\"exsl:node-set($rtf-layout)\"/>\n            <div class=\"tabular-box\">\n                <xsl:attribute name=\"style\">\n                    <xsl:text>width: </xsl:text>\n                    <xsl:value-of select=\"$layout/width\"/>\n                    <xsl:text>%;</xsl:text>\n                    <xsl:text> margin-left: </xsl:text>\n                    <xsl:value-of select=\"$layout/left-margin\"/>\n                    <xsl:text>%;</xsl:text>\n                    <xsl:text> margin-right: </xsl:text>\n                    <xsl:value-of select=\"$layout/right-margin\"/>\n                    <xsl:text>%;</xsl:text>\n                </xsl:attribute>\n                <xsl:apply-templates select=\".\" mode=\"tabular-inclusion\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                    <xsl:with-param name=\"width\" select=\"concat($layout/width, '%')\"/>\n                </xsl:apply-templates>\n            </div>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"tabular[ancestor::sidebyside]\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <!-- sidebyside should always provide width, -->\n    <!-- so no default value provided here       -->\n    <xsl:param name=\"width\"/>\n\n    <xsl:apply-templates select=\".\" mode=\"tabular-inclusion\">\n        <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n        <xsl:with-param name=\"width\" select=\"$width\" />\n    </xsl:apply-templates>\n</xsl:template>\n\n<xsl:template match=\"tabular\" mode=\"tabular-inclusion\">\n    <xsl:param name=\"b-original\" select=\"$b-original\"/>\n    <xsl:param name=\"width\"  select=\"$width\"/>\n\n    <!-- Abort if tabular's cols have widths summing to over 100% -->\n    <xsl:call-template name=\"cap-width-at-one-hundred-percent\">\n        <xsl:with-param name=\"nodeset\" select=\"col/@width\" />\n    </xsl:call-template>\n\n    <table class=\"tabular\">\n        <!-- We *actively* enforce header rows being (a) initial, and      -->\n        <!-- (b) contiguous.  So following two-part match will do no harm  -->\n        <!-- to correct source, but will definitely harm incorrect source. -->\n        <xsl:apply-templates select=\"row[@header]\">\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n            <xsl:with-param name=\"ambient-relative-width\" select=\"$width\" />\n        </xsl:apply-templates>\n        <xsl:apply-templates select=\"row[not(@header)]\">\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n            <xsl:with-param name=\"ambient-relative-width\" select=\"$width\" />\n        </xsl:apply-templates>\n    </table>\n    <!-- Table notes (\"tn\") collect just below the table, lettered in -->\n    <!-- reading order, which is document order of the marks (Notes   -->\n    <!-- to tables: CMoS 18th ed., 3.77-3.81; specific notes at       -->\n    <!-- 3.80).  Disjoint from true footnote numbering.               -->\n    <xsl:if test=\".//tn\">\n        <!-- each note is a list item (not a \"p\"): one tight -->\n        <!-- line per note, free of paragraph margins        -->\n        <ol class=\"tablenotes\" aria-label=\"Table notes\">\n            <xsl:for-each select=\".//tn\">\n                <xsl:variable name=\"note-number\">\n                    <xsl:apply-templates select=\".\" mode=\"number\"/>\n                </xsl:variable>\n                <li class=\"tablenote\">\n                    <xsl:attribute name=\"id\">\n                        <xsl:apply-templates select=\".\" mode=\"html-id\"/>\n                        <xsl:text>-note</xsl:text>\n                    </xsl:attribute>\n                    <sup>\n                        <a>\n                            <xsl:attribute name=\"href\">\n                                <xsl:text>#</xsl:text>\n                                <xsl:apply-templates select=\".\" mode=\"html-id\"/>\n                            </xsl:attribute>\n                            <xsl:attribute name=\"aria-label\">\n                                <xsl:text>Back to table note reference </xsl:text>\n                                <xsl:value-of select=\"$note-number\"/>\n                            </xsl:attribute>\n                            <i>\n                                <xsl:value-of select=\"$note-number\"/>\n                            </i>\n                        </a>\n                    </sup>\n                    <xsl:text> </xsl:text>\n                    <xsl:apply-templates/>\n                </li>\n            </xsl:for-each>\n        </ol>\n    </xsl:if>\n</xsl:template>\n\n<!-- A row of table -->\n<xsl:template match=\"row\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"ambient-relative-width\" />\n\n    <!-- Determine if the row is a header row -->\n    <!-- and construct class names as needed  -->\n    <xsl:variable name=\"header-row\">\n        <xsl:choose>\n            <xsl:when test=\"@header = 'yes'\">\n                <xsl:text>header-horizontal</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"@header = 'vertical'\">\n                <xsl:text>header-vertical</xsl:text>\n            </xsl:when>\n            <!-- \"no\" is other choice, or no attribute at all -->\n            <!-- controlled by schema, so no error-check here -->\n            <!-- empty implies no class attribute at all      -->\n            <xsl:otherwise/>\n        </xsl:choose>\n    </xsl:variable>\n\n    <!-- Form the HTML table row -->\n    <!-- newline inserted to encourage formatted output -->\n    <xsl:text>&#xa;</xsl:text>\n    <xsl:element name=\"tr\">\n        <!-- and a class attribute for horizontal or vertical headers -->\n        <xsl:if test=\"not($header-row = '')\">\n            <xsl:attribute name=\"class\">\n                <xsl:value-of select=\"$header-row\"/>\n            </xsl:attribute>\n        </xsl:if>\n        <!-- Walk the cells of the row -->\n        <xsl:apply-templates select=\"cell\" mode=\"row-cell\">\n            <xsl:with-param name=\"b-original\" select=\"$b-original\" />\n            <xsl:with-param name=\"ambient-relative-width\" select=\"$ambient-relative-width\" />\n        </xsl:apply-templates>\n    </xsl:element>\n</xsl:template>\n\n<!-- One cell of a table row.  The cell is the context node, so it resolves -->\n<!-- its own effective alignments and rule weights (see pretext-common.xsl) -->\n<!-- and finds its governing \"col\" by column number, with no cell cursor or -->\n<!-- column pointer threaded in.  Only the two genuinely ambient values     -->\n<!-- pass through: the original-vs-knowl-copy flag and the containing width. -->\n<xsl:template match=\"cell\" mode=\"row-cell\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <xsl:param name=\"ambient-relative-width\" />\n    <!-- A cell may span several columns, or default to just 1.  Its left  -->\n    <!-- end sits in column \"column-left-number\" (resolved in -common,     -->\n    <!-- honoring the colspans of preceding cells), which identifies the   -->\n    <!-- governing \"col\" for left border, alignment, and paragraph width.  -->\n    <!-- That \"col\" may be absent (an empty $left-col).                    -->\n    <xsl:variable name=\"column-span\">\n        <xsl:choose>\n            <xsl:when test=\"@colspan\">\n                <xsl:value-of select=\"@colspan\" />\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>1</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"left-column-number\">\n        <xsl:apply-templates select=\".\" mode=\"column-left-number\"/>\n    </xsl:variable>\n    <xsl:variable name=\"left-col\" select=\"ancestor::tabular/col[number($left-column-number)]\"/>\n\n    <!-- Check if row-headers are requested -->\n    <xsl:variable name=\"b-row-headers\" select=\"boolean(parent::row/parent::tabular[@row-headers = 'yes'])\"/>\n    <!-- And if we are at the first cell -->\n    <xsl:variable name=\"b-row-header\" select=\"$b-row-headers and not(preceding-sibling::cell)\"/>\n\n    <!-- build an HTML data cell, with CSS decorations              -->\n    <!-- we set properties in various variables,                    -->\n    <!-- then write them in a class attribute                       -->\n    <!-- we look outward and upward for characteristics of the cell -->\n    <!--                                                            -->\n    <!-- effective alignments and rule weights, resolved in -common; -->\n    <!-- each is a token translated to a CSS class fragment below     -->\n    <xsl:variable name=\"alignment\">\n        <xsl:apply-templates select=\".\" mode=\"effective-halign\"/>\n    </xsl:variable>\n    <xsl:variable name=\"valignment\">\n        <xsl:apply-templates select=\".\" mode=\"effective-valign\"/>\n    </xsl:variable>\n    <xsl:variable name=\"bottom\">\n        <xsl:apply-templates select=\".\" mode=\"effective-bottom\"/>\n    </xsl:variable>\n    <xsl:variable name=\"right\">\n        <xsl:apply-templates select=\".\" mode=\"effective-right\"/>\n    </xsl:variable>\n    <xsl:variable name=\"left\">\n        <xsl:apply-templates select=\".\" mode=\"effective-left\"/>\n    </xsl:variable>\n    <xsl:variable name=\"top\">\n        <xsl:apply-templates select=\".\" mode=\"effective-top\"/>\n    </xsl:variable>\n\n    <!-- a cell of a header row needs to be \"th\" -->\n    <!-- else the HTML mark up is \"td\"           -->\n    <xsl:variable name=\"header-row-elt\">\n        <xsl:choose>\n            <xsl:when test=\"parent::row/@header = 'yes'\">\n                <xsl:text>th</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"parent::row/@header = 'vertical'\">\n                <xsl:text>th</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"$b-row-header\">\n                <xsl:text>th</xsl:text>\n            </xsl:when>\n            <!-- \"no\" is other choice, or no attribute at all -->\n            <!-- controlled by schema, so no error-check here -->\n            <xsl:otherwise>\n                <xsl:text>td</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n\n    <!-- the HTML element for the cell -->\n    <!-- newline inserted to encourage formatted output -->\n    <xsl:text>&#xa;</xsl:text>\n    <xsl:element name=\"{$header-row-elt}\">\n        <!-- Scope attribute helps with accessibility: what          -->\n        <!-- is the table element/cell describing?                   -->\n        <!-- if this is a row of column headers, declare scope=\"col\" -->\n        <!-- if this is a column of row headers, declare scope=\"row\" -->\n        <xsl:if test=\"$header-row-elt = 'th'\">\n            <xsl:attribute name=\"scope\">\n                <!-- If in upper-left corner, let column headings dominate -->\n                <xsl:choose>\n                    <xsl:when test=\"(parent::row/@header = 'yes') or (parent::row/@header = 'vertical')\">\n                        <xsl:text>col</xsl:text>\n                    </xsl:when>\n                    <xsl:when test=\"$b-row-header\">\n                        <xsl:text>row</xsl:text>\n                    </xsl:when>\n                </xsl:choose>\n            </xsl:attribute>\n        </xsl:if>\n        <!-- and the class attribute -->\n        <xsl:attribute name=\"class\">\n            <!-- always write alignment, so *precede* all subsequent with a space -->\n            <xsl:choose>\n                <xsl:when test=\"p and $alignment='justify'\">\n                    <xsl:text>j</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:call-template name=\"halign-specification\">\n                        <xsl:with-param name=\"align\" select=\"$alignment\" />\n                    </xsl:call-template>\n                </xsl:otherwise>\n            </xsl:choose>\n            <!-- vertical alignment -->\n            <xsl:text> </xsl:text>\n            <xsl:call-template name=\"valign-specification\">\n                <xsl:with-param name=\"align\" select=\"$valignment\" />\n            </xsl:call-template>\n            <!-- bottom border -->\n            <xsl:text> b</xsl:text>\n            <xsl:call-template name=\"thickness-specification\">\n                <xsl:with-param name=\"width\" select=\"$bottom\" />\n            </xsl:call-template>\n            <!-- right border -->\n            <xsl:text> r</xsl:text>\n            <xsl:call-template name=\"thickness-specification\">\n                <xsl:with-param name=\"width\" select=\"$right\" />\n            </xsl:call-template>\n            <!-- left border -->\n            <xsl:text> l</xsl:text>\n            <xsl:call-template name=\"thickness-specification\">\n                <xsl:with-param name=\"width\" select=\"$left\" />\n            </xsl:call-template>\n            <!-- top border -->\n            <xsl:text> t</xsl:text>\n            <xsl:call-template name=\"thickness-specification\">\n                <xsl:with-param name=\"width\" select=\"$top\" />\n            </xsl:call-template>\n            <!-- no wrapping unless paragraph cell -->\n            <xsl:if test=\"not(p)\">\n                <xsl:text> lines</xsl:text>\n            </xsl:if>\n        </xsl:attribute>\n        <xsl:if test=\"not($column-span = 1)\">\n            <xsl:attribute name=\"colspan\">\n                <xsl:value-of select=\"$column-span\" />\n            </xsl:attribute>\n        </xsl:if>\n        <xsl:if test=\"p\">\n            <xsl:attribute name=\"style\">\n                <xsl:text>max-width:</xsl:text>\n                <xsl:choose>\n                    <xsl:when test=\"$left-col/@width\">\n                        <xsl:variable name=\"width\">\n                            <xsl:call-template name=\"normalize-percentage\">\n                                <xsl:with-param name=\"percentage\" select=\"$left-col/@width\" />\n                            </xsl:call-template>\n                        </xsl:variable>\n                        <xsl:value-of select=\"$design-width * substring-before($width, '%') div 100 * substring-before($ambient-relative-width, '%') div 100\" />\n                        <xsl:text>px;</xsl:text>\n                    </xsl:when>\n                    <!-- If there is no $left-col/@width, silently use 20% as default -->\n                    <!-- We get some ill-formed WW exercises here, so a less-precise  -->\n                    <!-- warning is given on the author's source.                     -->\n                    <xsl:otherwise>\n                        <xsl:value-of select=\"$design-width * 0.2 * substring-before($ambient-relative-width, '%') div 100\" />\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:attribute>\n        </xsl:if>\n        <!-- process the actual contents           -->\n        <!-- condition on indicators of structure  -->\n        <!-- All \"line\", all \"p\", or mixed content -->\n        <!-- TODO: is it important to pass $b-original -->\n        <!-- flag into template for \"line\" elements?   -->\n        <xsl:choose>\n            <xsl:when test=\"line\">\n                <xsl:apply-templates select=\"line\"/>\n            </xsl:when>\n            <xsl:when test=\"p\">\n                <xsl:apply-templates select=\"p\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                </xsl:apply-templates>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:apply-templates select=\".\">\n                    <xsl:with-param name=\"b-original\" select=\"$b-original\"/>\n                </xsl:apply-templates>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:element>\n</xsl:template>\n\n<!-- ############################ -->\n<!-- Table construction utilities -->\n<!-- ############################ -->\n\n<!-- Utilities are defined in xsl/pretext-common.xsl -->\n\n<!-- \"thickness-specification\" : param \"width\"    -->\n<!--     none, minor, medium, major -> 0, 1, 2, 3 -->\n\n<!-- \"halign-specification\" : param \"align\"       -->\n<!--     left, right, center -> l, c, r           -->\n\n<!-- \"valign-specification\" : param \"align\"       -->\n<!--     top, middle, bottom -> t, m, b           -->\n\n\n<!-- ################ -->\n<!-- Cross-References -->\n<!-- ################ -->\n\n<!-- Much of the cross-reference mechanism is -->\n<!-- implemented in the common routines,      -->\n<!-- here we implement two abstract templates -->\n<!-- which are called from those routines     -->\n\n<!-- The \"text\" of a cross-reference typically   -->\n<!-- includes a number and our numbering code is -->\n<!-- designed to sync with LaTeX's schemes       -->\n\n<!-- The xref-link template provides one of two types of links      -->\n<!--                                                                -->\n<!-- (a) a traditional HTML hyperlink, a jump to a new location     -->\n<!-- (b) a knowl, aka a transclusion, which appears within the text -->\n<!--                                                                -->\n<!-- A hyperlink is the default. For conversions to different       -->\n<!-- HTML outputs, the choice of targets appearing as knowls        -->\n<!-- can be adjusted by overriding the next template                -->\n\n<!-- This is the implementation of an abstract template, -->\n<!-- to accomodate hard-coded HTML numbers and for       -->\n<!-- LaTeX the \\ref and \\label mechanism                 -->\n<xsl:template match=\"*\" mode=\"xref-number\">\n    <xsl:param name=\"xref\" select=\"/..\" />\n    <xsl:variable name=\"needs-part-prefix\">\n        <xsl:apply-templates select=\".\" mode=\"crosses-part-boundary\">\n            <xsl:with-param name=\"xref\" select=\"$xref\" />\n        </xsl:apply-templates>\n    </xsl:variable>\n    <xsl:if test=\"$needs-part-prefix = 'true'\">\n        <xsl:apply-templates select=\"ancestor::part\" mode=\"serial-number\" />\n        <xsl:text>.</xsl:text>\n    </xsl:if>\n    <xsl:apply-templates select=\".\" mode=\"number\" />\n</xsl:template>\n\n<!-- One exception is a local tag on an mrow -->\n<xsl:template match=\"mrow[@tag]\" mode=\"xref-number\">\n    <xsl:apply-templates select=\"@tag\" mode=\"tag-symbol\" />\n</xsl:template>\n\n<!-- Same for a bare \"md\" whose manufactured \"mrow\" carries a @tag -->\n<xsl:template match=\"md[@pi:authored-one-line and mrow/@tag]\" mode=\"xref-number\">\n    <xsl:apply-templates select=\"mrow/@tag\" mode=\"tag-symbol\" />\n</xsl:template>\n\n<!-- The second abstract template, we condition   -->\n<!-- on if the link is rendered as a knowl or not -->\n<!-- and then condition on the location of the    -->\n<!-- actual link, which is sensitive to display   -->\n<!-- math in particular                           -->\n<!-- See xsl/pretext-common.xsl for more info     -->\n<!-- NB: for HTML output, the $content variable   -->\n<!-- may have HTML elements in it (e.g. link is a  -->\n<!-- title with emphasis, or a MathJax processing  -->\n<!-- span) so we want a \"copy-of\" here, not a      -->\n<!-- \"value-of\".                                   -->\n<!-- TODO: could match on \"xref\" once link routines  -->\n<!-- are broken into two and other uses are rearranged -->\n<xsl:template match=\"*\" mode=\"xref-link\">\n    <xsl:param name=\"target\" select=\"/..\" />\n    <xsl:param name=\"origin\" select=\"''\" />\n    <xsl:param name=\"content\" select=\"'MISSING LINK CONTENT'\"/>\n    <xsl:variable name=\"knowl\">\n        <xsl:apply-templates select=\"$target\" mode=\"xref-as-knowl\">\n            <xsl:with-param name=\"link\" select=\".\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <xsl:choose>\n        <!-- 1st exceptional case, xref in a webwork, or in    -->\n        <!-- some sort of title.  Then just parrot the content -->\n        <xsl:when test=\"ancestor::webwork-reps|ancestor::title|ancestor::shorttitle|ancestor::subtitle\">\n            <xsl:copy-of select=\"$content\"/>\n        </xsl:when>\n        <!-- 2nd exceptional case, xref in mrow of display math  -->\n        <!--   with Javascript (pure HTML) we can make knowls    -->\n        <!--   without Javascript (EPUB) we use plain text       -->\n        <xsl:when test=\"parent::mrow\">\n            <xsl:apply-templates select=\".\" mode=\"xref-link-display-math\">\n                <xsl:with-param name=\"target\" select=\"$target\"/>\n                <xsl:with-param name=\"origin\" select=\"'xref'\"/>\n                <xsl:with-param name=\"content\" select=\"$content\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- usual case, always an \"a\" element (anchor) -->\n        <xsl:otherwise>\n            <xsl:element name=\"a\">\n                <!-- knowl/hyperlink variability here -->\n                <xsl:choose>\n                    <!-- build a modern knowl -->\n                    <xsl:when test=\"$knowl='true'\">\n                        <!-- provide href for a fallback behavior if knowl is -->\n                        <!-- disabled intentionally or not                    -->\n                        <xsl:attribute name=\"href\">\n                            <xsl:apply-templates select=\"$target\" mode=\"url\" />\n                        </xsl:attribute>\n                        <!-- mark as duplicated content via an xref -->\n                        <xsl:attribute name=\"class\">\n                            <xsl:text>xref</xsl:text>\n                        </xsl:attribute>\n                        <xsl:attribute name=\"data-knowl\">\n                            <xsl:apply-templates select=\"$target\" mode=\"knowl-filename\">\n                                <xsl:with-param name=\"origin\" select=\"$origin\"/>\n                            </xsl:apply-templates>\n                        </xsl:attribute>\n                        <!-- text to use for tooltip/aria  -->\n                        <xsl:attribute name=\"data-reveal-label\">\n                            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                                <xsl:with-param name=\"string-id\" select=\"'reveal'\"/>\n                            </xsl:apply-templates>\n                        </xsl:attribute>\n                        <xsl:attribute name=\"data-close-label\">\n                            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                                <xsl:with-param name=\"string-id\" select=\"'close'\"/>\n                            </xsl:apply-templates>\n                        </xsl:attribute>\n                    </xsl:when>\n                    <!-- build traditional hyperlink -->\n                    <xsl:otherwise>\n                        <xsl:attribute name=\"href\">\n                            <xsl:apply-templates select=\"$target\" mode=\"url\" />\n                        </xsl:attribute>\n                        <!-- use a class to identify an internal link -->\n                        <xsl:attribute name=\"class\">\n                            <xsl:text>internal</xsl:text>\n                        </xsl:attribute>\n                    </xsl:otherwise>\n                </xsl:choose>\n                <!-- add HTML title attribute to the link -->\n                <xsl:attribute name=\"title\">\n                    <xsl:apply-templates select=\"$target\" mode=\"tooltip-text\" />\n                </xsl:attribute>\n                <!-- link content from common template -->\n                <xsl:copy-of select=\"$content\"/>\n            </xsl:element>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- For pure HTML we can make a true knowl or traditional link -->\n<!-- when an \"xref\" is authored inside of a display math \"mrow\" -->\n<!-- Requires a MathJax extension for knowls to render.         -->\n<!-- See discussion in \"xref-link\" about \"copy-of\" necessity.   -->\n<xsl:template match=\"*\" mode=\"xref-link-display-math\">\n    <xsl:param name=\"target\"/>\n    <xsl:param name=\"origin\"/>\n    <xsl:param name=\"content\"/>\n\n    <!-- this could be passed as a parameter, but -->\n    <!-- we have $target anyway, so can recompute -->\n    <xsl:variable name=\"knowl\">\n        <xsl:apply-templates select=\"$target\" mode=\"xref-as-knowl\">\n            <xsl:with-param name=\"link\" select=\".\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$knowl='true'\">\n            <xsl:text>\\knowl{</xsl:text>\n            <xsl:apply-templates select=\"$target\" mode=\"knowl-filename\">\n                <xsl:with-param name=\"origin\" select=\"'xref'\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>\\href{</xsl:text>\n            <xsl:apply-templates select=\"$target\" mode=\"url\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n    <xsl:text>}{</xsl:text>\n    <xsl:copy-of select=\"$content\"/>\n    <xsl:text>}</xsl:text>\n</xsl:template>\n\n<!-- A URL is needed various places, such as                     -->\n<!--   1. xref to material larger than a knowl, e.g. a \"chapter\" -->\n<!--   2. \"in-context\" link in xref-knowls                       -->\n<!--   3. summary-page links                                     -->\n<!--   4. many navigation devices, e.g. ToC, prev/next buttons   -->\n<!-- This is strictly an HTML construction.                      -->\n<!-- A containing filename, plus possibly a fragment identifier. -->\n<!-- NB: a \"p\" whose initial content is display math results in  -->\n<!-- a contest for the HTML id that goes on the                  -->\n<!-- div.displaymath.  The \"p\" is only a target of a hyperlink   -->\n<!-- when it is the \"in-context\" link of a knowl for the \"p\",    -->\n<!-- which only happens in the index, so the \"p\" must also have  -->\n<!-- an \"idx\" element.  So we are labeling the div for what it   -->\n<!-- is, display math, so links to numbered equations will work. -->\n<!-- So we have:                                                 -->\n<!-- BUG: a \"p\" that leads with display math and has an \"idx\"    -->\n<!-- creates a knowl in the index whose \"in-context\" link is     -->\n<!-- incorrect.                                                  -->\n<xsl:template match=\"*\" mode=\"url\">\n    <xsl:choose>\n        <xsl:when test=\"$chunk-level = 0\">\n            <!-- When building a single page, we just want the     -->\n            <!-- fragment identifier since links should just jump  -->\n            <!-- around the page. Not including the filename makes -->\n            <!-- it easy for for a user to rename the file later.  -->\n            <xsl:apply-templates select=\".\" mode=\"url-fragment\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- In other other cases, we want a filename plus a fragment -->\n            <!-- identifier if the link is to the interior of a page.     -->\n            <xsl:apply-templates select=\".\" mode=\"containing-filename\" />\n            <xsl:variable name=\"intermediate\">\n                <xsl:apply-templates select=\".\" mode=\"is-intermediate\" />\n            </xsl:variable>\n            <xsl:variable name=\"chunk\">\n                <xsl:apply-templates select=\".\" mode=\"is-chunk\" />\n            </xsl:variable>\n            <xsl:if test=\"$intermediate='false' and $chunk='false'\">\n                <!-- interior to a page, needs fragment identifier -->\n                <xsl:apply-templates select=\".\" mode=\"url-fragment\"/>\n            </xsl:if>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"url-fragment\">\n    <xsl:text>#</xsl:text>\n    <!-- All display math is in a  div.displaymath  with  -->\n    <!-- an HTML id.  An \"mrow\" can have an @xml:id, and  -->\n    <!-- we direct a URL (typically the \"in-context\" link -->\n    <!-- of a knowl) to the enclosing \"md\" or \"mdn\" (we   -->\n    <!-- can't know which in advance)                     -->\n    <xsl:choose>\n        <xsl:when test=\"self::mrow\">\n            <xsl:apply-templates select=\"parent::*\" mode=\"html-id\"/>\n        </xsl:when>\n        <!-- an \"men\" is fine here, we do not need a parent -->\n        <xsl:otherwise>\n            <xsl:apply-templates select=\".\" mode=\"html-id\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- The @id attribute of an HTML element is critical.      -->\n<!-- We supply the \"unique-id\".                             -->\n<xsl:template match=\"*\" mode=\"html-id\">\n    <xsl:apply-templates select=\".\" mode=\"unique-id\"/>\n</xsl:template>\n\n<!-- And a convenience template to make an id attribute.  -->\n<!-- Note: the purpose of an id is to later reference it, -->\n<!-- so we still need the \"html-id\" template in order to  -->\n<!-- make those references, but these two templates       -->\n<!-- together ensure that they are consistent.  And there -->\n<!-- are limited cases where we need ids derived from     -->\n<!-- these baseline versions.                             -->\n<xsl:template match=\"*\" mode=\"html-id-attribute\">\n    <xsl:attribute name=\"id\">\n        <xsl:apply-templates select=\".\" mode=\"html-id\"/>\n    </xsl:attribute>\n</xsl:template>\n\n<!-- We manufacture Javascript variables sometimes using            -->\n<!-- this id to keep them unique, but a dash (encouraged in PTX)    -->\n<!-- is banned in Javascript, so we make a \"no-dash\" version,       -->\n<!-- by replacing a hyphen by a double-underscore.                  -->\n<!-- NB: This runs some non-zero probability of breaking uniqueness -->\n<xsl:template match=\"*\" mode=\"unique-id-no-dash\">\n    <xsl:variable name=\"the-id\">\n        <xsl:apply-templates select=\".\" mode=\"unique-id\" />\n    </xsl:variable>\n    <xsl:value-of select=\"str:replace($the-id, '-', '__')\" />\n</xsl:template>\n\n\n<!-- ######## -->\n<!-- SI Units -->\n<!-- ######## -->\n\n<xsl:template match=\"quantity\">\n    <!-- Unicode FRACTION SLASH -->\n    <xsl:variable name=\"fraction-slash\" select=\"'&#x2044;'\"/>\n\n    <!-- span to prevent line breaks within the quantity -->\n    <span class=\"quantity\">\n        <xsl:apply-templates select=\"mag\"/>\n        <!-- if not solo, add separation -->\n        <xsl:if test=\"mag and (unit or per)\">\n            <xsl:text> </xsl:text>\n        </xsl:if>\n        <xsl:choose>\n            <xsl:when test=\"per\">\n               <sup>\n                    <xsl:if test=\"not(unit)\">\n                        <xsl:text>1</xsl:text>\n                    </xsl:if>\n                    <xsl:apply-templates select=\"unit\" />\n                </sup>\n                <xsl:value-of select=\"$fraction-slash\"/>\n                <sub>\n                    <xsl:apply-templates select=\"per\" />\n                </sub>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:apply-templates select=\"unit\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </span>\n    <!-- NB: no mag, no per, no unit implies no output -->\n    <!-- (really should be caught in schema), but      -->\n    <!-- no real harm in just doing nothing            -->\n</xsl:template>\n\n<!-- \"mag\" is pretty much verbatim, but we allow LaTeX syntax  -->\n<!-- for \\pi and we need to make them amenable to MathJax.     -->\n<!-- TODO:                                                     -->\n<!--   - implement <pi/> strictly inside \"mag\" (LaTeX too)     -->\n<!--   - move the recursive template to the \"repair\"           -->\n<!--     pass of the pre-processor                             -->\n<xsl:template match=\"mag\">\n    <xsl:call-template name=\"wrap-units-pi\">\n        <xsl:with-param name=\"text\">\n            <xsl:value-of select=\".\"/>\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- We recursively isolate instances of \\pi and replace them  -->\n<!-- with wrapped versions so MathJax will process them.  A    -->\n<!-- simple string replacement will not work since the         -->\n<!-- replacement is a span.process-math (an HTML element).     -->\n<!-- NB: this will not generalize easily to additional symbols -->\n<xsl:template name=\"wrap-units-pi\">\n    <xsl:param name=\"text\"/>\n\n    <xsl:variable name=\"pi\" select=\"'\\pi'\"/>\n    <xsl:choose>\n        <xsl:when test=\"not(contains($text, $pi))\">\n            <!-- nothing left to do, output as-is, and finish -->\n            <xsl:value-of select=\"$text\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- must have a \\pi, output prior text -->\n            <xsl:value-of select=\"substring-before($text, $pi)\"/>\n            <!-- output \\pi, appropriately bundled -->\n            <xsl:call-template name=\"inline-math-wrapper\">\n                <xsl:with-param name=\"math\" select=\"$pi\"/>\n            </xsl:call-template>\n            <!-- recurse on remainder -->\n            <xsl:call-template name=\"wrap-units-pi\">\n                <xsl:with-param name=\"text\" select=\"substring-after($text, $pi)\"/>\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- unit and per children of a quantity element    -->\n<!-- have a mandatory base attribute                -->\n<!-- may have prefix and exp attributes             -->\n<!-- base and prefix are not abbreviations          -->\n\n<xsl:key name=\"prefix-key\" match=\"prefix\" use=\"concat(../@name, @full)\"/>\n<xsl:key name=\"base-key\" match=\"base\" use=\"concat(../@name, @full)\"/>\n\n<xsl:template match=\"unit|per\">\n    <!-- Unicode MIDDLE-DOT -->\n    <xsl:variable name=\"inter-unit-product\" select=\"'&#x00B7;'\"/>\n\n    <!-- add non-breaking hyphen within a numerator or denominator of units -->\n    <xsl:if test=\"(self::unit and preceding-sibling::unit) or (self::per and preceding-sibling::per)\">\n        <xsl:value-of select=\"$inter-unit-product\"/>\n    </xsl:if>\n    <!-- prefix is optional -->\n    <xsl:if test=\"@prefix\">\n        <xsl:variable name=\"prefix\">\n            <xsl:value-of select=\"@prefix\" />\n        </xsl:variable>\n        <xsl:variable name=\"short\">\n            <xsl:for-each select=\"document('pretext-units.xsl')\">\n                <xsl:value-of select=\"key('prefix-key',concat('prefixes',$prefix))/@short\"/>\n            </xsl:for-each>\n        </xsl:variable>\n        <xsl:value-of select=\"$short\" />\n    </xsl:if>\n    <!-- base unit is required -->\n    <xsl:variable name=\"base\">\n        <xsl:value-of select=\"@base\" />\n    </xsl:variable>\n    <xsl:variable name=\"short\">\n        <xsl:for-each select=\"document('pretext-units.xsl')\">\n            <xsl:value-of select=\"key('base-key',concat('bases',$base))/@short\"/>\n        </xsl:for-each>\n    </xsl:variable>\n    <xsl:value-of select=\"$short\" />\n     <!-- exponent is optional -->\n    <xsl:if test=\"@exp\">\n        <sup>\n            <xsl:value-of select=\"@exp\"/>\n        </sup>\n    </xsl:if>\n</xsl:template>\n\n<!-- ############ -->\n<!-- Attributions -->\n<!-- ############ -->\n\n<!-- At end of: blockquote, preface, foreword       -->\n<!-- free-form for one line, or structured as lines -->\n<!-- TODO: add CSS for attribution, div flush right         -->\n<!-- And go slanted (\"oblique\"?)                            -->\n<!-- Maybe use CSS to right align as a block                -->\n<!-- https://github.com/BooksHTML/mathbook-assets/issues/64 -->\n\n<!-- Single line, mixed-content          -->\n<!-- Or structured by \"line\" elements    -->\n<!-- Quotation dash if within blockquote -->\n<!-- Unicode Character 'HORIZONTAL BAR' aka 'QUOTATION DASH' -->\n<xsl:template match=\"attribution\">\n    <cite class=\"attribution\">\n        <xsl:if test=\"parent::blockquote\">\n            <xsl:text>&#x2015;</xsl:text>\n        </xsl:if>\n        <xsl:choose>\n            <xsl:when test=\"line\">\n                <xsl:apply-templates select=\"line\" />\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:apply-templates/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </cite>\n</xsl:template>\n\n<!-- Defined terms (bold, typically) -->\n<xsl:template match=\"term\">\n    <dfn class=\"terminology\">\n        <xsl:apply-templates/>\n    </dfn>\n</xsl:template>\n\n<!-- Acronyms, Initialisms, Abbreviations -->\n<!-- abbreviation: contracted form                                  -->\n<!-- acronym: initials, pronounced as a word (eg SCUBA, RADAR)      -->\n<!-- initialism: one letter at a time, (eg CIA, FBI)                -->\n<!-- All are marked as the HTML \"abbr\" tag, but classes distinguish -->\n<!-- Would a screen reader know the difference?                     -->\n<xsl:template match=\"abbr\">\n    <abbr class=\"abbreviation\">\n        <xsl:apply-templates/>\n    </abbr>\n</xsl:template>\n\n<xsl:template match=\"acro\">\n    <abbr class=\"acronym\">\n        <xsl:apply-templates/>\n    </abbr>\n</xsl:template>\n\n<xsl:template match=\"init\">\n    <abbr class=\"initialism\">\n        <xsl:apply-templates/>\n    </abbr>\n</xsl:template>\n\n<!-- Emphasis -->\n<xsl:template match=\"em\">\n    <em class=\"emphasis\">\n        <xsl:apply-templates/>\n    </em>\n</xsl:template>\n\n<!-- Alert -->\n<xsl:template match=\"alert\">\n    <em class=\"alert\">\n        <xsl:apply-templates/>\n    </em>\n</xsl:template>\n\n<!-- CSS for ins, del, s -->\n<!-- http://html5doctor.com/ins-del-s/           -->\n<!-- http://stackoverflow.com/questions/2539207/ -->\n\n<!-- Insert (an edit) -->\n<xsl:template match=\"insert\">\n    <ins class=\"insert\">\n        <xsl:apply-templates/>\n    </ins>\n</xsl:template>\n\n<!-- Delete (an edit) -->\n<xsl:template match=\"delete\">\n    <del class=\"delete\">\n        <xsl:apply-templates/>\n    </del>\n</xsl:template>\n\n<!-- Stale (no longer relevant) -->\n<xsl:template match=\"stale\">\n    <s class=\"stale\">\n        <xsl:apply-templates/>\n    </s>\n</xsl:template>\n\n<!-- Characters for Tagging Equations -->\n\n<!-- 'SIX POINTED BLACK STAR' (U+2736) -->\n<xsl:template name=\"tag-star\">\n    <xsl:text>&#x2736;</xsl:text>\n</xsl:template>\n\n<!-- 'DAGGER' (U+2020) -->\n<xsl:template name=\"tag-dagger\">\n    <xsl:text>&#x2020;</xsl:text>\n</xsl:template>\n\n<!-- 'DOUBLE DAGGER' (U+2021) -->\n<xsl:template name=\"tag-daggerdbl\">\n    <xsl:text>&#x2021;</xsl:text>\n</xsl:template>\n\n<!-- 'NUMBER SIGN' (U+0023), identical to LaTeX -->\n<xsl:template name=\"tag-hash\">\n    <xsl:text>\\#</xsl:text>\n</xsl:template>\n\n<!-- 'MALTESE CROSS' (U+2720) -->\n<xsl:template name=\"tag-maltese\">\n    <xsl:text>&#x2720;</xsl:text>\n</xsl:template>\n\n<!-- Fill-in blank -->\n<!-- Bringhurst suggests 5/11 em per character                            -->\n<!-- A 'span' normally, but a MathJax non-standard \\Rule for math         -->\n<!-- \"\\Rule is a MathJax-specific extension with parameters being width,  -->\n<!-- height and depth of the rule\"                                        -->\n<!-- Davide Cervone                                                       -->\n<!-- https://groups.google.com/forum/#!topic/mathjax-users/IEivs1D7ntM    -->\n<xsl:template match=\"fillin[not(parent::m or parent::mrow)]\">\n    <xsl:choose>\n        <xsl:when test=\"ancestor::statement/../@pi:exercise-interactive='fillin'\">\n            <xsl:apply-imports />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:variable name=\"characters\">\n                <xsl:choose>\n                    <xsl:when test=\"@characters\">\n                        <xsl:value-of select=\"@characters\" />\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:text>10</xsl:text>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:variable>\n            <span class=\"fillin {$fillin-text-style}\" role=\"img\">\n                <xsl:attribute name=\"aria-label\">\n                    <xsl:value-of select=\"$characters\" />\n                    <xsl:text>-character blank</xsl:text>\n                </xsl:attribute>\n                <xsl:attribute name=\"style\">\n                    <xsl:text>width: </xsl:text>\n                    <xsl:value-of select=\"5 * $characters div 11\" />\n                    <xsl:text>em;</xsl:text>\n                </xsl:attribute>\n            </span>\n            <xsl:if test=\"@rows or @cols\">\n                <xsl:apply-templates select=\".\" mode=\"fillin-array\"/>\n            </xsl:if>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Implication Symbols -->\n<!-- TODO: better names! -->\n<xsl:template match=\"imply\">\n    <xsl:text>&#x21D2;</xsl:text>\n</xsl:template>\n<xsl:template match=\"implyreverse\">\n    <xsl:text>&#x21D0;</xsl:text>\n</xsl:template>\n\n<!-- TeX, LaTeX w/ CSS -->\n<!-- Corresponding CSS from William Hammond   -->\n<!-- attributed to David Carlisle             -->\n<!-- \"mathjax-users\" Google Group, 2015-12-27 -->\n<!-- PreTeXt, XeLaTeX, XeTeX are in -common   -->\n\n<xsl:template match=\"latex\">\n    <span class=\"latex-logo\">L<span class=\"A\">a</span>T<span class=\"E\">e</span>X</span>\n</xsl:template>\n<xsl:template match=\"tex\">\n    <span class=\"latex-logo\">T<span class=\"E\">e</span>X</span>\n</xsl:template>\n\n<!-- External URLs, Email        -->\n<!-- Open in new window/tab as external reference                        -->\n<!-- If \"no-content\", prefer @visual to @href, and then automatically    -->\n<!-- format like code (verbatim)                                         -->\n<!-- Within titles, we just produce (formatted) text, but nothing active -->\n<!-- N.B.  In \"content\" case, we get a special footnote from the         -->\n<!-- assembly phase, so look elsewhere for that handling.                -->\n<!-- N.B. compare with LaTeX version, could move much to -common         -->\n<xsl:template match=\"url|dataurl\">\n    <!-- link/reference/location may be external -->\n    <!-- (@href) or internal (dataurl[@source])  -->\n    <xsl:variable name=\"uri\">\n        <xsl:choose>\n            <!-- \"url\" and \"dataurl\" both support external @href -->\n            <xsl:when test=\"@href\">\n                <xsl:value-of select=\"@href\"/>\n            </xsl:when>\n            <!-- a \"dataurl\" might be local, @source is      -->\n            <!-- indication, so prefix with a local path/URI -->\n            <xsl:when test=\"self::dataurl and @source\">\n                <!-- empty when not using managed directories -->\n                <xsl:value-of select=\"$external-directory\"/>\n                <xsl:value-of select=\"@source\"/>\n            </xsl:when>\n            <!-- empty will be non-functional -->\n            <xsl:otherwise/>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- visible portion of HTML is the URL itself,   -->\n    <!-- formatted as code, or content of PTX element -->\n    <xsl:variable name=\"visible-text\">\n        <xsl:choose>\n            <xsl:when test=\"node()\">\n                <xsl:apply-templates/>\n            </xsl:when>\n            <xsl:otherwise>\n                <code class=\"code-inline tex2jax_ignore\">\n                    <xsl:choose>\n                        <xsl:when test=\"@visual\">\n                            <xsl:value-of select=\"@visual\"/>\n                        </xsl:when>\n                        <xsl:otherwise>\n                            <xsl:value-of select=\"$uri\"/>\n                        </xsl:otherwise>\n                    </xsl:choose>\n                </code>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- Normally in an active link, except inactive in titles -->\n    <xsl:choose>\n        <xsl:when test=\"ancestor::title|ancestor::shorttitle|ancestor::subtitle\">\n            <xsl:copy-of select=\"$visible-text\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- class name identifies an external link -->\n            <a class=\"external\" href=\"{$uri}\" target=\"_blank\">\n                <xsl:copy-of select=\"$visible-text\" />\n            </a>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"email\">\n    <xsl:element name=\"a\">\n        <xsl:attribute name=\"href\">\n            <xsl:text>mailto:</xsl:text>\n            <xsl:value-of select=\".\" />\n        </xsl:attribute>\n        <xsl:value-of select=\".\" />\n    </xsl:element>\n</xsl:template>\n\n\n<!-- ############# -->\n<!-- Verbatim Text -->\n<!-- ############# -->\n\n<!-- Code, inline -->\n<!-- HTML \"code\" element, with classes -->\n<xsl:template name=\"code-wrapper\">\n    <xsl:param name=\"content\"/>\n\n    <code class=\"code-inline tex2jax_ignore\">\n        <xsl:value-of select=\"$content\"/>\n    </code>\n</xsl:template>\n\n<!-- A copy button serves a block of code; within a \"tabular\"  -->\n<!-- cell the content is short and the floating button crowds  -->\n<!-- the cell, so there we decline to provide one.             -->\n<xsl:template name=\"insert-clipboardable-class\">\n    <xsl:if test=\"not(ancestor::tabular)\">\n        <xsl:text> clipboardable</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<!-- 100% analogue of LaTeX's verbatim            -->\n<!-- environment or HTML's <pre> element          -->\n<!-- TODO: center on page?                        -->\n\n<!-- When visual spaces are requested, we mimic the               -->\n<!-- long-established pattern in LaTeX and use a (short) open     -->\n<!-- box character, which is also suggested as a \"graphic for     -->\n<!-- space\" as part of the Unicode standard.                      -->\n<!-- Unicode Character 'OPEN BOX' (U+2423)                        -->\n<!-- https://www.fileformat.info/info/unicode/char/2423/index.htm -->\n\n<!-- cd is for use in paragraphs, inline -->\n<!-- Unstructured is pure text           -->\n<xsl:template match=\"cd\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <!-- newline inserted to encourage formatted output -->\n    <xsl:text>&#xa;</xsl:text>\n    <xsl:element name=\"pre\">\n        <xsl:attribute name=\"class\">\n            <xsl:text>code-display tex2jax_ignore</xsl:text>\n            <xsl:call-template name=\"insert-clipboardable-class\" />\n        </xsl:attribute>\n        <xsl:choose>\n            <xsl:when test=\"not(@showspaces) or (@showspaces = 'none')\">\n                <xsl:value-of select=\".\" />\n            </xsl:when>\n            <xsl:when test=\"@showspaces = 'all'\">\n                <xsl:value-of select=\"str:replace(., '&#x20;', '&#x2423;')\" />\n            </xsl:when>\n        </xsl:choose>\n    </xsl:element>\n</xsl:template>\n\n<!-- cline template is in xsl/pretext-common.xsl -->\n<xsl:template match=\"cd[cline]\">\n    <xsl:param name=\"b-original\" select=\"true()\" />\n    <!-- newline inserted to encourage formatted output -->\n    <xsl:text>&#xa;</xsl:text>\n    <xsl:element name=\"pre\">\n        <xsl:attribute name=\"class\">\n            <xsl:text>code-display tex2jax_ignore</xsl:text>\n            <xsl:call-template name=\"insert-clipboardable-class\" />\n        </xsl:attribute>\n        <xsl:apply-templates select=\"cline\" />\n    </xsl:element>\n</xsl:template>\n\n<!-- Override from -common to insert visual spaces -->\n<xsl:template match=\"cline[parent::cd/@showspaces = 'all']\">\n    <xsl:value-of select=\"str:replace(., '&#x20;', '&#x2423;')\" />\n    <xsl:text>&#xa;</xsl:text>\n</xsl:template>\n\n<!-- \"pre\" is analogous to the HTML tag of the same name -->\n<!-- The \"interior\" templates decide between two styles  -->\n<!--   (a) clean up raw text, just like for Sage code    -->\n<!--   (b) interpret cline as line-by-line structure     -->\n<!-- (See templates in xsl/pretext-common.xsl file)     -->\n<!-- Then wrap in a pre element that MathJax ignores     -->\n<xsl:template match=\"pre\">\n    <pre>\n        <xsl:attribute name=\"class\">\n            <xsl:text>code-block tex2jax_ignore</xsl:text>\n            <xsl:call-template name=\"insert-clipboardable-class\" />\n        </xsl:attribute>\n        <xsl:apply-templates select=\".\" mode=\"interior\"/>\n    </pre>\n</xsl:template>\n\n<!-- ################## -->\n<!-- Special Characters -->\n<!-- ################## -->\n\n<!-- Left Single Quote -->\n<xsl:template match=\"*\" mode=\"lsq-character\">\n    <xsl:apply-templates select=\".\" mode=\"quote-character-unicode\">\n        <xsl:with-param name=\"style\">\n            <xsl:apply-templates select=\".\" mode=\"get-quote-secondary\"/>\n        </xsl:with-param>\n        <xsl:with-param name=\"side\" select=\"'left'\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Right Single Quote -->\n<xsl:template match=\"*\" mode=\"rsq-character\">\n    <xsl:apply-templates select=\".\" mode=\"quote-character-unicode\">\n        <xsl:with-param name=\"style\">\n            <xsl:apply-templates select=\".\" mode=\"get-quote-secondary\"/>\n        </xsl:with-param>\n        <xsl:with-param name=\"side\" select=\"'right'\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Left (Primary) Quote -->\n<xsl:template match=\"*\" mode=\"lq-character\">\n    <xsl:apply-templates select=\".\" mode=\"quote-character-unicode\">\n        <xsl:with-param name=\"style\">\n            <xsl:apply-templates select=\".\" mode=\"get-quote-primary\"/>\n        </xsl:with-param>\n        <xsl:with-param name=\"side\" select=\"'left'\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Right (Double) Quote -->\n<xsl:template match=\"*\" mode=\"rq-character\">\n    <xsl:apply-templates select=\".\" mode=\"quote-character-unicode\">\n        <xsl:with-param name=\"style\">\n            <xsl:apply-templates select=\".\" mode=\"get-quote-primary\"/>\n        </xsl:with-param>\n        <xsl:with-param name=\"side\" select=\"'right'\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n\n<!-- Other Miscellaneous Symbols, Constructions -->\n\n<!-- Foreign words/idioms -->\n<!-- Rutter, Web Typography, p.50 advocates a \"span\" with      -->\n<!-- a \"lang\" attribute for foreign words so screen readers    -->\n<!-- and hyphenation react properly.  Elsewhere, italics is    -->\n<!-- suggested only for transliterated wods, to avoid          -->\n<!-- confusion. However, for now, we are using \"i\" by default, -->\n<!-- with a class that can be used in CSS for distinctions.    -->\n<!-- But see also (2018-03-23):                                -->\n<!-- https://www.w3.org/TR/html5/text-level-semantics.html#the-i-element -->\n<xsl:template match=\"foreign\">\n    <i class=\"foreign\">\n        <xsl:if test=\"@xml:lang\">\n            <xsl:attribute name=\"lang\">\n                <xsl:value-of select=\"@xml:lang\" />\n            </xsl:attribute>\n        </xsl:if>\n        <xsl:apply-templates/>\n    </i>\n</xsl:template>\n\n<!-- Symbols -->\n<!-- Symbols are for internal use within theme designs.            -->\n<!-- Compare to \"icons\" which are designed for author use.         -->\n<!-- Presumes material symbols font was loaded in \"fonts\" template -->\n<xsl:include href=\"./html-symbols.xsl\"/>\n<xsl:key name=\"symbol-key\" match=\"symbolinfo\" use=\"@name\"/>\n<xsl:variable name=\"symbol-table\" select=\"exsl:node-set($available-symbols-list)\"/>\n\n<xsl:template name=\"insert-symbol\">\n    <xsl:param name = \"name\" />\n    <!-- List of available html symbols for symbol    -->\n\n    <!-- lookup entity code as sanity check -->\n    <xsl:variable name=\"entity-name\">\n        <xsl:for-each select=\"$symbol-table\">\n            <xsl:value-of select=\"key('symbol-key', $name)/@entity\"/>\n        </xsl:for-each>\n    </xsl:variable>\n\n    <xsl:if test=\"$entity-name=''\">\n        <xsl:message>PTX:ERROR: the symbol name <xsl:value-of select=\"$name\"/> is not a known symbol. It will not render correctly.</xsl:message>\n    </xsl:if>\n\n    <!-- Could also just use $name here if assume browser supports ligatures. (Just about all do)  -->\n    <span class=\"icon material-symbols-outlined\" aria-hidden=\"true\">\n        <xsl:text disable-output-escaping=\"yes\">&amp;#x</xsl:text><xsl:value-of select=\"$entity-name\"/><xsl:text>;</xsl:text>\n    </span>\n</xsl:template>\n\n<!-- ##### -->\n<!-- Icons -->\n<!-- ##### -->\n\n<!-- Presumes CSS headers have been loaded -->\n<xsl:template match=\"icon\">\n    <!-- the name attribute of the \"icon\" in text as a string -->\n    <xsl:variable name=\"icon-name\">\n        <xsl:value-of select=\"@name\"/>\n    </xsl:variable>\n\n    <!-- for-each is just one node, but sets context for key() -->\n    <xsl:variable name=\"fa-family\">\n        <xsl:for-each select=\"$icon-table\">\n            <xsl:value-of select=\"key('icon-key', $icon-name)/@font-awesome-family\"/>\n        </xsl:for-each>\n    </xsl:variable>\n\n    <!-- for-each is just one node, but sets context for key() -->\n    <xsl:variable name=\"fa-name\">\n        <xsl:for-each select=\"$icon-table\">\n            <xsl:value-of select=\"key('icon-key', $icon-name)/@font-awesome\"/>\n        </xsl:for-each>\n    </xsl:variable>\n\n    <!-- Element could be \"i\", but seems non-semantic for screenreaders -->\n    <xsl:element name=\"span\">\n        <xsl:attribute name=\"class\">\n            <xsl:choose>\n                <xsl:when test=\"$fa-family = 'classic'\">\n                    <!-- \"solid\", may become \"fa-solid\" in v6\" -->\n                    <xsl:text>fas</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$fa-family = 'brands'\">\n                    <!-- \"brands\", may become \"fa-brand\" in v6\" -->\n                    <xsl:text>fab</xsl:text>\n                </xsl:when>\n                <xsl:otherwise/>\n            </xsl:choose>\n            <xsl:text> </xsl:text>\n            <xsl:text>fa-</xsl:text>\n            <xsl:value-of select=\"$fa-name\"/>\n        </xsl:attribute>\n    </xsl:element>\n</xsl:template>\n\n\n<!-- ############# -->\n<!-- Keyboard Keys -->\n<!-- ############# -->\n\n<xsl:template match=\"kbd[not(@name)]\">\n    <kbd class=\"kbdkey\">\n        <xsl:value-of select=\".\"/>\n    </kbd>\n</xsl:template>\n\n<xsl:template match=\"kbd[@name]\">\n    <!-- the name attribute of the \"kbd\" in text as a string -->\n    <xsl:variable name=\"kbdkey-name\">\n        <xsl:value-of select=\"@name\"/>\n    </xsl:variable>\n    <!-- Entirely similar HTML/CSS, but will hold a Unicode character -->\n    <kbd class=\"kbdkey\">\n        <!-- for-each is just one node, but sets context for key() -->\n        <xsl:for-each select=\"$kbdkey-table\">\n            <xsl:value-of select=\"key('kbdkey-key', $kbdkey-name)/@unicode\" />\n        </xsl:for-each>\n    </kbd>\n</xsl:template>\n\n\n<!-- ################ -->\n<!-- Biological Names -->\n<!-- ################ -->\n\n<!-- typically in an italic font -->\n\n<xsl:template match=\"taxon\">\n    <span class=\"taxon\">\n        <xsl:choose>\n            <!-- both substructures -->\n            <xsl:when test=\"genus and species\">\n                <xsl:apply-templates select=\"genus\"/>\n                <xsl:text> </xsl:text>\n                <xsl:apply-templates select=\"species\"/>\n            </xsl:when>\n            <!-- just one -->\n            <xsl:when test=\"genus\">\n                <xsl:apply-templates select=\"genus\"/>\n            </xsl:when>\n            <!-- just the other one -->\n            <xsl:when test=\"species\">\n                <xsl:apply-templates select=\"species\"/>\n            </xsl:when>\n            <!-- not structured, use content -->\n            <xsl:otherwise>\n                <xsl:apply-templates/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </span>\n</xsl:template>\n\n<xsl:template match=\"genus\">\n    <span class=\"genus\">\n        <xsl:apply-templates select=\"text()\"/>\n    </span>\n</xsl:template>\n\n<xsl:template match=\"species\">\n    <span class=\"species\">\n        <xsl:apply-templates select=\"text()\"/>\n    </span>\n</xsl:template>\n\n<!-- Titles of Publications -->\n<!-- 2018-02-05: Deprecate \"booktitle\" in favor of       -->\n<!-- \"pubtitle\".  Will still maintain all for a while.   -->\n<!-- CMOS:  When quoted in text or listed in a           -->\n<!-- bibliography, titles of books, journals, plays,     -->\n<!-- and other freestanding works are italicized; titles -->\n<!-- of articles, chapters, and other shorter works      -->\n<!-- are set in roman and enclosed in quotation marks.   -->\n<xsl:template match=\"pubtitle\">\n    <span class=\"booktitle\">\n        <xsl:apply-templates/>\n    </span>\n</xsl:template>\n\n<!-- We provide the quotation marks explicitly, along       -->\n<!-- with a span for any additional styling.  The quotation -->\n<!-- marks are necessary for accessibility.                 -->\n<xsl:template match=\"articletitle\">\n    <span class=\"articletitle\">\n        <xsl:apply-templates select=\".\" mode=\"lq-character\"/>\n        <xsl:apply-templates/>\n        <xsl:apply-templates select=\".\" mode=\"rq-character\"/>\n    </span>\n</xsl:template>\n\n\n<!-- ################## -->\n<!-- Special Characters -->\n<!-- ################## -->\n\n<!-- Each character is the bare Unicode code point, read from the -->\n<!-- representation table in  pretext-common.xsl; an exception    -->\n<!-- needing markup overrides the modal template, per character   -->\n\n<xsl:template match=\"char\" mode=\"character\">\n    <xsl:choose>\n        <xsl:when test=\"@unicode\">\n            <xsl:value-of select=\"@unicode\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:call-template name=\"warn-unimplemented-character\">\n                <xsl:with-param name=\"char-name\" select=\"@name\"/>\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Times -->\n<!-- A \"multiplication sign\" symbol for use in text   -->\n<!-- Styled to enhance, consensus at Google Group was -->\n<!-- font-size: larger; vertical-align: -.2ex;        -->\n<xsl:template match=\"char[@name = 'times']\" mode=\"character\">\n    <xsl:element name=\"span\">\n        <xsl:attribute name=\"class\">\n            <xsl:text>times-sign</xsl:text>\n        </xsl:attribute>\n        <xsl:text>&#xd7;</xsl:text>\n    </xsl:element>\n</xsl:template>\n\n<!--       -->\n<!-- Music -->\n<!--       -->\n\n<!--                 -->\n<!-- Musical Symbols -->\n<!--                 -->\n\n<!-- Accidentals -->\n\n<!-- TODO: If requested, add semi- and sesqui- versions of sharp and flat -->\n\n<!-- Double Sharp -->\n<!-- Unicode Character 'MUSICAL SYMBOL DOUBLE SHARP' (U+1D12A)    -->\n<!-- http://www.fileformat.info/info/unicode/char/1d12a/index.htm -->\n<xsl:template name=\"doublesharp\">\n    <xsl:text>&#x1D12A;</xsl:text>\n</xsl:template>\n\n<!-- Sharp -->\n<!-- Unicode Character 'MUSIC SHARP SIGN' (U+266F)               -->\n<!-- http://www.fileformat.info/info/unicode/char/266f/index.htm -->\n<xsl:template name=\"sharp\">\n    <xsl:text>&#x266F;</xsl:text>\n</xsl:template>\n\n<!-- Natural -->\n<!-- Unicode Character 'MUSIC NATURAL SIGN' (U+266E)             -->\n<!-- http://www.fileformat.info/info/unicode/char/266e/index.htm -->\n<xsl:template name=\"natural\">\n    <xsl:text>&#x266E;</xsl:text>\n</xsl:template>\n\n<!-- Flat -->\n<!-- Unicode Character 'MUSIC FLAT SIGN' (U+266D)                -->\n<!-- http://www.fileformat.info/info/unicode/char/266d/index.htm -->\n<xsl:template name=\"flat\">\n    <xsl:text>&#x266D;</xsl:text>\n</xsl:template>\n\n<!-- Double Flat -->\n<!-- Unicode Character 'MUSICAL SYMBOL DOUBLE FLAT' (U+1D12B)     -->\n<!-- http://www.fileformat.info/info/unicode/char/1d12b/index.htm -->\n<xsl:template name=\"doubleflat\">\n    <xsl:text>&#x1D12B;</xsl:text>\n</xsl:template>\n\n<!-- Half Diminished -->\n<!-- (MathJax does not support \"\\o\") -->\n<!-- Unicode Character 'LATIN SMALL LETTER O WITH STROKE' (U+00F8) -->\n<!-- http://www.fileformat.info/info/unicode/char/00F8/index.htm -->\n<xsl:template name=\"halfdiminishedchordsymbol\">\n    <xsl:text>&#x00F8;</xsl:text>\n</xsl:template>\n\n<!-- Implement abstract templates to support      -->\n<!-- formatting of bibliographic entries in HTML. -->\n\n<xsl:template match=\"*\" mode=\"italic\">\n    <i>\n        <xsl:apply-templates/>\n    </i>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"bold\">\n    <b>\n        <xsl:apply-templates/>\n    </b>\n</xsl:template>\n\n<!-- This should likely become an \"a\" for URLS -->\n<xsl:template match=\"*\" mode=\"monospace\">\n    <code class=\"code-inline tex2jax_ignore\">\n        <xsl:apply-templates/>\n    </code>\n</xsl:template>\n\n<xsl:template name=\"biblio-period\">\n    <xsl:text>.</xsl:text>\n</xsl:template>\n\n<!-- Index Entries -->\n<!-- Kill on sight, collect later to build index  -->\n<xsl:template match=\"index[not(index-list)]\" />\n<xsl:template match=\"idx\" />\n\n\n<!-- ############################ -->\n<!-- Literate Programming Support -->\n<!-- ############################ -->\n\n<!-- The \"fragment\" element is used various other places, so that it   -->\n<!-- slots into the knowl-creation system.  The pointer to a fragment, -->\n<!-- \"fragref\", is different, and this makes a visual representation   -->\n<!-- of a pointer to the target, as a knowl.  The next two templates   -->\n<!-- support the \"wrapped-content\" template for \"fragment\".            -->\n\n<!-- @ref is simply a pointer to a fragment, so -->\n<!-- convert title into a knowl for the target  -->\n<xsl:template match=\"fragref\">\n    <xsl:variable name=\"target\" select=\"id(@ref)\"/>\n    <span>\n        <xsl:call-template name=\"character\">\n            <xsl:with-param name=\"name\" select=\"'langle'\"/>\n        </xsl:call-template>\n        <xsl:apply-templates select=\".\" mode=\"xref-link\">\n            <xsl:with-param name=\"target\" select=\"$target\" />\n            <!-- \"fragref\" is isomorpic to \"xref\" as a link -->\n            <xsl:with-param name=\"origin\" select=\"'xref'\" />\n            <xsl:with-param name=\"content\">\n                <xsl:apply-templates select=\"$target\" mode=\"title-full\"/>\n            </xsl:with-param>\n        </xsl:apply-templates>\n        <xsl:text> </xsl:text>\n        <xsl:apply-templates select=\"$target\" mode=\"number\"/>\n        <xsl:call-template name=\"character\">\n            <xsl:with-param name=\"name\" select=\"'rangle'\"/>\n        </xsl:call-template>\n    </span>\n    <br/>\n</xsl:template>\n\n<!-- wrap code in a \"pre\" environment, after pulling left -->\n<!-- Drop whitespace only text() nodes                    -->\n<xsl:template match=\"fragment/code\">\n    <xsl:variable name=\"normalized-frag\" select=\"normalize-space(.)\"/>\n    <xsl:if test=\"not($normalized-frag = '')\">\n        <xsl:call-template name=\"sanitize-text\">\n            <xsl:with-param name=\"text\" select=\".\" />\n        </xsl:call-template>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- Sage Cells -->\n<!-- TODO: make hidden autoeval cells link against sage-compute cells -->\n\n<!-- The block-type parameter is only received from, and sent to, the -->\n<!-- templates in the HTML conversion.  The purpose is to inform that -->\n<!-- conversion that the Sage cell is inside a born-hidden knowl      -->\n<!-- ($block-type = 'hidden') and adjust the class name accordingly.  -->\n\n<!-- Never an @id , so just repeat -->\n<xsl:template match=\"sage\" mode=\"duplicate\">\n    <xsl:apply-templates select=\".\" />\n</xsl:template>\n\n<!-- An abstract named template accepts input text and   -->\n<!-- output text, then wraps it for the Sage Cell Server -->\n<!-- TODO: consider showing output in green span (?),    -->\n<!-- presently output is dropped as computable           -->\n<!-- NB: button text is also set as part of knowls code  -->\n<xsl:template match=\"sage\" mode=\"sage-active-markup\">\n    <xsl:param name=\"language-attribute\" />\n    <xsl:param name=\"b-autoeval\" select=\"false()\"/>\n    <xsl:param name=\"in\" />\n    <xsl:param name=\"out\" />\n    <xsl:param name=\"b-original\"/>\n\n    <xsl:element name=\"div\">\n        <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n        <xsl:attribute name=\"class\">\n            <!-- \".ptx-sagecell\" for CSS (and not simply .sagecell). -->\n            <!-- See https://github.com/sagemath/sagecell/issues/542 -->\n            <xsl:text>ptx-sagecell </xsl:text>\n            <xsl:call-template name=\"sagecell-class-name\">\n                <xsl:with-param name=\"language-attribute\" select=\"$language-attribute\"/>\n                <xsl:with-param name=\"b-autoeval\" select=\"$b-autoeval\"/>\n            </xsl:call-template>\n        </xsl:attribute>\n\n        <xsl:element name=\"script\">\n            <xsl:attribute name=\"type\">\n                <xsl:text>text/x-sage</xsl:text>\n            </xsl:attribute>\n            <xsl:value-of select=\"$in\" />\n        </xsl:element>\n    </xsl:element>\n</xsl:template>\n\n<!-- An abstract named template accepts input text   -->\n<!-- and provides the display class, so untouchable  -->\n<xsl:template name=\"sage-display-markup\">\n    <xsl:param name=\"in\" />\n\n    <pre>\n        <xsl:attribute name=\"class\">\n            <!-- \".ptx-sagecell\" for CSS (and not simply .sagecell). -->\n            <!-- See https://github.com/sagemath/sagecell/issues/542 -->\n            <xsl:text>ptx-sagecell sage-display</xsl:text>\n        </xsl:attribute>\n        <script type=\"text/x-sage\">\n            <xsl:value-of select=\"$in\" />\n        </script>\n    </pre>\n</xsl:template>\n\n<!-- Program Listings -->\n<!-- Research:  http://softwaremaniacs.org/blog/2011/05/22/highlighters-comparison/  -->\n<!-- See common file for more on language handlers, and \"language-prism\" template    -->\n<!-- TODO: maybe ship sanitized \"input\" to each modal template? -->\n<xsl:template match=\"program[not(ancestor::sidebyside)]|console[not(ancestor::sidebyside)]\">\n    <!-- Possibly annotate with the source                     -->\n    <xsl:apply-templates select=\".\" mode=\"view-source-widget\"/>\n    <xsl:choose>\n        <!-- if  a program is elected as interactive, then     -->\n        <!-- let Runestone do the best it can via the template -->\n        <xsl:when test=\"self::program and (@interactive='activecode')\">\n            <xsl:apply-templates select=\".\" mode=\"runestone-activecode\"/>\n        </xsl:when>\n        <!-- if  a program is elected as interactive, then     -->\n        <!-- let Runestone do the best it can via the template -->\n        <xsl:when test=\"self::program and (@interactive='codelens')\">\n            <xsl:apply-templates select=\".\" mode=\"runestone-codelens\"/>\n        </xsl:when>\n        <!-- fallback is a less-capable static version, which -->\n        <!-- might actually be desired for many formats       -->\n        <xsl:otherwise>\n            <xsl:variable name=\"rtf-layout\">\n                <xsl:apply-templates select=\".\" mode=\"layout-parameters\" />\n            </xsl:variable>\n            <xsl:variable name=\"layout\" select=\"exsl:node-set($rtf-layout)\" />\n            <!-- div is constraint/positioning for contained program/console -->\n            <div class=\"code-box\">\n                <!-- only produce inline styles if width has been changed -->\n                <xsl:if test=\"$layout/width != 100\">\n                    <xsl:attribute name=\"style\">\n                        <xsl:text>width: </xsl:text>\n                        <xsl:value-of select=\"$layout/width\"/>\n                        <xsl:text>%;</xsl:text>\n                        <xsl:text> margin-left: </xsl:text>\n                        <xsl:value-of select=\"$layout/left-margin\"/>\n                        <xsl:text>%;</xsl:text>\n                        <xsl:text> margin-right: </xsl:text>\n                        <xsl:value-of select=\"$layout/right-margin\"/>\n                        <xsl:text>%;</xsl:text>\n                    </xsl:attribute>\n                </xsl:if>\n                <xsl:apply-templates select=\".\" mode=\"code-inclusion\"/>\n            </div>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"program[ancestor::sidebyside]|console[ancestor::sidebyside]\">\n    <!-- Possibly annotate with the source                     -->\n    <xsl:apply-templates select=\".\" mode=\"view-source-widget\"/>\n    <xsl:choose>\n        <!-- if  a program is elected as interactive, then     -->\n        <!-- let Runestone do the best it can via the template -->\n        <xsl:when test=\"self::program and (@interactive='activecode')\">\n            <xsl:apply-templates select=\".\" mode=\"runestone-activecode\"/>\n        </xsl:when>\n        <!-- if  a program is elected as interactive, then     -->\n        <!-- let Runestone do the best it can via the template -->\n        <xsl:when test=\"self::program and (@interactive='codelens')\">\n            <xsl:apply-templates select=\".\" mode=\"runestone-codelens\"/>\n        </xsl:when>\n        <!-- fallback is a less-capable static version, which -->\n        <!-- might actually be desired for many formats       -->\n        <!-- constrained by side-by-side boxes                -->\n        <xsl:otherwise>\n            <xsl:apply-templates select=\".\" mode=\"code-inclusion\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- An inline program fragment with potential -->\n<!-- syntax highlighting from Prism            -->\n<!-- Whitespace is left as authored            -->\n<xsl:template match=\"pf\">\n    <xsl:variable name=\"prism-language\">\n        <xsl:apply-templates select=\".\" mode=\"prism-language\"/>\n    </xsl:variable>\n    <code>\n        <xsl:attribute name=\"class\">\n            <xsl:text>code-inline tex2jax_ignore</xsl:text>\n            <xsl:choose>\n                <xsl:when test=\"not($prism-language = '')\">\n                    <xsl:text> language-</xsl:text>\n                    <xsl:value-of select=\"$prism-language\" />\n                </xsl:when>\n                <!-- else, explicitly use what code gives -->\n                <xsl:otherwise>\n                    <xsl:text> language-none</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:attribute>\n        <xsl:value-of select=\".\" />\n    </code>\n</xsl:template>\n\n<!-- A non-interactive version with potential -->\n<!-- syntax highlighting from Prism           -->\n<xsl:template match=\"program\" mode=\"code-inclusion\">\n    <xsl:variable name=\"prism-language\">\n        <xsl:apply-templates select=\".\" mode=\"prism-language\"/>\n    </xsl:variable>\n    <!-- a \"program\" element may be empty in a coding       -->\n    <!-- exercise, and just used to indicate an interactive -->\n    <!-- area supporting some language                      -->\n    <xsl:variable name=\"b-has-code\" select=\"not(normalize-space(code) = '') or preamble[@visible = 'yes'] or postamble[@visible = 'yes']\"/>\n    <xsl:if test=\"$b-has-code\">\n        <pre>\n            <!-- always identify as coming from \"program\" -->\n            <xsl:attribute name=\"class\">\n                <xsl:text>program</xsl:text>\n                <xsl:call-template name=\"insert-clipboardable-class\" />\n                <!-- conditionally request line numbers -->\n                <xsl:if test=\"@line-numbers = 'yes'\">\n                    <xsl:text> line-numbers</xsl:text>\n                </xsl:if>\n            </xsl:attribute>\n            <!-- Setup line highlighting and numbering -->\n            <xsl:if test=\"@highlight-lines != ''\">\n                <xsl:attribute name=\"data-line\">\n                    <!-- force comma-, or space-separated, list to commas -->\n                    <xsl:value-of select=\"translate(normalize-space(translate(@highlight-lines, ',', ' ')), ' ', ',')\"/>\n                </xsl:attribute>\n            </xsl:if>\n            <code>\n                <!-- Runestone may have a use for ids and filenames, even on non-interactive -->\n                <!-- programs (e.g. inclusion elsewhere).                                    -->\n                <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n                <xsl:if test=\"@filename\">\n                    <xsl:attribute name=\"data-filename\">\n                        <xsl:value-of select=\"@filename\"/>\n                    </xsl:attribute>\n                </xsl:if>\n                <!-- Prism only needs a single class name, per language  -->\n                <!-- placed on \"code\" but will migrate to the \"pre\" also -->\n                <xsl:attribute name=\"class\">\n                    <xsl:choose>\n                        <xsl:when test=\"not($prism-language = '')\">\n                            <xsl:text>language-</xsl:text>\n                            <xsl:value-of select=\"$prism-language\" />\n                        </xsl:when>\n                        <!-- else, explicitly use what code gives -->\n                        <xsl:otherwise>\n                            <xsl:text>language-none</xsl:text>\n                        </xsl:otherwise>\n                    </xsl:choose>\n                </xsl:attribute>\n                <!-- build up full program text so we can apply sanitize-text to entire blob -->\n                <!-- and thus allow relative indentation for preamble/code/postamble         -->\n                <xsl:variable name=\"program-text\">\n                    <xsl:if test=\"preamble[not(@visible = 'no')]\">\n                        <xsl:apply-templates select=\"preamble\" mode=\"program-part-processing\"/>\n                    </xsl:if>\n                    <xsl:apply-templates select=\"code\" mode=\"program-part-processing\"/>\n                    <xsl:if test=\"postamble[not(@visible = 'no')]\">\n                        <xsl:apply-templates select=\"postamble\" mode=\"program-part-processing\"/>\n                    </xsl:if>\n                </xsl:variable>\n                <!-- now sanitize the whole blob -->\n                <xsl:call-template name=\"sanitize-text\">\n                    <xsl:with-param name=\"text\" select=\"$program-text\" />\n                </xsl:call-template>\n            </code>\n        </pre>\n    </xsl:if>\n</xsl:template>\n\n<!-- Data Files -->\n\n<xsl:template match=\"datafile\">\n    <xsl:apply-templates select=\".\" mode=\"runestone-to-interactive\"/>\n</xsl:template>\n\n<!-- Queries -->\n\n<xsl:template match=\"query\">\n    <xsl:apply-templates select=\".\" mode=\"runestone-to-interactive\"/>\n</xsl:template>\n\n<!-- Console/input helper -->\n<!-- A single line of input, possibly with \"prefix\" (prompt or continuation) -->\n<!-- prefix gets wrapped in span if not empty -->\n<xsl:template name=\"input-line-with-prompt\">\n    <xsl:param name=\"text\" />\n    <xsl:param name=\"prefix\" />\n    <xsl:if test=\"not($prefix = '')\">\n        <span class=\"prompt unselectable\">\n            <xsl:value-of select=\"$prefix\"/>\n        </span>\n    </xsl:if>\n    <b>\n        <xsl:value-of select=\"$text\" />\n    </b>\n</xsl:template>\n\n<!-- Console Session -->\n<!-- An interactive command-line session with a prompt, input and output -->\n<xsl:template match=\"console\" mode=\"code-inclusion\">\n    <!-- ignore prompt, and pick it up in trailing input -->\n    <pre>\n        <xsl:attribute name=\"class\">\n            <xsl:text>console</xsl:text>\n            <xsl:call-template name=\"insert-clipboardable-class\" />\n        </xsl:attribute>\n        <xsl:apply-templates select=\"input|output\"/>\n    </pre>\n</xsl:template>\n\n<xsl:template match=\"console/input\">\n    <xsl:variable name=\"prompt\">\n        <xsl:apply-templates select=\".\" mode=\"determine-console-prompt\"/>\n    </xsl:variable>\n    <xsl:variable name=\"continuation\">\n        <xsl:apply-templates select=\".\" mode=\"determine-console-continuation\"/>\n    </xsl:variable>\n    <xsl:variable name=\"sanitized-text\">\n        <xsl:call-template name=\"sanitize-text\">\n            <xsl:with-param name=\"text\" select=\".\" />\n        </xsl:call-template>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$continuation = ''\">\n            <xsl:call-template name=\"input-line-with-prompt\">\n                <xsl:with-param name=\"text\" select=\"$sanitized-text\" />\n                <xsl:with-param name=\"prefix\" select=\"$prompt\" />\n            </xsl:call-template>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:for-each select=\"str:tokenize($sanitized-text, '&#xa;')\">\n                <xsl:choose>\n                    <xsl:when test=\"preceding-sibling::token\">\n                        <xsl:call-template name=\"input-line-with-prompt\">\n                            <xsl:with-param name=\"text\" select=\".\" />\n                            <xsl:with-param name=\"prefix\" select=\"$continuation\" />\n                        </xsl:call-template>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:call-template name=\"input-line-with-prompt\">\n                            <xsl:with-param name=\"text\" select=\".\" />\n                            <xsl:with-param name=\"prefix\" select=\"$prompt\" />\n                        </xsl:call-template>\n                    </xsl:otherwise>\n                </xsl:choose>\n                <xsl:text>&#xa;</xsl:text>\n            </xsl:for-each>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"console/output\">\n    <xsl:call-template name=\"sanitize-text\">\n        <xsl:with-param name=\"text\" select=\".\" />\n    </xsl:call-template>\n</xsl:template>\n\n\n<!-- ############ -->\n<!-- Interactives -->\n<!-- ############ -->\n\n<!-- Every interactive is an \"iframe\" - this allows us to confine      -->\n<!-- libraries, variables, and scripts to just where they are needed.  -->\n<!-- And we can \"sandbox\" an iframe.  Some simple interactives, coming -->\n<!-- from servers, are built to be iframes.  In other cases, we build  -->\n<!-- a super-minimal page to serve as the @src of an iframe.  For each -->\n<!-- \"interactive\", we also build a stand-alone page to serve as the   -->\n<!-- target of a live link in a static format (such as a QR code in a  -->\n<!-- LaTeX/PDF document).                                              -->\n<!--                                                                   -->\n<!-- PTX source may include a \"static\" element - we routinely ignore   -->\n<!-- for HTML output, as it is only employed in static output formats  -->\n<!-- https://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/ -->\n\n<!-- Three actions, all based on \"interactive-core\" template -->\n<xsl:template match=\"interactive\">\n    <xsl:param name=\"heading-level\"/>\n    <!-- (1) Build, display full content on the page, where born -->\n    <xsl:apply-templates select=\".\" mode=\"interactive-core\">\n        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n    </xsl:apply-templates>\n    <!-- (2) Identical content, but now isolated on a reader-friendly page -->\n    <!-- (we skip this for portable html)                                  -->\n    <xsl:if test=\"not($b-portable-html)\">\n        <xsl:apply-templates select=\".\" mode=\"standalone-page\" >\n            <xsl:with-param name=\"content\">\n                <xsl:apply-templates select=\".\" mode=\"interactive-core\">\n                    <xsl:with-param name=\"is-standalone\" select=\"true()\"/>\n                    <xsl:with-param name=\"heading-level\" select=\"1\"/>\n                </xsl:apply-templates>\n            </xsl:with-param>\n        </xsl:apply-templates>\n    </xsl:if>\n    <!-- (3) A simple page that can be used in an iframe construction -->\n    <!-- (portable html still needs these, since they contain the     -->\n    <!-- the content for the interactive                              -->\n    <xsl:apply-templates select=\".\" mode=\"create-iframe-page\" />\n</xsl:template>\n\n<!-- Following will generate:              -->\n<!--   1.  Instructions (paragraphs, etc)  -->\n<!--   2.  An iframe, via modal-template   -->\n<xsl:template match=\"interactive\" mode=\"interactive-core\">\n    <xsl:param name=\"is-standalone\" select=\"false()\"/>\n    <xsl:param name=\"heading-level\"/>\n    <!-- We want to recognize an \"interactive\" authored  -->\n     <!-- in an \"exercise\" (or similar) which originated -->\n     <!-- from a \"dual\" dynamic/static exercise.         -->\n    <xsl:variable name=\"b-in-dual-exercise\" select=\"ancestor::*[@pi:exercise-interactive = 'dual']\"/>\n    <xsl:choose>\n        <!-- A DoenetML interactive lives two lives.  Plain 'ol PreTeXt,  -->\n        <!-- supported by a Doenet CDN for its interactivity.  But when   -->\n        <!-- hosted on Runestone it can communicate its results.  So it   -->\n        <!-- needs surrounding infrastructure, in part to hold an id.     -->\n        <xsl:when test=\"(@platform = 'doenetml') and $b-host-runestone\">\n            <div class=\"ptx-runestone-container\">\n                <div data-component=\"doenet\">\n                    <xsl:attribute name=\"id\">\n                        <xsl:apply-templates select=\".\" mode=\"runestone-id\"/>\n                    </xsl:attribute>\n                    <xsl:apply-templates select=\".\" mode=\"iframe-interactive\"/>\n                </div>\n            </div>\n        </xsl:when>\n        <!-- In a SCORM package, DoenetML can also communicate its results     -->\n        <!-- via SPLICE postMessage.  We add data-component=\"doenet\" and an    -->\n        <!-- id so ptx_scorm_events.js can locate and grade the activity,      -->\n        <!-- but we omit the ptx-runestone-container wrapper (Runestone only). -->\n        <xsl:when test=\"(@platform = 'doenetml') and $b-host-scorm\">\n            <div data-component=\"doenet\">\n                <xsl:attribute name=\"id\">\n                    <xsl:apply-templates select=\".\" mode=\"runestone-id\"/>\n                </xsl:attribute>\n                <xsl:apply-templates select=\".\" mode=\"iframe-interactive\"/>\n            </div>\n        </xsl:when>\n        <!-- An iframe interactive lives two lives.  Plain 'ol PreTeXt. But  -->\n        <!-- when hosted on Runestone, and authored as the \"dynamic\" part of -->\n        <!-- a \"dual\" exercise it needs surrounding infrastructure, in part  -->\n        <!-- to hold an id.  SPLICE is the protocol for a generic iframe to  -->\n        <!-- communicate reader responses, plus save and restore state.      -->\n        <xsl:when test=\"@iframe and $b-in-dual-exercise and $b-host-runestone\">\n            <div class=\"ptx-runestone-container\">\n                <div data-component=\"splice\">\n                    <xsl:attribute name=\"id\">\n                        <xsl:apply-templates select=\".\" mode=\"runestone-id\"/>\n                    </xsl:attribute>\n                    <xsl:apply-templates select=\".\" mode=\"iframe-interactive\"/>\n                </div>\n            </div>\n        </xsl:when>\n        <!-- no more special situations for Runestone exercises -->\n        <xsl:otherwise>\n            <div class=\"interactive-iframe-container\">\n                <xsl:apply-templates select=\".\" mode=\"iframe-interactive\"/>\n            </div>\n            <xsl:variable name=\"resize-behavior\">\n                <xsl:apply-templates select=\".\" mode=\"get-resize-behavior\"/>\n            </xsl:variable>\n            <xsl:if test=\"$is-standalone = false()\">\n                <div class=\"interactive-iframe-container__opener\">\n                    <xsl:variable name=\"if-filename\">\n                        <xsl:apply-templates select=\".\" mode=\"standalone-filename\" />\n                    </xsl:variable>\n                    <xsl:variable name=\"label\">\n                        <xsl:apply-templates select=\".\" mode=\"type-name\">\n                            <xsl:with-param name=\"string-id\" select=\"'open-new-tab'\"/>\n                        </xsl:apply-templates>\n                    </xsl:variable>\n                    <a href=\"{$if-filename}\" title=\"{$label}\" aria-label=\"{$label}\" target=\"_blank\">\n                        <xsl:call-template name=\"insert-symbol\">\n                            <xsl:with-param name=\"name\" select=\"'open_in_new'\"/>\n                        </xsl:call-template>\n                    </a>\n                </div>\n            </xsl:if>\n        </xsl:otherwise>\n    </xsl:choose>\n    <!-- \"instructions\" next, *always* as a knowl -->\n    <!-- \"title\" is handled in knowl creation     -->\n    <!-- div.solutions is good, but replacable?   -->\n    <xsl:if test=\"instructions\">\n        <div class=\"instructions interactive__instructions\">\n            <xsl:apply-templates select=\"instructions\">\n                <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n            </xsl:apply-templates>\n        </div>\n    </xsl:if>\n</xsl:template>\n\n<!-- ################### -->\n<!-- iframe Interactives -->\n<!-- ################### -->\n\n<!-- Given by a small piece of information used -->\n<!-- to form the @src attribute of an \"iframe\"  -->\n<!-- An iframe has @width, @height attributes,  -->\n<!-- specified in pixels                        -->\n\n<!-- Check if author wants to dark mode to propagate into iframe   -->\n<!-- Propogation will only work for iframes on same server as page -->\n<xsl:template match=\"*\" mode=\"iframe-dark-mode-attribute\">\n    <xsl:if test=\"$b-theme-has-darkmode and @dark-mode-enabled\">\n        <xsl:attribute name=\"data-dark-mode-enabled\">true</xsl:attribute>\n    </xsl:if>\n</xsl:template>\n\n<!-- Desmos -->\n<!-- The simplest possible example of this type -->\n<xsl:template match=\"interactive[@desmos]\" mode=\"iframe-interactive\">\n    <iframe src=\"https://www.desmos.com/calculator/{@desmos}\">\n        <xsl:apply-templates select=\".\" mode=\"iframe-common-attributes\" />\n        <xsl:apply-templates select=\".\" mode=\"iframe-accessibility-attributes\"/>\n    </iframe>\n    <!-- possibly give a long description -->\n    <xsl:apply-templates select=\".\" mode=\"description\"/>\n</xsl:template>\n\n<!-- CalcPlot3D -->\n<!-- A bit more complicated, as the configuration   -->\n<!-- is a query string of a URL, and we can specify -->\n<!-- the style of the interface through @variant    -->\n<xsl:template match=\"interactive[@calcplot3d]\" mode=\"iframe-interactive\">\n    <!-- Use @variant to pick an endpoint/view/infrastructure. -->\n    <!-- The schema restricts @variant on \"interactive\" to one -->\n    <!-- of these three, so no defensive otherwise is needed.  -->\n    <xsl:variable name=\"cp3d-endpoint\">\n        <xsl:choose>\n            <xsl:when test=\"@variant='application'\">\n                <xsl:text>https://c3d.libretexts.org/CalcPlot3D/index.html</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"@variant='controls'\">\n                <xsl:text>https://c3d.libretexts.org/CalcPlot3D/dynamicFigureWCP/index.html</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"@variant='minimal'\">\n                <xsl:text>https://c3d.libretexts.org/CalcPlot3D/dynamicFigure/index.html</xsl:text>\n            </xsl:when>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- load 'em up and go -->\n    <!-- TODO: box-sizing, etc does not seem to help with vertical scroll bars -->\n    <xsl:variable name=\"full-url\" select=\"concat($cp3d-endpoint, '?', @calcplot3d)\" />\n    <iframe src=\"{$full-url}\">\n        <xsl:apply-templates select=\".\" mode=\"iframe-common-attributes\" />\n        <xsl:apply-templates select=\".\" mode=\"iframe-accessibility-attributes\"/>\n    </iframe>\n    <!-- possibly give a long description -->\n    <xsl:apply-templates select=\".\" mode=\"description\"/>\n</xsl:template>\n\n<!-- CircuitJS: https://www.falstad.com -->\n<!-- www.bait-consulting.com/publications/circuit_simulator_manual.pdf -->\n<xsl:template match=\"interactive[@circuitjs]\" mode=\"iframe-interactive\">\n    <!-- CircuitJS native language, as a URL-safe string -->\n    <xsl:variable name=\"url-string\">\n        <xsl:choose>\n            <!-- a prepared string is in the signaling attribute -->\n            <xsl:when test=\"normalize-space(@circuitjs)\">\n                <xsl:value-of select=\"@circuitjs\"/>\n            </xsl:when>\n            <!-- Else, a more-friendly version is in a \"source\" element -->\n            <!-- Note that when a \"source\" element is used, and then    -->\n            <!-- provided in iframe/@src, the XSL processing itself     -->\n            <!-- will do the necessary escaping to join lines, etc      -->\n            <!-- (such as newlines to \"%0A\" and spaces to \"%20\")        -->\n            <!-- So we just strip leading whitespace primarily          -->\n            <xsl:when test=\"source\">\n                <xsl:call-template name=\"sanitize-text\">\n                    <xsl:with-param  name=\"text\">\n                        <xsl:value-of select=\"source\"/>\n                    </xsl:with-param>\n                </xsl:call-template>\n            </xsl:when>\n            <!-- no code, empty string, still makes a nice widget -->\n            <xsl:otherwise/>\n        </xsl:choose>\n    </xsl:variable>\n    <iframe src=\"https://www.falstad.com/circuit/circuitjs.html?cct='{$url-string}'\">\n        <xsl:apply-templates select=\".\" mode=\"iframe-common-attributes\" />\n        <xsl:apply-templates select=\".\" mode=\"iframe-accessibility-attributes\"/>\n    </iframe>\n    <!-- possibly give a long description -->\n    <xsl:apply-templates select=\".\" mode=\"description\"/>\n</xsl:template>\n\n<!-- Arbitrary IFrame -->\n<!-- Almost too easy and trivial, so last, not first -->\n<!-- Assumes a local, \"external\", HTML file to house -->\n<xsl:template match=\"interactive[@iframe]\" mode=\"iframe-interactive\">\n    <!-- Distinguish netowk location versus (external) file -->\n    <xsl:variable name=\"b-network-location\" select=\"(substring(@iframe, 1, 7) = 'http://') or\n                                                    (substring(@iframe, 1, 8) = 'https://')\"/>\n\n    <xsl:variable name=\"location\">\n        <!-- prefix with directory information if not obviously a network location -->\n        <xsl:if test=\"not($b-network-location)\">\n            <!-- empty when not using managed directories -->\n            <xsl:value-of select=\"$external-directory\"/>\n        </xsl:if>\n        <xsl:value-of select=\"@iframe\"/>\n    </xsl:variable>\n    <iframe src=\"{$location}\">\n        <xsl:apply-templates select=\".\" mode=\"iframe-common-attributes\" />\n        <xsl:apply-templates select=\".\" mode=\"iframe-accessibility-attributes\"/>\n    </iframe>\n    <!-- possibly give a long description -->\n    <xsl:apply-templates select=\".\" mode=\"description\"/>\n</xsl:template>\n\n<!-- For more complicated interactives, we just point to the page we generate -->\n<xsl:template match=\"interactive[@platform]\" mode=\"iframe-interactive\">\n    <iframe>\n        <xsl:apply-templates select=\".\" mode=\"iframe-common-attributes\" />\n        <xsl:attribute name=\"src\">\n            <xsl:apply-templates select=\".\" mode=\"iframe-filename\" />\n        </xsl:attribute>\n        <xsl:apply-templates select=\".\" mode=\"iframe-accessibility-attributes\"/>\n    </iframe>\n    <!-- possibly give a long description -->\n    <xsl:apply-templates select=\".\" mode=\"description\"/>\n</xsl:template>\n\n<!-- Set the title attribute for accessibility purposes -->\n<!-- If there is a description but not a shortdescription, provide text and aria-describedby -->\n<xsl:template match=\"*\" mode=\"iframe-accessibility-attributes\">\n    <!-- title attribute for accessibility -->\n    <xsl:choose>\n        <xsl:when test=\"not(string(shortdescription) = '')\">\n            <xsl:attribute name=\"title\">\n                <xsl:apply-templates select=\"shortdescription\" />\n            </xsl:attribute>\n        </xsl:when>\n        <xsl:when test=\"description\">\n            <xsl:attribute name=\"title\">\n                <xsl:text>described in detail following the image</xsl:text>\n            </xsl:attribute>\n            <xsl:attribute name=\"aria-describedby\">\n                <xsl:apply-templates select=\".\" mode=\"describedby-id\"/>\n            </xsl:attribute>\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Attributes that are common to the iframe interactives -->\n<xsl:template match=\"*\" mode=\"iframe-common-attributes\">\n    <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n    <xsl:apply-templates select=\".\" mode=\"iframe-dark-mode-attribute\" />\n    <xsl:apply-templates select=\".\" mode=\"interactive-sizing-style-attribute\" />\n</xsl:template>\n\n<!-- ######################### -->\n<!-- Source File Interactives  -->\n<!-- ######################### -->\n\n<!-- Build a minimal page for iframe contents -->\n<!-- This version for @platform variant       -->\n<!--   MathJax for PTX delimiters             -->\n<!--   Platform specific libraries into head  -->\n<!--   Author-libraries after slate exist     -->\n<xsl:template match=\"interactive[@platform]\" mode=\"create-iframe-page\">\n    <xsl:variable name=\"if-filename\">\n        <xsl:apply-templates select=\".\" mode=\"iframe-filename\" />\n    </xsl:variable>\n    <exsl:document href=\"{$if-filename}\" method=\"html\" indent=\"yes\" encoding=\"UTF-8\" doctype-system=\"about:legacy-compat\">\n        <xsl:call-template name=\"converter-blurb-html-no-date\"/>\n        <html>\n            <xsl:call-template name=\"language-attributes\"/>\n            <head>\n                <!-- grab the contents every iframe gets -->\n                <xsl:copy-of select=\"$file-wrap-iframe-head-cache\"/>\n                <!-- now do anything that is or could be page-specific and comes after cache -->\n                <!-- and CSS for the entire interactive, into the head -->\n                <xsl:apply-templates select=\"@css\" />\n                <!-- load header libraries (for all \"slate\") -->\n                <xsl:apply-templates select=\".\" mode=\"header-libraries\" />\n            </head>\n                <!-- ignore MathJax signals everywhere, then enable selectively -->\n                <body class=\"ptx-content ignore-math\">\n                <!-- potential document-id per-page -->\n                <xsl:call-template name=\"document-id\"/>\n                <!-- React flag -->\n                <xsl:call-template name=\"react-in-use-flag\"/>\n                <!-- Some interactives use slates that are PreTeXt  -->\n                <!-- elements, hence could have math, hence need to -->\n                <!-- know globally available macros from the author -->\n                <xsl:apply-templates select=\".\" mode=\"latex-macros\"/>\n                <xsl:if test=\"slate|sidebyside|sbsgroup\">\n                    <div>\n                        <!-- aspect ratio will force the proper height for wrapper div                           -->\n                        <!-- don't want to mess with width as iframe has applied any % width and px is redundant -->\n                        <xsl:attribute name=\"style\">\n                            <xsl:text>aspect-ratio: </xsl:text>\n                            <xsl:apply-templates select=\".\" mode=\"get-aspect-ratio\"/>\n                            <xsl:text>;</xsl:text>\n                        </xsl:attribute>\n\n                        <!-- stack, else use a layout -->\n                        <xsl:apply-templates select=\"slate|sidebyside|sbsgroup\" />\n                    </div>\n                </xsl:if>\n                <!-- accumulate script tags *after* HTML elements -->\n                <xsl:apply-templates select=\"@source\" />\n                <!-- accumulate script elements *after* @source scripts -->\n                <xsl:apply-templates select=\"script\"/>\n            </body>\n        </html>\n    </exsl:document>\n</xsl:template>\n\n<!-- These forms *are* iframes, so we don't need to build their content -->\n<!-- NB: coordinate with \"embed-iframe-url\" in -common                  -->\n<xsl:template match=\"interactive[@desmos|@geogebra|@calcplot3d|@circuitjs|@iframe]\" mode=\"create-iframe-page\" />\n\n\n<!-- ################ -->\n<!-- Header Libraries -->\n<!-- ################ -->\n\n<!-- Specified by libraries through @platform attribute  -->\n<!-- or explicitly with @library, and with per-slate     -->\n<!-- @source files stored locally, these draw on \"slate\" -->\n<!-- elements having different @surface characteristics  -->\n\n<!-- Geogebra header libraries -->\n<xsl:template match=\"interactive[@platform = 'geogebra']\" mode=\"header-libraries\">\n    <script type=\"text/javascript\" src=\"https://cdn.geogebra.org/apps/deployggb.js\"></script>\n</xsl:template>\n\n<!-- Sage Interact header libraries -->\n<!-- \".sage-interact\" must match use in \"slate\" -->\n<xsl:template match=\"interactive[@platform = 'sage']\" mode=\"header-libraries\">\n    <script src=\"https://sagecell.sagemath.org/static/embedded_sagecell.js\"></script>\n    <script>\n        <xsl:text>sagecell.makeSagecell(</xsl:text>\n        <xsl:call-template name=\"json\">\n            <xsl:with-param name=\"content\">\n                <map xmlns=\"http://www.w3.org/2005/xpath-functions\">\n                    <string key=\"inputLocation\">.sage-interact</string>\n                    <boolean key=\"autoeval\">true</boolean>\n                    <array key=\"hide\">\n                        <string>editor</string>\n                        <string>evalButton</string>\n                        <string>permalink</string>\n                    </array>\n                </map>\n            </xsl:with-param>\n        </xsl:call-template>\n        <xsl:text>);&#xa;</xsl:text>\n    </script>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"https://sagecell.sagemath.org/static/sagecell_embed.css\" />\n</xsl:template>\n\n<!-- JSXGraph header libraries -->\n<xsl:template match=\"interactive[@platform = 'jsxgraph']\" mode=\"header-libraries\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"https://cdnjs.cloudflare.com/ajax/libs/jsxgraph/1.8.0/jsxgraph.css\" />\n    <script type=\"text/javascript\" src=\"https://cdnjs.cloudflare.com/ajax/libs/jsxgraph/1.8.0/jsxgraphcore.js\"></script>\n</xsl:template>\n\n<!-- D3.js header libraries -->\n<xsl:template match=\"interactive[@platform = 'd3']\" mode=\"header-libraries\">\n    <xsl:variable name=\"d3-library-url\">\n        <xsl:text>https://d3js.org/d3.v</xsl:text>\n        <!-- versions could be 3, 4, 5 -->\n        <xsl:choose>\n            <xsl:when test=\"@version\">\n                <xsl:value-of select=\"@version\" />\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>5</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n        <xsl:text>.min.js</xsl:text>\n    </xsl:variable>\n    <script src=\"{$d3-library-url}\"></script>\n</xsl:template>\n\n<!-- DoenetML header libraries -->\n<xsl:template match=\"interactive[@platform = 'doenetml']\" mode=\"header-libraries\">\n    <xsl:variable name=\"doenet-version\">\n        <xsl:choose>\n            <xsl:when test=\"@version\">\n                <xsl:value-of select=\"@version\"/>\n            </xsl:when>\n            <xsl:when test=\"$docinfo/doenetml/@version\">\n                <xsl:value-of select=\"$docinfo/doenetml/@version\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>latest</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"doenet-css-url\">\n        <xsl:text>https://cdn.jsdelivr.net/npm/@doenet/standalone@</xsl:text>\n        <xsl:value-of select=\"$doenet-version\"/>\n        <xsl:text>/style.css</xsl:text>\n    </xsl:variable>\n    <xsl:variable name=\"doenet-js-url\">\n        <xsl:text>https://cdn.jsdelivr.net/npm/@doenet/standalone@</xsl:text>\n        <xsl:value-of select=\"$doenet-version\"/>\n        <xsl:text>/doenet-standalone.js</xsl:text>\n    </xsl:variable>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"{$doenet-css-url}\" />\n    <script onload=\"onLoad()\" type=\"module\" src=\"{$doenet-js-url}\"></script>\n    <script>\n        <xsl:text>function onLoad() {window.renderDoenetViewerToContainer(document.querySelector(\".doenetml-applet\"))}</xsl:text>\n    </script>\n</xsl:template>\n\n<xsl:template match=\"image/mermaid\" mode=\"header-libraries\">\n    <xsl:call-template name=\"mermaid-header\"/>\n</xsl:template>\n\n<!-- Javascript header libraries (none) -->\n<xsl:template match=\"interactive[@platform = 'javascript']\" mode=\"header-libraries\" />\n\n<!-- ########################### -->\n<!-- Slates (objects to draw on) -->\n<!-- ########################### -->\n\n<!-- Slates are where we draw, with different surfaces -->\n\n<xsl:template match=\"slate[@surface='div']\">\n    <div>\n        <xsl:attribute name=\"id\">\n            <xsl:value-of select=\"@xml:id\" />\n        </xsl:attribute>\n        <!-- aspect ratio will force the proper height for wrapper div -->\n        <xsl:attribute name=\"style\">\n            <xsl:text>aspect-ratio: </xsl:text>\n            <xsl:apply-templates select=\".\" mode=\"get-aspect-ratio\"/>\n            <xsl:text>;</xsl:text>\n        </xsl:attribute>\n        <xsl:apply-templates select=\".\" mode=\"interactive-slate-sizing-style-attributes\" />\n    </div>\n</xsl:template>\n\n<xsl:template match=\"slate[@surface = 'pretext']\">\n    <div class=\"slate-ptx\">\n        <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n        <!-- Perhaps more children make sense?  A 1-panel \"sidebyside\" -->\n        <!-- does allow for a wider range of children.                 -->\n        <xsl:apply-templates select=\"p|tabular|sidebyside|sbsgroup\"/>\n    </div>\n</xsl:template>\n\n<xsl:template match=\"slate[@surface='svg']\">\n    <svg>\n        <xsl:attribute name=\"id\">\n            <xsl:value-of select=\"@xml:id\" />\n        </xsl:attribute>\n        <xsl:apply-templates select=\".\" mode=\"interactive-slate-sizing-style-attributes\" />\n    </svg>\n</xsl:template>\n\n<xsl:template match=\"slate[@surface = 'canvas']\">\n    <canvas>\n        <xsl:attribute name=\"id\">\n            <xsl:value-of select=\"@xml:id\" />\n        </xsl:attribute>\n        <xsl:apply-templates select=\".\" mode=\"interactive-slate-sizing-style-attributes\" />\n    </canvas>\n</xsl:template>\n\n<!-- HTML Code                                                  -->\n<!-- TODO: should this be a div, with width and height?         -->\n<!-- Authored HTML goes into the page, which is the content's   -->\n<!-- only destination, and an HTML parser has no notion of      -->\n<!-- namespaces.  So the copy keeps just the local name of each -->\n<!-- element: an author declares the XHTML namespace once (say, -->\n<!-- a prefix on the \"slate\") to satisfy validation, and the    -->\n<!-- output carries plain HTML tags with no declarations at     -->\n<!-- all.  (This utility may serve other embedded-markup        -->\n<!-- copying; nothing about it is specific to a \"slate\".)       -->\n<xsl:template match=\"slate[@surface = 'html']\">\n    <xsl:apply-templates select=\"*\" mode=\"copy-authored-xml\"/>\n</xsl:template>\n\n<!-- Attributes in the internal namespace are the assembly's     -->\n<!-- identification stamps, not the author's work, so they stay  -->\n<!-- out of the copy.                                            -->\n<xsl:template match=\"*\" mode=\"copy-authored-xml\">\n    <xsl:element name=\"{local-name()}\">\n        <xsl:copy-of select=\"@*[namespace-uri(.) != 'http://pretextbook.org/2020/pretext/internal']\"/>\n        <xsl:apply-templates select=\"node()\" mode=\"copy-authored-xml\"/>\n    </xsl:element>\n</xsl:template>\n\n<xsl:template match=\"text()|comment()|processing-instruction()\" mode=\"copy-authored-xml\">\n    <xsl:copy/>\n</xsl:template>\n\n<!-- Similar to the \"div\" surface, but with class information -->\n<xsl:template match=\"slate[@surface = 'jsxboard']\">\n    <div>\n        <xsl:attribute name=\"id\">\n            <xsl:value-of select=\"@xml:id\" />\n        </xsl:attribute>\n        <xsl:attribute name=\"class\">\n            <xsl:text>jxgbox process-math</xsl:text>\n        </xsl:attribute>\n        <xsl:apply-templates select=\".\" mode=\"size-pixels-style-attribute\" />\n    </div>\n</xsl:template>\n\n<!-- Sage Cell Server will execute an interact, when     -->\n<!-- properly bundled up with the right HTML markup      -->\n<!-- \".sage-interact\" must match use in \"header-library\" -->\n<xsl:template match=\"slate[@surface = 'sage']\">\n    <!-- \".ptx-sagecell\" for CSS (and not simply .sagecell). -->\n    <!-- See https://github.com/sagemath/sagecell/issues/542 -->\n    <pre class=\"ptx-sagecell sage-interact\">\n      <script type=\"text/x-sage\">\n        <xsl:call-template name=\"sanitize-text\">\n            <xsl:with-param name=\"text\" select=\".\" />\n        </xsl:call-template>\n      </script>\n    </pre>\n</xsl:template>\n\n<xsl:template match=\"slate[@surface='geogebra']\">\n    <!-- size of the window, to be passed as a parameter -->\n    <xsl:variable name=\"width\">\n        <xsl:apply-templates select=\".\" mode=\"get-width-pixels\" />\n    </xsl:variable>\n    <xsl:variable name=\"height\">\n        <xsl:apply-templates select=\".\" mode=\"get-height-pixels\" />\n    </xsl:variable>\n    <xsl:variable name=\"material-width\">\n        <xsl:choose>\n            <xsl:when test=\"@material-width\">\n                <xsl:value-of select=\"@material-width\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$width\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"material-height\">\n        <xsl:choose>\n            <xsl:when test=\"@material-height\">\n                <xsl:value-of select=\"@material-height\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$height\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- We need a Javascript identifier to name the applet.      -->\n    <!-- Other variables will use this as their root.  Need to    -->\n    <!-- ensure identifier does not lead with a digit, so \"ggb_\". -->\n    <xsl:variable name=\"applet-name\">\n        <xsl:text>ggb_</xsl:text>\n        <xsl:apply-templates select=\".\" mode=\"unique-id-no-dash\" />\n    </xsl:variable>\n    <!-- And a Javascript identifier for the parameters -->\n    <xsl:variable name=\"applet-parameters\">\n        <xsl:value-of select=\"$applet-name\"/>\n        <xsl:text>_params</xsl:text>\n    </xsl:variable>\n    <!-- And a Javascript identifier for the onload function -->\n    <xsl:variable name=\"applet-onload\">\n        <xsl:value-of select=\"$applet-name\"/>\n        <xsl:text>_onload</xsl:text>\n    </xsl:variable>\n    <!-- And a Javascript identifier for the onload function argument -->\n    <!-- not strictly necessary, but clarifies HTML                   -->\n    <xsl:variable name=\"applet-onload-argument\">\n        <xsl:value-of select=\"$applet-name\"/>\n        <xsl:text>_applet</xsl:text>\n    </xsl:variable>\n    <!-- And an HTML unique identifier -->\n    <xsl:variable name=\"applet-container\">\n        <xsl:apply-templates select=\".\" mode=\"unique-id\" />\n        <xsl:text>-container</xsl:text>\n    </xsl:variable>\n    <!-- Javascript API for loading GeoGebra                               -->\n    <script>\n        <!-- API commands, as text() nodes in the slate. Manual at:   -->\n        <!-- https://wiki.geogebra.org/en/Reference:GeoGebra_Apps_API -->\n        <!-- In PTX source, use the commands one per line, as in:     -->\n        <!-- setCoordSystem(0, 20, 0, 10);                            -->\n        <!-- enableShiftDragZoom(false);                              -->\n        <xsl:if test=\"normalize-space(text())\">\n            <xsl:text>var </xsl:text>\n            <xsl:value-of select=\"$applet-onload\" />\n            <xsl:text> = function(</xsl:text>\n            <xsl:value-of select=\"$applet-onload-argument\" />\n            <xsl:text>) {&#xa;</xsl:text>\n            <xsl:call-template name=\"prepend-string\">\n                <xsl:with-param name=\"text\">\n                    <xsl:call-template name=\"sanitize-text\">\n                        <xsl:with-param name=\"text\" select=\".\" />\n                    </xsl:call-template>\n                </xsl:with-param>\n                <!-- period below is Javascript syntax for methods -->\n                <xsl:with-param name=\"pad\" select=\"concat($applet-onload-argument,'.')\" />\n            </xsl:call-template>\n            <!-- call a function named 'listeners()' in attached .js file to communicate with other divs -->\n            <xsl:text>listeners(</xsl:text><xsl:value-of select='$applet-onload-argument'/><xsl:text>)</xsl:text>\n            <xsl:text>};&#xa;</xsl:text>\n        </xsl:if>\n        <!-- Parameter reference:                                              -->\n        <!-- https://wiki.geogebra.org/en/Reference:GeoGebra_App_Parameters    -->\n        <!-- We leave most parameters as their default value. In most cases,   -->\n        <!-- an author could use API commands to alter these settings.         -->\n        <xsl:text>var </xsl:text>\n        <xsl:value-of select=\"$applet-parameters\" />\n        <xsl:text> = {&#xa;</xsl:text>\n        <!-- Prioritize local over remote -->\n        <xsl:choose>\n            <xsl:when test=\"@base64\">\n                <xsl:text>ggbBase64:\"</xsl:text>\n                <xsl:value-of select=\"@base64\" />\n                <xsl:text>\",&#xa;</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"@source\">\n                <xsl:text>filename:\"</xsl:text>\n                <!-- empty when not using managed directories -->\n                <xsl:value-of select=\"$external-directory\"/>\n                <xsl:value-of select=\"@source\" />\n                <xsl:text>\",&#xa;</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"@material\">\n                <xsl:text>material_id:\"</xsl:text>\n                <xsl:value-of select=\"@material\" />\n                <xsl:text>\",&#xa;</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"@geogebra\">\n                <xsl:message>PTX:DEPRECATE: \"geogebra\" attribute on \"slate\" element is deprecated; use \"material\" attribute</xsl:message>\n                <xsl:text>material_id:\"</xsl:text>\n                <xsl:value-of select=\"@geogebra\" />\n                <xsl:text>\",&#xa;</xsl:text>\n            </xsl:when>\n            <xsl:otherwise/>\n        </xsl:choose>\n        <!-- Perspective must be authored in source, so we can check -->\n        <!-- setting perspective via an attribute.  This bypasses a  -->\n        <!-- bug where using \"setPerspective()\" in source caused the -->\n        <!-- focus to be grabbed here.                               -->\n        <xsl:if test=\"@perspective\">\n            <xsl:text>perspective:\"</xsl:text>\n            <xsl:value-of select=\"@perspective\"/>\n            <xsl:text>\",&#xa;</xsl:text>\n        </xsl:if>\n        <xsl:if test=\"@toolbar\">\n            <xsl:text>showToolBar: </xsl:text>\n            <xsl:choose>\n                <xsl:when test=\"@toolbar='yes'\">\n                    <xsl:text>true</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:text>false</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n            <xsl:text>,&#xa;</xsl:text>\n        </xsl:if>\n        <xsl:if test=\"@algebra-input\">\n            <xsl:text>showAlgebraInput: </xsl:text>\n            <xsl:choose>\n                <xsl:when test=\"@algebra-input='yes'\">\n                    <xsl:text>true</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:text>false</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n            <xsl:text>,&#xa;</xsl:text>\n        </xsl:if>\n        <xsl:if test=\"@reset-icon\">\n            <xsl:text>showResetIcon: </xsl:text>\n            <xsl:choose>\n                <xsl:when test=\"@reset-icon='yes'\">\n                    <xsl:text>true</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:text>false</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n            <xsl:text>,&#xa;</xsl:text>\n        </xsl:if>\n        <xsl:if test=\"@shift-drag-zoom\">\n            <xsl:text>enableShiftDragZoom: </xsl:text>\n            <xsl:choose>\n                <xsl:when test=\"@shift-drag-zoom='yes'\">\n                    <xsl:text>true</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:text>false</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n            <xsl:text>,&#xa;</xsl:text>\n        </xsl:if>\n        <xsl:if test=\"@zoom-buttons\">\n            <xsl:text>showZoomButtons: </xsl:text>\n            <xsl:choose>\n                <xsl:when test=\"@zoom-buttons='yes'\">\n                    <xsl:text>true</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:text>false</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n            <xsl:text>,&#xa;</xsl:text>\n        </xsl:if>\n        <xsl:text>width:</xsl:text><xsl:value-of select=\"$material-width\" />\n        <xsl:text>,&#xa;</xsl:text>\n        <xsl:text>height:</xsl:text><xsl:value-of select=\"$material-height\" />\n        <xsl:text>,&#xa;</xsl:text>\n        <xsl:if test=\"normalize-space(text())\">\n            <xsl:text>appletOnLoad:</xsl:text>\n            <xsl:value-of select=\"$applet-onload\" />\n        </xsl:if>\n        <xsl:text>};&#xa;</xsl:text>\n\n        <xsl:text>new Promise((resolve, reject) => {&#xa;</xsl:text>\n        <xsl:text>var </xsl:text>\n            <xsl:value-of select=\"$applet-name\" />\n        <xsl:text> = new GGBApplet(</xsl:text>\n            <xsl:value-of select=\"$applet-parameters\" />\n        <xsl:text>, true);&#xa;</xsl:text>\n\n      <xsl:text>resolve(</xsl:text><xsl:value-of select=\"$applet-name\" /><xsl:text>);})&#xa;</xsl:text>\n      <xsl:text>.then((</xsl:text><xsl:value-of select=\"$applet-name\" /><xsl:text>) => {&#xa;</xsl:text>\n        <!-- inject the applet into the div below -->\n        <xsl:text>window.onload = function() { </xsl:text>\n        <xsl:value-of select=\"$applet-name\" />\n        <xsl:text>.inject('</xsl:text>\n        <xsl:value-of select=\"$applet-container\" />\n        <xsl:text>'); }&#xa;</xsl:text>\n        <xsl:text>},&#xa;</xsl:text>\n        <xsl:text>(error) => {console.log('GGB applet load failure.', error)});&#xa;</xsl:text>\n    </script>\n    <!-- Force line-height 0 to prevent scroll bars -->\n    <div style=\"line-height: 0;\">\n        <!-- build a container div with the right shape -->\n        <div class=\"geogebra-applet\" id=\"{$applet-container}\">\n            <xsl:apply-templates select=\".\" mode=\"size-pixels-style-attribute\" />\n        </div>\n    </div>\n</xsl:template>\n\n<xsl:template match=\"slate[@surface = 'jessiecode']\">\n  <!-- size of the window, to be passed as a parameter -->\n  <xsl:variable name=\"width\">\n      <xsl:apply-templates select=\".\" mode=\"get-width-pixels\" />\n  </xsl:variable>\n  <xsl:variable name=\"height\">\n      <xsl:apply-templates select=\".\" mode=\"get-height-pixels\" />\n  </xsl:variable>\n  <!-- the div that jsxgraph will take over -->\n  <xsl:element name=\"div\">\n      <xsl:attribute name=\"id\">\n          <xsl:apply-templates select=\".\" mode=\"unique-id\" />\n      </xsl:attribute>\n      <xsl:attribute name=\"class\">\n          <xsl:text>jxgbox</xsl:text>\n      </xsl:attribute>\n      <xsl:apply-templates select=\".\" mode=\"size-pixels-style-attribute\" />\n  </xsl:element>\n  <!-- Add a script wrapper to parse using JSXGraph -->\n  <xsl:choose>\n      <xsl:when test=\"text()\">\n          <xsl:element name=\"script\">\n              <xsl:attribute name=\"type\">\n                  <xsl:text>text/jessiecode</xsl:text>\n              </xsl:attribute>\n              <!-- Put the board in the appropriate container. -->\n              <xsl:attribute name=\"container\">\n                  <xsl:apply-templates select=\".\" mode=\"unique-id\" />\n              </xsl:attribute>\n              <xsl:if test=\"@boundingbox\">\n                  <xsl:attribute name=\"boundingbox\">\n                      <xsl:value-of select=\"@boundingbox\" />\n                  </xsl:attribute>\n              </xsl:if>\n              <xsl:if test=\"@axis\">\n                  <xsl:attribute name=\"axis\">\n                      <xsl:value-of select=\"@axis\" />\n                  </xsl:attribute>\n              </xsl:if>\n              <xsl:if test=\"@grid\">\n                  <xsl:attribute name=\"grid\">\n                      <xsl:value-of select=\"@grid\" />\n                  </xsl:attribute>\n              </xsl:if>\n              <!-- Add the script -->\n              <xsl:call-template name=\"sanitize-text\">\n                  <xsl:with-param name=\"text\" select=\".\" />\n              </xsl:call-template>\n          </xsl:element>\n      </xsl:when>\n      <xsl:when test=\"@source\">\n          <xsl:element name=\"script\">\n              <xsl:attribute name=\"type\">\n                  <xsl:text>text/javascript</xsl:text>\n              </xsl:attribute>\n              <xsl:text>function parseJessie(code) {&#xa;</xsl:text>\n              <xsl:text>  let board = JXG.JSXGraph.initBoard('</xsl:text>\n              <xsl:apply-templates select=\".\" mode=\"unique-id\" />\n              <xsl:text>', {</xsl:text>\n              <xsl:if test=\"@boundingbox\">\n                  <xsl:text>boundingbox:[</xsl:text>\n                  <xsl:value-of select=\"@boundingbox\" />\n                  <xsl:text>], </xsl:text>\n              </xsl:if>\n              <xsl:if test=\"@axis\">\n                  <xsl:text>axis:</xsl:text>\n                  <xsl:value-of select=\"@axis\" />\n                  <xsl:text>, </xsl:text>\n              </xsl:if>\n              <xsl:if test=\"@grid\">\n                  <xsl:text>grid:</xsl:text>\n                  <xsl:value-of select=\"@grid\" />\n                  <xsl:text>, </xsl:text>\n              </xsl:if>\n              <xsl:text>keepaspectratio:true});&#xa;</xsl:text>\n              <xsl:text>  board.jc = new JXG.JessieCode();&#xa;</xsl:text>\n              <xsl:text>  board.jc.use(board);&#xa;</xsl:text>\n              <xsl:text>  board.suspendUpdate();&#xa;</xsl:text>\n              <xsl:text>  board.jc.parse(code);&#xa;</xsl:text>\n              <xsl:text>  board.unsuspendUpdate();&#xa;</xsl:text>\n              <xsl:text>}&#xa;</xsl:text>\n              <xsl:text>fetch('</xsl:text>\n              <!-- empty when not using managed directories -->\n              <xsl:value-of select=\"$external-directory\"/>\n              <xsl:value-of select=\"@source\" />\n              <xsl:text>').then(function(response) { response.text().then( function(text) { parseJessie(text); }); });&#xa;</xsl:text>\n          </xsl:element>\n      </xsl:when>\n  </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"slate[@surface = 'doenetml']\">\n    <div class=\"doenetml-applet\" data-doenet-add-virtual-keyboard=\"false\" data-doenet-send-resize-events=\"true\">\n        <!-- on Runestone and SCORM builds, enable SPLICE messaging to the parent -->\n        <xsl:if test=\"$b-host-runestone or $b-host-scorm\">\n            <xsl:attribute name=\"data-doenet-message-parent\">\n                <xsl:text>true</xsl:text>\n            </xsl:attribute>\n        </xsl:if>\n        <div class=\"doenetml-loading\" style=\"text-align:center\">\n            <p><img src=\"https://www.doenet.org/Doenet_Logo_Frontpage.png\"/></p>\n            <p><xsl:text>Waiting on the page to load...</xsl:text></p>\n        </div>\n        <script type=\"text/doenetml\">\n            <xsl:value-of select=\"text()\"/>\n        </script>\n    </div>\n</xsl:template>\n\n<!-- Utilities -->\n\n<!-- These can be vastly improved with a call to \"tokenize()\"   -->\n<!-- and then a \"for-each\" can effectively loop over the pieces -->\n\n<!-- @source attribute to multiple script tags -->\n<xsl:template match=\"interactive[@platform]/@source\">\n    <xsl:variable name=\"scripts\" select=\"str:tokenize(., ', ')\"/>\n    <!-- $scripts is a collection of \"token\" and does not have -->\n    <!-- a root, which implies the form of the \"for-each\"      -->\n    <xsl:for-each select=\"$scripts\">\n        <!-- create a script tag for each JS file -->\n        <script>\n            <!-- this is a hack to allow for local files and network resources,   -->\n            <!-- with or without managed directories.  There should be a separate -->\n            <!-- attribute like an @href used for audio and video, and then any   -->\n            <!-- \"http\"-leading string should be flagged as a deprecation         -->\n            <xsl:variable name=\"location\">\n                <xsl:variable name=\"raw-location\">\n                    <xsl:value-of select=\".\"/>\n                </xsl:variable>\n                <xsl:choose>\n                    <xsl:when test=\"substring($raw-location,1,4) = 'http'\">\n                        <xsl:value-of select=\"$raw-location\"/>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:value-of select=\"$external-directory\"/>\n                        <xsl:value-of select=\"$raw-location\"/>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:variable>\n            <xsl:attribute name=\"src\">\n                <xsl:value-of select=\"$location\" />\n            </xsl:attribute>\n        </script>\n    </xsl:for-each>\n</xsl:template>\n\n<!-- @css attribute to multiple \"link\" element -->\n<xsl:template match=\"interactive[@platform]/@css\">\n    <xsl:variable name=\"csses\" select=\"str:tokenize(., ', ')\"/>\n    <!-- $scripts is a collection of \"token\" and does not have -->\n    <!-- a root, which implies the form of the \"for-each\"      -->\n    <xsl:for-each select=\"$csses\">\n        <link rel=\"stylesheet\" type=\"text/css\">\n            <!-- This is a hack to allow for local files and network -->\n            <!-- resources, with or without managed directories.     -->\n            <xsl:variable name=\"location\">\n                <xsl:variable name=\"raw-location\">\n                    <xsl:value-of select=\".\"/>\n                </xsl:variable>\n                <xsl:choose>\n                    <xsl:when test=\"substring($raw-location,1,4) = 'http'\">\n                        <xsl:value-of select=\"$raw-location\"/>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:value-of select=\"$external-directory\"/>\n                        <xsl:value-of select=\"$raw-location\"/>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:variable>\n            <xsl:attribute name=\"href\">\n                <xsl:value-of select=\"$location\" />\n            </xsl:attribute>\n        </link>\n    </xsl:for-each>\n</xsl:template>\n\n<!-- Sizing styles for interactives                                       -->\n<!-- Two major modes based on how to resize: responsive or fixed-height   -->\n<!-- fixed-height applies aspect ratio at build as css height             -->\n<!-- responsive dynamically applies aspect ratio via css                  -->\n\n<xsl:template name=\"responsive-height-style-rules\">\n    <!-- max-width should already have px or % -->\n    <xsl:param name=\"max-width\"/>\n    <xsl:param name=\"aspect-ratio\"/>\n    <xsl:text>max-width: </xsl:text>\n    <xsl:value-of select=\"$max-width\"/>\n    <xsl:text>; </xsl:text>\n    <xsl:text>width: 100%; </xsl:text>\n    <xsl:text>aspect-ratio:</xsl:text>\n    <xsl:value-of select=\"$aspect-ratio\"/>\n</xsl:template> \n\n<xsl:template match=\"interactive\" mode=\"interactive-sizing-style-attribute\">\n    <xsl:param name=\"default-aspect\" select=\"'1:1'\" />\n    <xsl:variable name=\"resize-behavior\">\n        <xsl:apply-templates select=\".\" mode=\"get-resize-behavior\"/>\n    </xsl:variable>\n    <!-- tag wide interactives with some data attributes that styling/js can use -->\n    <xsl:if test=\"@design-width != ''\">\n        <xsl:attribute name=\"data-design-width\">\n            <xsl:value-of select=\"@design-width\"/>\n        </xsl:attribute>\n        <!-- css can't easily test numerics, so provide hint this content is wide -->\n        <xsl:if test=\"@design-width > $html-design-width\">\n            <xsl:attribute name=\"data-design-width-wide\"/>\n        </xsl:if>\n    </xsl:if>\n    <xsl:choose>\n        <xsl:when test=\"$resize-behavior = 'responsive'\">\n            <xsl:attribute name=\"style\">\n                <xsl:variable name=\"max-width\">\n                    <xsl:choose>\n                        <xsl:when test=\"@design-width != ''\">\n                            <xsl:value-of select=\"@design-width\"/>\n                            <xsl:text>px</xsl:text>\n                        </xsl:when>\n                        <xsl:otherwise>\n                            <xsl:apply-templates select=\".\" mode=\"get-width-percentage\"/>\n                        </xsl:otherwise>\n                    </xsl:choose>\n                </xsl:variable>\n                <xsl:variable name=\"aspect-ratio\">\n                    <xsl:apply-templates select=\".\" mode=\"get-aspect-ratio\">\n                        <xsl:with-param name=\"default-aspect\" select=\"'1:1'\" />\n                    </xsl:apply-templates>\n                </xsl:variable>\n                <xsl:text>max-width: </xsl:text>\n                <xsl:value-of select=\"$max-width\"/>\n                <xsl:text>; </xsl:text>\n                <xsl:text>width: 100%; </xsl:text>\n                <xsl:text>aspect-ratio:</xsl:text>\n                <xsl:value-of select=\"$aspect-ratio\"/>\n            </xsl:attribute>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- resize-behavior: fixed-height -->\n            <xsl:apply-templates select=\".\" mode=\"size-pixels-style-attribute\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Existing -common template handles if we have slate@aspect. But if attr -->\n<!-- is missing, look to parent interactive for an aspect and use that      -->\n<xsl:template match=\"slate[not(@aspect)]\" mode=\"get-aspect-ratio\">\n    <xsl:param name=\"default-aspect\" select=\"'1:1'\"/>\n    <xsl:apply-templates select=\"ancestor::interactive\" mode=\"get-aspect-ratio\">\n        <xsl:with-param name=\"default-aspect\" select=\"$default-aspect\" />\n    </xsl:apply-templates>\n</xsl:template>\n\n<xsl:template match=\"slate\" mode=\"interactive-slate-sizing-style-attributes\">\n    <xsl:variable name=\"resize-behavior\">\n        <xsl:apply-templates select=\"ancestor::interactive\" mode=\"get-resize-behavior\"/>\n    </xsl:variable>\n    <xsl:variable name=\"aspect-ratio\">\n        <xsl:apply-templates select=\".\" mode=\"get-aspect-ratio\">\n            <xsl:with-param name=\"default-aspect\" select=\"'1:1'\" />\n        </xsl:apply-templates>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$resize-behavior = 'responsive'\">\n            <xsl:attribute name=\"style\">\n                <!-- size is already constrained by interactive... only need max here -->\n                <!-- if there is a specific design width                              -->\n                <xsl:if test=\"@design-width != ''\">\n                    <xsl:text>max-width: </xsl:text>\n                    <xsl:value-of select=\"@design-width\"/>\n                    <xsl:text>px; </xsl:text>\n                </xsl:if>\n                <xsl:text>width: 100%; </xsl:text>\n                <xsl:text>aspect-ratio:</xsl:text>\n                <xsl:value-of select=\"$aspect-ratio\"/>\n                <xsl:text>;</xsl:text>\n            </xsl:attribute>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- fixed height -->\n            <xsl:attribute name=\"style\">\n                <xsl:apply-templates select=\".\" mode=\"size-pixels-style-attribute-core\"/>\n                <!-- May or may not need aspect ratio. Usually height overrides    -->\n                <!-- but can help for elements that are in a flex layout container -->\n                <xsl:text>aspect-ratio:</xsl:text>\n                <xsl:value-of select=\"$aspect-ratio\"/>\n                <xsl:text>;</xsl:text>\n            </xsl:attribute>\n            <!-- may or may not need width/height attributes, but won't hurt if not needed-->\n            <xsl:apply-templates select=\".\" mode=\"size-pixels-attributes\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"interactive\" mode=\"get-design-width\">\n    <xsl:choose>\n        <xsl:when test=\"@design-width != ''\">\n            <xsl:value-of select=\"@design-width\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- global value set by stylesheet -->\n            <xsl:value-of select=\"$design-width\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"slate\" mode=\"get-design-width\">\n    <xsl:choose>\n        <xsl:when test=\"@design-width != ''\">\n            <xsl:value-of select=\"@design-width\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\"ancestor::interactive\" mode=\"get-design-width\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"interactive\" mode=\"get-resize-behavior\">\n    <xsl:variable name=\"platform\" select=\"@pi:interactive-platform\"/>\n    <xsl:choose>\n        <xsl:when test=\"@resize-behavior != ''\">\n            <xsl:value-of select=\"@resize-behavior\"/>\n        </xsl:when>\n        <xsl:when test=\"$publication/html/interactives/*[local-name()=$platform and @resize-behavior != '']\">\n            <xsl:apply-templates select=\"$publisher-attribute-options/html/interactives/*[local-name()=$platform]/pi:pub-attribute[@name='resize-behavior']\" mode=\"set-pubfile-variable\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\"$publisher-attribute-options/html/interactives/pi:pub-attribute[@name='resize-behavior']\" mode=\"set-pubfile-variable\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"slate\" mode=\"get-resize-behavior\">\n    <xsl:choose>\n        <xsl:when test=\"@resize-behavior != ''\">\n            <xsl:value-of select=\"@resize-behavior\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:variable name=\"container\" select=\"ancestor::interactive\"/>\n            <xsl:apply-templates select=\"$container\" mode=\"get-resize-behavior\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Next two utilities write attributes, so cannot go in -common -->\n\n<!-- iframes, etc, need size as a pair of attributes in pixels -->\n<xsl:template match=\"*\" mode=\"size-pixels-attributes\">\n    <xsl:attribute name=\"width\">\n        <xsl:apply-templates select=\".\" mode=\"get-width-pixels\" />\n    </xsl:attribute>\n    <xsl:attribute name=\"height\">\n        <xsl:apply-templates select=\".\" mode=\"get-height-pixels\" />\n    </xsl:attribute>\n</xsl:template>\n\n<!-- various elements need size in a style attribute -->\n<xsl:template match=\"*\" mode=\"size-pixels-style-attribute\">\n    <xsl:attribute name=\"style\">\n        <xsl:apply-templates select=\".\" mode=\"size-pixels-style-attribute-core\" />\n    </xsl:attribute>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"size-pixels-style-attribute-core\">\n    <xsl:variable name=\"width\">\n        <xsl:apply-templates select=\".\" mode=\"get-width-pixels\" />\n    </xsl:variable>\n    <xsl:variable name=\"height\">\n        <xsl:apply-templates select=\".\" mode=\"get-height-pixels\" />\n    </xsl:variable>\n    <xsl:text>width:</xsl:text>\n    <xsl:value-of select=\"$width\" />\n    <xsl:text>px; </xsl:text>\n    <xsl:text>height:</xsl:text>\n    <xsl:value-of select=\"$height\" />\n    <xsl:text>px; </xsl:text>\n    <xsl:text>display: block; </xsl:text>\n</xsl:template>\n\n<!-- Add js from script elemenets inside interactives     -->\n<!-- Scripts are added in order, after all other elements -->\n<!-- in the interactive, include scripts created from     -->\n<!-- @source directives in the interactive element        -->\n<xsl:template match=\"interactive[@platform = 'javascript']/script\">\n    <script>\n        <!-- ECMAScript modules need type=\"module\" on the script -->\n        <xsl:if test=\"@type\">\n          <xsl:attribute name=\"type\">\n            <xsl:value-of select=\"@type\"/>\n          </xsl:attribute>\n        </xsl:if>\n        <xsl:value-of select=\".\"/>\n    </script>\n</xsl:template>\n\n<!-- JSXGraph -->\n<!-- DEPRECATED (2018-04-06)                             -->\n<!-- Restrict edits to cosmetic, no functional change    -->\n<!-- Remove when continued maintenance becomes untenable -->\n<xsl:template match=\"jsxgraph\">\n    <!-- interpret @width percentage and @aspect ratio -->\n    <xsl:variable name=\"width-percent\">\n        <xsl:apply-templates select=\".\" mode=\"get-width-percentage\" />\n    </xsl:variable>\n    <xsl:variable name=\"width-fraction\">\n        <xsl:value-of select=\"substring-before($width-percent,'%') div 100\" />\n    </xsl:variable>\n    <xsl:variable name=\"aspect-ratio\">\n        <xsl:apply-templates select=\".\" mode=\"get-aspect-ratio\">\n            <xsl:with-param name=\"default-aspect\" select=\"'1:1'\" />\n        </xsl:apply-templates>\n    </xsl:variable>\n    <!-- these are now standardized templates -->\n    <xsl:variable name=\"width\"  select=\"$design-width * $width-fraction\" />\n    <xsl:variable name=\"height\" select=\"$design-width * $width-fraction div $aspect-ratio\" />\n    <!-- the div to hold the JSX output -->\n    <xsl:element name=\"div\">\n        <xsl:attribute name=\"id\">\n            <xsl:apply-templates select=\".\" mode=\"unique-id\" />\n        </xsl:attribute>\n        <xsl:attribute name=\"class\">\n            <xsl:text>jxgbox</xsl:text>\n        </xsl:attribute>\n        <xsl:attribute name=\"style\">\n            <xsl:text>width:</xsl:text>\n            <xsl:value-of select=\"$width\" />\n            <xsl:text>px; height:</xsl:text>\n            <xsl:value-of select=\"$height\" />\n            <xsl:text>px;</xsl:text>\n        </xsl:attribute>\n    </xsl:element>\n    <!-- the script to hold the code                       -->\n    <!-- JSXGraph code must reference the id on the div,   -->\n    <!-- so ideally an xml:id specifies this in the source -->\n    <xsl:element name=\"script\">\n        <xsl:call-template name=\"sanitize-text\">\n            <xsl:with-param name=\"text\" select=\"input\" />\n        </xsl:call-template>\n    </xsl:element>\n    <xsl:copy-of select=\"controls\" />\n</xsl:template>\n\n<!-- ########################## -->\n<!-- WeBWorK Embedded Exercises -->\n<!-- ########################## -->\n\n<!-- WeBWorK Javascript header -->\n<xsl:template name=\"webwork-js\">\n    <xsl:if test=\"$b-has-webwork-reps\">\n        <script src=\"{$html.js.dir}/pretext-webwork.js\"></script>\n        <script src=\"{$webwork-server}/webwork2_files/node_modules/iframe-resizer/js/iframeResizer.min.js\"></script>\n    </xsl:if>\n</xsl:template>\n\n<!-- lti-iframe-resizer -->\n<xsl:template name=\"lti-iframe-resizer\">\n    <script src=\"{$html.js.dir}/lti_iframe_resizer.js\"></script>\n</xsl:template>\n\n\n<!-- The guts of a WeBWorK problem realized in HTML -->\n<!-- This is heart of an external knowl version, or -->\n<!-- what is born visible under control of a switch -->\n<xsl:template match=\"webwork-reps\">\n    <xsl:param name=\"b-original\" select=\"true()\"/>\n    <xsl:param name=\"heading-level\"/>\n    <!-- TODO: simplify these variables, much like for LaTeX -->\n    <xsl:variable name=\"b-has-hint\" select=\"(ancestor::*[&PROJECT-FILTER;] and $b-has-project-hint) or\n                                            (ancestor::exercises and $b-has-divisional-hint) or\n                                            (ancestor::reading-questions and $b-has-reading-hint) or\n                                            (ancestor::worksheet and $b-has-worksheet-hint) or\n                                            (not(ancestor::*[&PROJECT-FILTER;] or ancestor::exercises or ancestor::reading-questions or ancestor::worksheet) and $b-has-inline-hint)\" />\n    <xsl:variable name=\"b-has-answer\" select=\"(ancestor::*[&PROJECT-FILTER;] and $b-has-project-answer) or\n                                              (ancestor::exercises and $b-has-divisional-answer) or\n                                              (ancestor::reading-questions and $b-has-reading-answer) or\n                                              (ancestor::worksheet and $b-has-worksheet-answer) or\n                                              (not(ancestor::*[&PROJECT-FILTER;] or ancestor::exercises or ancestor::reading-questions or ancestor::worksheet) and $b-has-inline-answer)\" />\n    <xsl:variable name=\"b-has-solution\" select=\"(ancestor::*[&PROJECT-FILTER;] and $b-has-project-solution) or\n                                                (ancestor::exercises and $b-has-divisional-solution) or\n                                                (ancestor::reading-questions and $b-has-reading-solution) or\n                                                (ancestor::worksheet and $b-has-worksheet-solution) or\n                                                (not(ancestor::*[&PROJECT-FILTER;] or ancestor::exercises or ancestor::reading-questions or ancestor::worksheet) and $b-has-inline-solution)\"/>\n    <xsl:variable name=\"b-static\" select=\"(ancestor::*[&PROJECT-FILTER;] and $b-webwork-project-static) or\n                                          (ancestor::exercises and $b-webwork-divisional-static) or\n                                          (ancestor::reading-questions and $b-webwork-reading-static) or\n                                          (ancestor::worksheet and $b-webwork-worksheet-static) or\n                                          (not(ancestor::*[&PROJECT-FILTER;] or ancestor::exercises or ancestor::reading-questions or ancestor::worksheet) and $b-webwork-inline-static)\"/>\n    <xsl:choose>\n        <!-- We print the static version when that is explicitly directed. -->\n        <xsl:when test=\"$b-static\">\n            <xsl:apply-templates select=\"static\" mode=\"exercise-components\">\n                <xsl:with-param name=\"b-original\"      select=\"$b-original\"/>\n                <xsl:with-param name=\"heading-level\"   select=\"$heading-level\"/>\n                <xsl:with-param name=\"b-has-statement\" select=\"true()\"/>\n                <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-hint\"/>\n                <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-answer\"/>\n                <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-solution\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\".\" mode=\"webwork-interactive-div\">\n                <xsl:with-param name=\"b-original\"     select=\"$b-original\"/>\n                <xsl:with-param name=\"heading-level\"  select=\"$heading-level\"/>\n                <xsl:with-param name=\"b-has-hint\"     select=\"$b-has-hint\"/>\n                <xsl:with-param name=\"b-has-answer\"   select=\"$b-has-answer\"/>\n                <xsl:with-param name=\"b-has-solution\" select=\"$b-has-solution\"/>\n            </xsl:apply-templates>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Make a div with a button, where pretext-webwork.js can   -->\n<!-- replace the div content with a live, interactive problem -->\n<xsl:template match=\"webwork-reps\" mode=\"webwork-interactive-div\">\n    <xsl:param name=\"b-original\"/>\n    <xsl:param name=\"heading-level\"/>\n    <xsl:param name=\"b-has-hint\"/>\n    <xsl:param name=\"b-has-answer\"/>\n    <xsl:param name=\"b-has-solution\"/>\n\n    <!-- For Runestone, the WW problem is handled in isolation,   -->\n    <!-- yet capturing and storing student work/results needs     -->\n    <!-- to be associated with the parent/enclosing \"exercise\"    -->\n    <!-- (or PROJECT-LIKE).  So in this case (only) we place      -->\n    <!-- an id value on the  div.exercise-wrapper that is         -->\n    <!-- derived from the parent.  Otherwise, we use the          -->\n    <!-- @assembly-id of this \"webwork-reps\" with a \"-ww-inner\"   -->\n    <!-- suffix.  That attribute is NOT the assembly stamp and    -->\n    <!-- carries no \"pi\" prefix: it is written by webwork.py into -->\n    <!-- the generated representation file, naming it for the     -->\n    <!-- exercise it belongs to.  The suffix ensures the inner    -->\n    <!-- wrapper's DOM id is distinct from the enclosing          -->\n    <!-- \"exercise\" article's id, which holds the same value.     -->\n    <!-- Without the suffix, JavaScript (handleWW) would          -->\n    <!-- look up the inner id with getElementById and find        -->\n    <!-- the outer \"exercise\" article instead.                    -->\n    <xsl:variable name=\"inner-id\">\n        <xsl:choose>\n            <xsl:when test=\"$b-host-runestone\">\n                <xsl:apply-templates select=\"parent::*\" mode=\"runestone-id\"/>\n                <xsl:text>-ww-rs</xsl:text>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"concat(@assembly-id, '-ww-inner')\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <div id=\"{$inner-id}\" class=\"exercise-wrapper\">\n        <xsl:attribute name=\"data-domain\">\n            <xsl:value-of select=\"$webwork-server\"/>\n        </xsl:attribute>\n        <xsl:attribute name=\"data-seed\" >\n            <xsl:value-of select=\"static/@seed\"/>\n        </xsl:attribute>\n        <xsl:attribute name=\"data-localize-correct\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'correct'\"/>\n            </xsl:apply-templates>\n        </xsl:attribute>\n        <xsl:attribute name=\"data-localize-incorrect\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'incorrect'\"/>\n            </xsl:apply-templates>\n        </xsl:attribute>\n        <xsl:attribute name=\"data-localize-blank\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'blank'\"/>\n            </xsl:apply-templates>\n        </xsl:attribute>\n        <xsl:attribute name=\"data-localize-submit\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'submit'\"/>\n            </xsl:apply-templates>\n        </xsl:attribute>\n        <xsl:attribute name=\"data-localize-check-responses\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'check-responses'\"/>\n            </xsl:apply-templates>\n        </xsl:attribute>\n        <xsl:attribute name=\"data-localize-reveal\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'reveal'\"/>\n            </xsl:apply-templates>\n        </xsl:attribute>\n        <xsl:attribute name=\"data-localize-randomize\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'randomize'\"/>\n            </xsl:apply-templates>\n        </xsl:attribute>\n        <xsl:attribute name=\"data-localize-reset\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'reset'\"/>\n            </xsl:apply-templates>\n        </xsl:attribute>\n        <xsl:attribute name=\"data-localize-hint\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'hint'\"/>\n            </xsl:apply-templates>\n        </xsl:attribute>\n        <xsl:attribute name=\"data-localize-solution\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'solution'\"/>\n            </xsl:apply-templates>\n        </xsl:attribute>\n        <xsl:attribute name=\"data-origin\">\n            <xsl:value-of select=\"rendering-data/@origin\"/>\n        </xsl:attribute>\n        <xsl:choose>\n            <xsl:when test=\"rendering-data/@problemSource\">\n                <xsl:attribute name=\"data-problemSource\">\n                    <xsl:value-of select=\"rendering-data/@problemSource\"/>\n                </xsl:attribute>\n                <!-- When rendering a problem with problemSource, we want to know the base course id -->\n                <xsl:attribute name=\"data-documentID\">\n                    <xsl:value-of select=\"$document-id\"/>\n                </xsl:attribute>\n            </xsl:when>\n            <xsl:when test=\"rendering-data/@sourceFilePath\">\n                <xsl:attribute name=\"data-sourceFilePath\">\n                    <xsl:value-of select=\"rendering-data/@sourceFilePath\"/>\n                </xsl:attribute>\n            </xsl:when>\n        </xsl:choose>\n        <xsl:attribute name=\"data-courseID\">\n            <xsl:value-of select=\"rendering-data/@course-id\"/>\n        </xsl:attribute>\n        <xsl:attribute name=\"data-userID\">\n            <xsl:value-of select=\"rendering-data/@user-id\"/>\n        </xsl:attribute>\n        <xsl:attribute name=\"data-coursePassword\">\n            <xsl:choose>\n                <xsl:when test=\"rendering-data/@passwd\">\n                    <xsl:value-of select=\"rendering-data/@passwd\"/>\n                </xsl:when>\n                <!-- Old representations files will have one of the following @password -->\n                <xsl:when test=\"rendering-data/@password\">\n                    <xsl:value-of select=\"rendering-data/@password\"/>\n                </xsl:when>\n                <!-- Old representations files will have @course-password instead of @password -->\n                <xsl:otherwise>\n                    <xsl:value-of select=\"rendering-data/@course-password\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:attribute>\n        <xsl:attribute name=\"aria-live\">\n            <xsl:value-of select=\"'polite'\"/>\n        </xsl:attribute>\n        <div class=\"problem-buttons\">\n            <button class=\"webwork-button\" onclick=\"handleWW('{$inner-id}')\">\n                <xsl:apply-templates select=\".\" mode=\"type-name\">\n                    <xsl:with-param name=\"string-id\" select=\"'activate'\"/>\n                </xsl:apply-templates>\n            </button>\n        </div>\n        <div class=\"problem-contents\">\n            <xsl:apply-templates select=\"static\" mode=\"exercise-components\">\n                <xsl:with-param name=\"b-original\"      select=\"$b-original\"/>\n                <xsl:with-param name=\"heading-level\"   select=\"$heading-level\"/>\n                <xsl:with-param name=\"b-has-statement\" select=\"true()\"/>\n                <xsl:with-param name=\"b-has-hint\"      select=\"$b-has-hint\"/>\n                <xsl:with-param name=\"b-has-answer\"    select=\"$b-has-answer\"/>\n                <xsl:with-param name=\"b-has-solution\"  select=\"$b-has-solution\"/>\n            </xsl:apply-templates>\n        </div>\n    </div>\n</xsl:template>\n\n<!-- Select the correct URL from four pre-generated choices -->\n<!-- and package up as an iframe for interactive version    -->\n<!-- Used with 2.15- WW servers (webwork-reps version 1)    -->\n<xsl:template match=\"webwork-reps\" mode=\"webwork-iframe\">\n    <xsl:param name=\"b-has-hint\"/>\n    <xsl:param name=\"b-has-solution\"/>\n    <xsl:variable name=\"the-url\">\n        <xsl:choose>\n            <xsl:when test=\"$b-has-hint and $b-has-solution\">\n                <xsl:apply-templates select=\"server-url[@hint='yes' and @solution='yes']\"/>\n            </xsl:when>\n            <xsl:when test=\"$b-has-hint and not($b-has-solution)\">\n                <xsl:apply-templates select=\"server-url[@hint='yes' and @solution='no']\"/>\n            </xsl:when>\n            <xsl:when test=\"not($b-has-hint) and $b-has-solution\">\n                <xsl:apply-templates select=\"server-url[@hint='no'  and @solution='yes']\"/>\n            </xsl:when>\n            <xsl:when test=\"not($b-has-hint) and not($b-has-solution)\">\n                <xsl:apply-templates select=\"server-url[@hint='no'  and @solution='no']\"/>\n            </xsl:when>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- build the iframe -->\n    <!-- mimicking Mike Gage's blog post -->\n    <iframe name=\"{concat(@assembly-id, '-ww-inner')}\" width=\"{$design-width}\" src=\"{$the-url}\" data-seed=\"{static/@seed}\"/>\n    <script>\n        <xsl:text>iFrameResize({log:true,inPageLinks:true,resizeFrom:'child',checkOrigin:[\"</xsl:text>\n        <xsl:value-of select=\"$webwork-server\" />\n        <xsl:text>\"]})</xsl:text>\n    </script>\n</xsl:template>\n\n<!-- ############################# -->\n<!-- STACK Embedded Exercises -->\n<!-- ############################# -->\n\n<!-- STACK Javascript header -->\n<xsl:template name=\"stack-js\">\n\n    <xsl:if test=\"$b-has-stack\">\n        <script src=\"{$html.js.dir}/pretext-stack/stackjsvle.js\" type=\"text/javascript\"></script>\n        <script src=\"{$html.js.dir}/pretext-stack/stackapicalls.js\" type=\"text/javascript\"></script>\n        <script type=\"text/javascript\">\n            const stack_api_url = \"<xsl:value-of select=\"$stack-server\"/>\";\n        </script>\n        <script type=\"text/javascript\">\n            function docHasLoaded() {\n                stackSetup();\n            }\n        </script>\n    </xsl:if>\n</xsl:template>\n\n<!-- Not to be confused with  sidebyside/stack  panel -->\n<xsl:template match=\"exercise/stack\">\n    <!-- A little bit of STACK-specific HTML to  -->\n    <!-- embed a question file onto the page -->\n    <div class=\"container-fluid que stack\">\n        <xsl:attribute name=\"data-qfile\">\n            <!-- empty when not using managed directories -->\n            <xsl:value-of select=\"$external-directory\"/>\n            <xsl:value-of select=\"@source\"/>\n        </xsl:attribute>\n        <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n        <xsl:if test=\"@qname != ''\">\n            <xsl:attribute name=\"data-qname\">\n                <xsl:value-of select=\"@qname\" />\n            </xsl:attribute>\n        </xsl:if>\n    </div>\n</xsl:template>\n\n<!-- ############################# -->\n<!-- MyOpenMath Embedded Exercises -->\n<!-- ############################# -->\n\n<xsl:template match=\"myopenmath\">\n    <!-- A container controls the width. At 100% this is the     -->\n    <!-- full page width and when revealed in a knowl it shrinks -->\n    <!-- to fill available width.  In another application, the   -->\n    <!-- width might come from an author's source.               -->\n    <xsl:variable name=\"an-id\">\n        <xsl:apply-templates select=\".\" mode=\"html-id\"/>\n    </xsl:variable>\n    <div id=\"mom{$an-id}wrap\" style=\"width:100%;overflow:visible;position:relative\">\n        <!-- This preserves the aspect-ratio, and there is no       -->\n        <!-- clipping.  Basically this says scale the iframe to     -->\n        <!-- fill whatever width is available in the containing div -->\n        <iframe id=\"mom{$an-id}\" style=\"position:absolute;z-index:1;object-fit: contain; width: 100%\"\n            frameborder=\"0\" data-knowl-callback=\"sendResizeRequest\">\n            <xsl:attribute name=\"src\">\n                <xsl:text>https://www.myopenmath.com/embedq2.php?id=</xsl:text>\n                <xsl:value-of select=\"@problem\" />\n                <!-- can't disable escaping text of an attribute -->\n                <xsl:text>&amp;frame_id=mom</xsl:text>\n                <xsl:value-of select=\"$an-id\" />\n                <xsl:if test=\"@params != ''\">\n                    <xsl:text>&amp;</xsl:text>\n                    <xsl:value-of select=\"str:replace(@params, ',', '&amp;')\" />\n                </xsl:if>\n            </xsl:attribute>\n        </iframe>\n    </div>\n</xsl:template>\n\n<!--                         -->\n<!-- Web Page Infrastructure -->\n<!--                         -->\n\n<!-- Start by building a series of \"cache\" variables that hold common head/foot -->\n<!-- page elements. Ideally, all pages types can be kept in a strict ordering   -->\n<!-- of complexity so each cahce is a superset of the previous ones.            -->\n\n<!-- Start with what is required by iframes -->\n<xsl:variable name=\"file-wrap-iframe-head-cache\">\n    <xsl:call-template name=\"fonts\"/>\n    <xsl:call-template name=\"font-awesome\"/>\n    <xsl:call-template name=\"css\"/>\n    <xsl:call-template name=\"mathjax\"/>\n</xsl:variable>\n\n<!-- Build a cache of the head elements that are constant across ALL standalone -->\n<!-- pages in the document. Main targets are \"standalone\" pages for meadia and  -->\n<!-- interactive extraction.                                                    -->\n<xsl:variable name=\"file-wrap-basic-head-cache\">\n    <xsl:copy-of select=\"$file-wrap-iframe-head-cache\"/>\n    <!-- Add keywords, including those in bibinfo -->\n    <xsl:call-template name=\"keywords-meta-element\"/>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"/>\n    <!-- more \"meta\" elements for discovery -->\n    <xsl:call-template name=\"social-meta-info\"/>\n    <xsl:call-template name=\"pretext-js\"/>\n    <xsl:call-template name=\"runestone-header\"/>\n    <xsl:call-template name=\"scorm-js\"/>\n    <xsl:call-template name=\"diagcess-header\"/>\n    <xsl:call-template name=\"lti-iframe-resizer\"/>\n</xsl:variable>\n\n<!-- Content used by simple-file-wrap -->\n<xsl:variable name=\"file-wrap-simple-head-cache\">\n    <xsl:copy-of select=\"$file-wrap-basic-head-cache\"/>\n    <xsl:call-template name=\"sagecell-code\" />\n    <xsl:call-template name=\"favicon\"/>\n    <xsl:call-template name=\"webwork-js\"/>\n    <xsl:call-template name=\"stack-js\"/>\n    <xsl:call-template name=\"syntax-highlight\"/>\n    <xsl:call-template name=\"hypothesis-annotation\" />\n    <xsl:call-template name=\"geogebra\" />\n    <xsl:call-template name=\"jsxgraph\" />\n    <xsl:call-template name=\"mermaid-header\" />\n</xsl:variable>\n\n<!-- Content used by main file-wrap template -->\n<xsl:variable name=\"file-wrap-full-head-cache\">\n    <xsl:copy-of select=\"$file-wrap-simple-head-cache\"/>\n    <xsl:call-template name=\"google-search-box-js\" />\n    <xsl:call-template name=\"native-search-box-js\" />\n</xsl:variable>\n\n<!-- Now build end of body caches in the same manner          -->\n<!-- Again, start with univeral content and build from there  -->\n\n<!-- basic content is in any standalone page-->\n<xsl:variable name=\"file-wrap-basic-endbody-cache\">\n    <xsl:call-template name=\"statcounter\"/>\n    <xsl:call-template name=\"google-classic\"/>\n    <xsl:call-template name=\"google-universal\"/>\n    <xsl:call-template name=\"google-gst\"/>\n    <xsl:call-template name=\"diagcess-footer\"/>\n    <xsl:call-template name=\"extra-js-footer\"/>\n</xsl:variable>\n\n<!-- extra contents for main file-wrap template -->\n<xsl:variable name=\"file-wrap-full-endbody-cache\">\n    <xsl:copy-of select=\"$file-wrap-basic-endbody-cache\"/>\n    <xsl:call-template name=\"runestone-ethical-ads\"/>\n</xsl:variable>\n\n<xsl:template name=\"pretext-advertisement-and-style\">\n    <!-- 40 characters within comment for each line -->\n    <xsl:variable name=\"fixed-width-theme\"\n        select=\"concat(substring(concat($html-theme-name,   '                               '), 1, 31), '*')\"/>\n    <xsl:variable name=\"fixed-width-palette\"\n        select=\"concat(substring(concat($html-palette-name, '                               '), 1, 29), '*')\"/>\n    <xsl:comment>******************************************</xsl:comment><xsl:text>&#xa;</xsl:text>\n    <xsl:comment>*  Authored with PreTeXt                 *</xsl:comment><xsl:text>&#xa;</xsl:text>\n    <xsl:comment>*  pretextbook.org                       *</xsl:comment><xsl:text>&#xa;</xsl:text>\n    <xsl:comment>*  Theme: <xsl:value-of select=\"$fixed-width-theme\"/></xsl:comment><xsl:text>&#xa;</xsl:text>\n    <xsl:comment>*  Palette: <xsl:value-of select=\"$fixed-width-palette\"/></xsl:comment><xsl:text>&#xa;</xsl:text>\n    <xsl:comment>******************************************</xsl:comment><xsl:text>&#xa;</xsl:text>\n</xsl:template>\n\n\n\n<!-- An individual page:                                   -->\n<!-- Inputs:                                               -->\n<!-- * page content (exclusive of banners, navigation etc) -->\n<xsl:template match=\"*\" mode=\"file-wrap\">\n    <xsl:param name=\"content\" />\n    <xsl:param name=\"title\" select=\"''\"/>\n    <xsl:param name=\"filename\" select=\"''\"/>\n    <xsl:param name=\"b-has-printout\" select=\"false()\"/>\n    <xsl:param name=\"b-include-bottom-nav\" select=\"true()\"/>\n\n    <xsl:variable name=\"the-filename\">\n        <xsl:choose>\n            <xsl:when test=\"not($filename = '')\">\n                <xsl:value-of select=\"$filename\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:apply-templates select=\".\" mode=\"containing-filename\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n\n    <exsl:document href=\"{$the-filename}\" method=\"html\" indent=\"yes\" encoding=\"UTF-8\" doctype-system=\"about:legacy-compat\">\n    <xsl:call-template name=\"converter-blurb-html-no-date\"/>\n    <html>\n        <xsl:call-template name=\"language-attributes\"/>\n        <xsl:call-template name=\"html-theme-attributes\"/>\n        <xsl:call-template name=\"pretext-advertisement-and-style\"/>\n        <!-- Open Graph Protocol only in \"meta\" elements, within \"head\" -->\n        <head xmlns:og=\"http://ogp.me/ns#\" xmlns:book=\"https://ogp.me/ns/book#\">\n            <!-- optional head content that needs to come prior to other content -->\n            <xsl:apply-templates select=\".\" mode=\"file-wrap-head-pre\"/>\n            <title>\n                <xsl:choose>\n                    <xsl:when test=\"$title != ''\">\n                        <xsl:value-of select=\"$title\"/>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <!-- Leading with initials is useful for small tabs -->\n                        <xsl:if test=\"$docinfo/initialism\">\n                            <xsl:apply-templates select=\"$docinfo/initialism\" />\n                            <xsl:text> </xsl:text>\n                        </xsl:if>\n                        <xsl:apply-templates select=\".\" mode=\"title-plain\" />\n                    </xsl:otherwise>\n                </xsl:choose>\n            </title>\n            <!-- canonical link for better SEO -->\n            <xsl:call-template name=\"canonical-link\">\n                <xsl:with-param name=\"filename\" select=\"$the-filename\"/>\n            </xsl:call-template>\n            <!-- grab the contents every page gets -->\n            <xsl:copy-of select=\"$file-wrap-full-head-cache\"/>\n            <!-- now do anything that is or could be page-specific and comes after cache -->\n            <xsl:apply-templates select=\".\" mode=\"knowl\" />\n            <!-- webwork's iframeResizer needs to come before sagecell template -->\n            <xsl:apply-templates select=\".\" mode=\"sagecell\" />\n            <!-- optional head content that might override other content-->\n            <xsl:apply-templates select=\".\" mode=\"file-wrap-head-post\"/>\n        </head>\n        <body>\n            <xsl:if test=\"$b-has-stack\">\n                <xsl:attribute name=\"onload\">\n                    <xsl:text>docHasLoaded()</xsl:text>\n                </xsl:attribute>\n            </xsl:if>\n\n            <!-- potential document-id per-page -->\n            <xsl:call-template name=\"document-id\"/>\n            <!-- React flag -->\n            <xsl:call-template name=\"react-in-use-flag\"/>\n            <!-- the first class controls the default icon -->\n            <xsl:attribute name=\"class\">\n                <xsl:choose>\n                    <xsl:when test=\"$root/book\">pretext book</xsl:when>\n                    <xsl:when test=\"$root/article\">pretext article</xsl:when>\n                </xsl:choose>\n                <xsl:apply-templates select=\".\" mode=\"file-wrap-body-attr-extra\"/>\n                <!-- ignore MathJax signals everywhere, then enable selectively -->\n                <xsl:text> ignore-math</xsl:text>\n            </xsl:attribute>\n            <!-- assistive \"Skip to main content\" link    -->\n            <!-- this *must* be first for maximum utility -->\n            <xsl:call-template name=\"skip-to-content-link\" />\n            <!-- HTML5 body/header will be a \"banner\" landmark automatically -->\n            <header id=\"ptx-masthead\" class=\"ptx-masthead\" role=\"banner\">\n                <div class=\"ptx-banner\">\n                    <xsl:call-template name=\"brand-logo\" />\n                    <div class=\"title-container\">\n                        <xsl:variable name=\"banner-heading-element-type\">\n                            <xsl:apply-templates select=\".\" mode=\"banner-heading-element-type\"/>\n                        </xsl:variable>\n                        <xsl:element name=\"{$banner-heading-element-type}\">\n                            <xsl:attribute name=\"class\">heading ptx-banner-heading</xsl:attribute>\n                            <xsl:variable name=\"root-filename\">\n                                <xsl:apply-templates select=\"$document-root\" mode=\"containing-filename\" />\n                            </xsl:variable>\n                            <a href=\"{$root-filename}\">\n                                <xsl:variable name=\"b-has-subtitle\" select=\"boolean($document-root/subtitle)\"/>\n                                <span class=\"title\">\n                                    <!-- Do not use shorttitle in masthead,  -->\n                                    <!-- which is much like cover of a book  -->\n                                    <xsl:apply-templates select=\"$document-root\" mode=\"title-simple\" />\n                                </span>\n                                <xsl:if test=\"$b-has-subtitle and $b-html-banner-subtitle\">\n                                    <xsl:text> </xsl:text>\n                                    <span class=\"subtitle\">\n                                        <xsl:apply-templates select=\"$document-root\" mode=\"subtitle\" />\n                                    </span>\n                                </xsl:if>\n                            </a>\n                        </xsl:element>\n                        <!-- Serial list of authors/editors -->\n                        <xsl:if test=\"$b-html-banner-byline\">\n                            <p class=\"byline\">\n                                <xsl:apply-templates select=\"$bibinfo/author\" mode=\"name-list\"/>\n                                <xsl:apply-templates select=\"$bibinfo/editor\" mode=\"name-list\"/>\n                            </p>\n                        </xsl:if>\n                    </div>  <!-- title-container -->\n                </div> <!-- banner -->\n            </header>  <!-- masthead -->\n            <xsl:apply-templates select=\".\" mode=\"primary-navigation\"/>\n            <xsl:apply-templates select=\".\" mode=\"latex-macros\"/>\n            <div class=\"ptx-page\">\n                <xsl:apply-templates select=\".\" mode=\"sidebars\" />\n                <!-- HTML5 main will be a \"main\" landmark automatically -->\n                <main class=\"ptx-main\">\n                    <xsl:if test=\"$b-watermark\">\n                        <xsl:attribute name=\"style\">\n                            <xsl:value-of select=\"$watermark-css\"/>\n                        </xsl:attribute>\n                    </xsl:if>\n                    <div id=\"ptx-content\" class=\"ptx-content\">\n                        <xsl:if test=\"$b-has-printout\">\n                            <xsl:apply-templates select=\".\" mode=\"print-preview-header\"/>\n                        </xsl:if>\n                        <!-- Alternative to \"copy-of\": convert $content to a  -->\n                        <!-- node-set, and then hit with an identity template -->\n                        <!-- to duplicate.  Experiment indicates no change in -->\n                        <!-- output. (2023-01-11)                             -->\n                        <xsl:copy-of select=\"$content\" />\n                    </div>\n                    <xsl:if test=\"$b-include-bottom-nav\">\n                        <div id=\"ptx-content-footer\" class=\"ptx-content-footer\">\n                            <xsl:apply-templates select=\".\" mode=\"previous-button\"/>\n                            <xsl:variable name=\"top-localization\">\n                                <xsl:apply-templates select=\".\" mode=\"type-name\">\n                                    <xsl:with-param name=\"string-id\" select=\"'top'\"/>\n                                </xsl:apply-templates>\n                            </xsl:variable>\n                            <a class=\"top-button button\" href=\"#\" title=\"{$top-localization}\">\n                                <xsl:call-template name=\"insert-symbol\">\n                                    <xsl:with-param name=\"name\" select=\"'expand_less'\"/>\n                                </xsl:call-template>\n                                <span class=\"name\">\n                                    <xsl:value-of select=\"$top-localization\"/>\n                                </span>\n                            </a>\n                            <xsl:apply-templates select=\".\" mode=\"next-button\"/>\n                        </div>\n                    </xsl:if>\n                </main>\n            </div>\n            <!-- formerly \"extra\" -->\n            <div id=\"ptx-page-footer\" class=\"ptx-page-footer\">\n                <xsl:apply-templates select=\".\" mode=\"feedback-button\"/>\n                <xsl:call-template name=\"pretext-link\" />\n                <xsl:call-template name=\"runestone-link\"/>\n                <xsl:call-template name=\"mathjax-link\" />\n            </div>\n            <xsl:copy-of select=\"$file-wrap-full-endbody-cache\"/>\n            <!-- For portable builds we stash the lunr search here -->\n            <xsl:if test=\"$b-portable-html and $has-native-search\">\n                <xsl:call-template name=\"embedded-search-construction\"/>\n            </xsl:if>\n            <!-- optional body content that needs to be inserted after all content -->\n            <!-- e.g. script tags to run immediately                               -->\n            <xsl:apply-templates select=\".\" mode=\"file-wrap-body-post\"/>\n        </body>\n    </html>\n    </exsl:document>\n</xsl:template>\n\n<!-- Most pages get a plain div for the banner title element as content will have an h1 -->\n<xsl:template match=\"*\" mode=\"banner-heading-element-type\">\n    <xsl:text>div</xsl:text>\n</xsl:template>\n\n<!-- Root page for a single page document needs h1 as the banner title element -->\n<!-- as there will not be on in page contents.                                 -->\n<xsl:template match=\"book|article\" mode=\"banner-heading-element-type\">\n    <xsl:choose>\n        <xsl:when test=\"$b-is-single-page\">\n            <xsl:text>h1</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>div</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Templates that can be overriden to inject into various      -->\n<!-- points in the HTML page. See file-wrap above for locations. -->\n<xsl:template match=\"*\" mode=\"file-wrap-head-pre\"/>\n<xsl:template match=\"*\" mode=\"file-wrap-head-post\"/>\n<xsl:template match=\"*\" mode=\"file-wrap-body-attr-extra\"/>\n<xsl:template match=\"*\" mode=\"file-wrap-body-post\"/>\n\n<!-- A minimal individual page:                              -->\n<!-- Inputs:                                                 -->\n<!-- * page content (exclusive of banners, navigation etc)   -->\n<xsl:template match=\"*\" mode=\"simple-file-wrap\">\n    <xsl:param name=\"content\" />\n    <xsl:variable name=\"filename\">\n        <!-- do not use \"containing-filename\" may be different -->\n        <xsl:apply-templates select=\".\" mode=\"unique-id\" />\n        <text>.html</text>\n    </xsl:variable>\n    <exsl:document href=\"{$filename}\" method=\"html\" indent=\"yes\" encoding=\"UTF-8\" doctype-system=\"about:legacy-compat\">\n    <xsl:call-template name=\"converter-blurb-html-no-date\"/>\n    <html>\n        <xsl:call-template name=\"language-attributes\"/>\n        <xsl:call-template name=\"pretext-advertisement-and-style\"/>\n        <!-- Open Graph Protocol only in \"meta\" elements, within \"head\" -->\n        <head xmlns:og=\"http://ogp.me/ns#\" xmlns:book=\"https://ogp.me/ns/book#\">\n            <title>\n                <xsl:apply-templates select=\".\" mode=\"title-plain\" />\n            </title>\n            <!-- canonical link for better SEO -->\n            <xsl:call-template name=\"canonical-link\">\n                <xsl:with-param name=\"filename\" select=\"$filename\"/>\n            </xsl:call-template>\n            <!-- grab the contents every page gets -->\n            <xsl:copy-of select=\"$file-wrap-simple-head-cache\"/>\n            <!-- now do anything that is or could be page-specific and comes after cache -->\n            <xsl:apply-templates select=\".\" mode=\"knowl\" />\n            <xsl:apply-templates select=\".\" mode=\"sagecell\" />\n        </head>\n        <!-- TODO: needs some padding etc -->\n        <!-- ignore MathJax signals everywhere, then enable selectively -->\n        <body class=\"ignore-math\">\n            <!-- potential document-id per-page -->\n            <xsl:call-template name=\"document-id\"/>\n            <!-- React flag -->\n            <xsl:call-template name=\"react-in-use-flag\"/>\n            <xsl:copy-of select=\"$content\" />\n            <xsl:copy-of select=\"$file-wrap-basic-endbody-cache\"/>\n        </body>\n    </html>\n    </exsl:document>\n</xsl:template>\n\n<!-- The body element of every page will (optionally) carry  -->\n<!-- an id that identifies which document the HTML page is a -->\n<!-- portion of.  This requires the author to specify the    -->\n<!-- string in the docinfo/document-id element, which comes  -->\n<!-- here via the $document-id variable.                     -->\n<xsl:template name=\"document-id\">\n    <xsl:if test=\"not($document-id = '')\">\n        <xsl:attribute name=\"id\">\n            <xsl:value-of select=\"$document-id\"/>\n        </xsl:attribute>\n    </xsl:if>\n</xsl:template>\n\n<xsl:template name=\"react-in-use-flag\">\n    <xsl:if test=\"$b-debug-react\">\n        <xsl:attribute name=\"data-react-in-use\">\n            <xsl:value-of select=\"'yes'\"/>\n        </xsl:attribute>\n    </xsl:if>\n</xsl:template>\n\n<!-- ############# -->\n<!-- Meta keywords -->\n<!-- ############# -->\n\n<xsl:template name=\"keywords-meta-element\" >\n    <meta name=\"Keywords\">\n        <xsl:attribute name=\"content\">\n            <xsl:if test=\"$bibinfo/keywords[not(@authority='msc')]\">\n                <xsl:apply-templates select=\"$bibinfo/keywords[not(@authority='msc')]/keyword\" />\n                <xsl:text>, </xsl:text>\n            </xsl:if>\n            <xsl:text>Authored in PreTeXt</xsl:text>\n        </xsl:attribute>\n    </meta>\n</xsl:template>\n\n<!-- ################### -->\n<!-- Page Identification -->\n<!-- ################### -->\n\n<!-- Canonical Link -->\n<xsl:template name=\"canonical-link\">\n    <xsl:param name=\"filename\"/>\n    <!-- just for Runestone builds -->\n    <xsl:if test=\"$b-host-runestone\">\n        <xsl:variable name=\"site-root\">\n            <xsl:call-template name=\"runestone-server-baseurl\"/>\n        </xsl:variable>\n        <xsl:variable name=\"full-url\" select=\"concat($site-root, $filename)\"/>\n        <link rel=\"canonical\" href=\"{$full-url}\"/>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- Social meta tags (OpenGraph/Facebook, Twitter/X, others) -->\n<!-- https://ogp.me/                                          -->\n<!-- https://developers.facebook.com/docs/sharing/webmasters/ -->\n<!-- https://webcode.tools/generators/open-graph/book         -->\n<!-- Sanity-check live instance: https://opengraphcheck.com/  -->\n<!-- Includes Twitter/X: https://www.digitalocean.com/community/tutorials/how-to-add-twitter-card-and-open-graph-social-metadata-to-your-webpage-with-html -->\n<!-- NB not used for EPUB nor Jupyter (could be in RevealJS?) -->\n\n<xsl:template name=\"social-meta-info\">\n    <!-- type (og) - book, article, or missing -->\n    <xsl:if test=\"$b-is-article or $b-is-book\">\n        <xsl:call-template name=\"social-meta-element\">\n            <xsl:with-param name=\"og\" select=\"true()\"/>\n            <xsl:with-param name=\"property\" select=\"'type'\"/>\n            <xsl:with-param name=\"content\">\n                <xsl:choose>\n                    <xsl:when test=\"$b-is-book\">\n                        <xsl:text>book</xsl:text>\n                    </xsl:when>\n                    <xsl:when test=\"$b-is-article\">\n                        <xsl:text>article</xsl:text>\n                    </xsl:when>\n                </xsl:choose>\n            </xsl:with-param>\n        </xsl:call-template>\n    </xsl:if>\n    <!-- image (og,twitter) - if its URL can be constructed -->\n    <xsl:if test=\"$b-has-baseurl and $b-brandlogo\">\n        <xsl:call-template name=\"social-meta-element\">\n            <xsl:with-param name=\"og\" select=\"true()\"/>\n            <xsl:with-param name=\"twitter\" select=\"true()\"/>\n            <xsl:with-param name=\"property\" select=\"'image'\"/>\n            <!-- URL = baseurl + external + @source -->\n            <xsl:with-param name=\"content\">\n                <!-- empty when not using managed directories -->\n                <xsl:value-of select=\"$baseurl\"/>\n                <xsl:value-of select=\"$external-directory\"/>\n                <xsl:value-of select=\"$brandlogo-source\"/>\n            </xsl:with-param>\n        </xsl:call-template>\n        <!-- alttext -->\n        <xsl:call-template name=\"social-meta-element\">\n            <xsl:with-param name=\"og\" select=\"true()\"/>\n            <xsl:with-param name=\"twitter\" select=\"true()\"/>\n            <xsl:with-param name=\"property\" select=\"'image:alt'\"/>\n            <xsl:with-param name=\"content\">\n                <xsl:text>Document Logo</xsl:text>\n            </xsl:with-param>\n        </xsl:call-template>\n    </xsl:if>\n    <!-- title (og,twitter,book) (always exactly one)-->\n    <xsl:call-template name=\"social-meta-element\">\n        <xsl:with-param name=\"og\" select=\"true()\"/>\n        <xsl:with-param name=\"twitter\" select=\"true()\"/>\n        <xsl:with-param name=\"book\" select=\"$b-is-book\"/>\n        <xsl:with-param name=\"property\" select=\"'title'\"/>\n        <xsl:with-param name=\"content\">\n            <xsl:apply-templates select=\"$document-root\" mode=\"title-plain\"/>\n            <xsl:if test=\"$docinfo/blurb and $document-root/subtitle\">\n                <xsl:text>: </xsl:text>\n                <xsl:apply-templates select=\"$document-root\" mode=\"subtitle-plain\"/>\n            </xsl:if>\n        </xsl:with-param>\n    </xsl:call-template>\n    <!-- description (og,twitter) -->\n    <xsl:if test=\"$docinfo/blurb or $document-root/subtitle\">\n        <xsl:call-template name=\"social-meta-element\">\n            <xsl:with-param name=\"og\" select=\"true()\"/>\n            <xsl:with-param name=\"twitter\" select=\"true()\"/>\n            <xsl:with-param name=\"property\" select=\"'description'\"/>\n            <xsl:with-param name=\"content\">\n                <xsl:choose>\n                    <xsl:when test=\"$docinfo/blurb\">\n                        <xsl:value-of select=\"normalize-space($docinfo/blurb)\"/>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:apply-templates select=\"$document-root\" mode=\"subtitle-plain\"/>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:with-param>\n        </xsl:call-template>\n    </xsl:if>\n    <!-- card (twitter) -->\n    <xsl:call-template name=\"social-meta-element\">\n        <xsl:with-param name=\"twitter\" select=\"true()\"/>\n        <xsl:with-param name=\"property\" select=\"'card'\"/>\n        <xsl:with-param name=\"content\">\n            <xsl:choose>\n                <xsl:when test=\"$b-has-baseurl and $b-brandlogo\">\n                    <xsl:text>summary_large_image</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:text>summary</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n<xsl:template name=\"social-meta-element\">\n    <xsl:param name=\"twitter\" select=\"false()\"/>\n    <xsl:param name=\"og\" select=\"false()\"/>\n    <xsl:param name=\"book\" select=\"false()\"/>\n    <xsl:param name=\"property\"/>\n    <xsl:param name=\"content\"/>\n    <!-- Twitter/X carries the prefixed value in a \"name\" attribute,  -->\n    <!-- while OpenGraph and \"book\" use a \"property\" attribute.       -->\n    <xsl:if test=\"$twitter\">\n        <xsl:call-template name=\"social-meta-tag\">\n            <xsl:with-param name=\"attribute\" select=\"'name'\"/>\n            <xsl:with-param name=\"prefix\" select=\"'twitter'\"/>\n            <xsl:with-param name=\"property\" select=\"$property\"/>\n            <xsl:with-param name=\"content\" select=\"$content\"/>\n        </xsl:call-template>\n    </xsl:if>\n    <xsl:if test=\"$og\">\n        <xsl:call-template name=\"social-meta-tag\">\n            <xsl:with-param name=\"attribute\" select=\"'property'\"/>\n            <xsl:with-param name=\"prefix\" select=\"'og'\"/>\n            <xsl:with-param name=\"property\" select=\"$property\"/>\n            <xsl:with-param name=\"content\" select=\"$content\"/>\n        </xsl:call-template>\n    </xsl:if>\n    <xsl:if test=\"$book\">\n        <xsl:call-template name=\"social-meta-tag\">\n            <xsl:with-param name=\"attribute\" select=\"'property'\"/>\n            <xsl:with-param name=\"prefix\" select=\"'book'\"/>\n            <xsl:with-param name=\"property\" select=\"$property\"/>\n            <xsl:with-param name=\"content\" select=\"$content\"/>\n        </xsl:call-template>\n    </xsl:if>\n</xsl:template>\n\n<!-- One \"meta\" element: a prefixed \"name\"/\"property\" plus its content -->\n<xsl:template name=\"social-meta-tag\">\n    <xsl:param name=\"attribute\"/>\n    <xsl:param name=\"prefix\"/>\n    <xsl:param name=\"property\"/>\n    <xsl:param name=\"content\"/>\n    <meta>\n        <xsl:attribute name=\"{$attribute}\">\n            <xsl:value-of select=\"$prefix\"/>\n            <xsl:text>:</xsl:text>\n            <xsl:value-of select=\"$property\"/>\n        </xsl:attribute>\n        <xsl:attribute name=\"content\">\n            <xsl:value-of select=\"$content\"/>\n        </xsl:attribute>\n    </meta>\n</xsl:template>\n\n\n<!-- ################# -->\n<!-- Navigational Aids -->\n<!-- ################# -->\n\n<!-- Skip to Main Content link -->\n<!-- For accessibilty, a link (hidden off-screen)  -->\n<!-- which allows a quick by-pass of all the other -->\n<!-- navigational elements, direct to content      -->\n<xsl:template name=\"skip-to-content-link\">\n    <xsl:element name=\"a\">\n        <xsl:attribute name=\"class\">\n            <xsl:text>assistive</xsl:text>\n        </xsl:attribute>\n        <xsl:attribute name=\"href\">\n            <xsl:text>#ptx-content</xsl:text>\n        </xsl:attribute>\n        <xsl:apply-templates select=\".\" mode=\"type-name\">\n            <xsl:with-param name=\"string-id\" select=\"'skip-to-content'\"/>\n        </xsl:apply-templates>\n    </xsl:element>\n</xsl:template>\n\n<!-- Prev/Up/Next URL's -->\n<!-- The \"tree\" versions are simpler, though less natural for a reader -->\n<!-- They often return empty and require the use of the Up button      -->\n<!-- The \"linear\" versions are breadth-first search, and so mimic      -->\n<!-- the way a reader would encounter the sections in a (linear) book  -->\n\n<!-- TODO: perhaps isolate logic to return nodes and put into \"common\" -->\n\n<!-- Is a node a unit of the linear page order?  The structural  -->\n<!-- nodes are; so is a division companion realized as a page     -->\n<xsl:template match=\"*\" mode=\"is-linear-unit\">\n    <xsl:apply-templates select=\".\" mode=\"is-structural\"/>\n</xsl:template>\n\n<xsl:template match=\"&DIVISION-COMPANION;\" mode=\"is-linear-unit\">\n    <xsl:apply-templates select=\".\" mode=\"is-chunk\"/>\n</xsl:template>\n\n<!-- Check if the XML tree has a preceding/following/parent node -->\n<!-- Then check if it is a page of the reading order             -->\n<!-- If so, compute the URL for the node                         -->\n<!-- NB: tree urls maybe enabled as a processing option          -->\n<xsl:template match=\"*\" mode=\"previous-tree-url\">\n    <xsl:if test=\"preceding-sibling::*\">\n        <xsl:variable name=\"preceding\" select=\"preceding-sibling::*[1]\" />\n        <xsl:variable name=\"structural\">\n            <xsl:apply-templates select=\"$preceding\" mode=\"is-linear-unit\" />\n        </xsl:variable>\n        <xsl:if test=\"$structural='true'\">\n            <xsl:apply-templates select=\"$preceding\" mode=\"url\" />\n        </xsl:if>\n    </xsl:if>\n    <!-- could be empty -->\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"next-tree-url\">\n    <xsl:if test=\"following-sibling::*\">\n        <xsl:variable name=\"following\" select=\"following-sibling::*[1]\" />\n        <xsl:variable name=\"structural\">\n            <xsl:apply-templates select=\"$following\" mode=\"is-linear-unit\" />\n        </xsl:variable>\n        <xsl:if test=\"$structural='true'\">\n            <xsl:apply-templates select=\"$following\" mode=\"url\" />\n        </xsl:if>\n    </xsl:if>\n    <!-- could be empty -->\n</xsl:template>\n\n<!-- Create the URL of the parent document node    -->\n<!-- Parent always exists, since the               -->\n<!-- structural check fails at <pretext>           -->\n<!-- Identical in tree/linear schemes, up is up    -->\n<xsl:template match=\"*\" mode=\"up-url\">\n    <xsl:if test=\"parent::*\">\n        <xsl:variable name=\"parent\" select=\"parent::*[1]\" />\n        <xsl:variable name=\"structural\">\n            <xsl:apply-templates select=\"$parent\" mode=\"is-structural\" />\n        </xsl:variable>\n        <xsl:if test=\"$structural='true'\">\n            <xsl:apply-templates select=\"$parent\" mode=\"url\" />\n        </xsl:if>\n    </xsl:if>\n    <!-- will be empty precisely at children of <pretext> -->\n</xsl:template>\n\n<!-- Next Linear URL -->\n<!-- Breadth-first search, try to descend into first summary link -->\n<!-- Else, look sideways for next structural sibling              -->\n<!-- Else, go up to parent and look sideways                      -->\n<!-- Else done and return empty url                               -->\n<xsl:template match=\"*\" mode=\"next-linear-url\">\n    <xsl:variable name=\"intermediate\">\n        <xsl:apply-templates select=\".\" mode=\"is-intermediate\" />\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$intermediate='true'\">\n            <!-- Descend once, will always have a child that is structural -->\n            <xsl:variable name=\"first-structural-child\" select=\"*[&STRUCTURAL-FILTER; or ($b-division-companion-chunks and (&DIVISION-COMPANION-FILTER;))][1]\" />\n            <xsl:apply-templates select=\"$first-structural-child\" mode=\"url\" />\n            <!-- remainder is a basic check, could be removed -->\n            <xsl:variable name=\"structural\">\n                <xsl:apply-templates select=\"$first-structural-child\" mode=\"is-linear-unit\" />\n            </xsl:variable>\n            <xsl:if test=\"$structural='false'\">\n                <xsl:message>PTX:ERROR: descending into first node of an intermediate page (<xsl:value-of select=\"local-name($first-structural-child)\" />) that is non-structural; maybe your source has incorrect structure</xsl:message>\n                <xsl:apply-templates select=\".\" mode=\"location-report\" />\n            </xsl:if>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- try going sideways, which climbs up the tree recursively -->\n            <xsl:apply-templates select=\".\" mode=\"next-sideways-url\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Recursively look sideways to the right, else up    -->\n<!-- <pretext> is not structural, so halt looking there -->\n<xsl:template match=\"*\" mode=\"next-sideways-url\">\n    <xsl:variable name=\"url\">\n        <xsl:if test=\"following-sibling::*\">\n            <xsl:variable name=\"following\" select=\"following-sibling::*[1]\" />\n            <xsl:variable name=\"structural\">\n                <xsl:apply-templates select=\"$following\" mode=\"is-linear-unit\" />\n            </xsl:variable>\n            <xsl:if test=\"$structural='true'\">\n                <!-- A normal sibling following -->\n                <xsl:apply-templates select=\"$following\" mode=\"url\" />\n            </xsl:if>\n        </xsl:if>\n        <!-- could be empty here-->\n    </xsl:variable>\n    <xsl:value-of select=\"$url\" /> <!-- no harm if empty -->\n    <xsl:if test=\"$url=''\">\n        <!-- Try going up and then sideways                          -->\n        <!-- parent always exists, since <pretext> is non-structural -->\n        <xsl:variable name=\"parent\" select=\"parent::*[1]\" />\n        <xsl:variable name=\"structural\">\n            <xsl:apply-templates select=\"$parent\" mode=\"is-structural\" />\n        </xsl:variable>\n        <xsl:if test=\"$structural='true'\">\n            <!-- Up a level, so try looking sideways again -->\n            <xsl:apply-templates select=\"$parent\" mode=\"next-sideways-url\" />\n        </xsl:if>\n        <!-- otherwise we are off the top and quit with an empty url -->\n    </xsl:if>\n</xsl:template>\n\n<!-- Look sideways to the left                                  -->\n<!-- If present, move there and descend right branches          -->\n<!-- If nothing there, move up once                             -->\n<!-- <pretext> is not structural, so halt if we go up to there  -->\n<xsl:template match=\"*\" mode=\"previous-linear-url\">\n    <xsl:variable name=\"url\">\n        <xsl:if test=\"preceding-sibling::*\">\n            <xsl:variable name=\"preceding\" select=\"preceding-sibling::*[1]\" />\n            <xsl:variable name=\"structural\">\n                <xsl:apply-templates select=\"$preceding\" mode=\"is-linear-unit\" />\n            </xsl:variable>\n            <xsl:if test=\"$structural='true'\">\n                <!-- A normal sibling precedin, result is just a sentinel-->\n                <xsl:apply-templates select=\"$preceding\" mode=\"url\" />\n            </xsl:if>\n        </xsl:if>\n        <!-- could be empty here -->\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$url=''\">\n            <!-- Go up to parent and get the URL there (not recursive)   -->\n            <!-- parent always exists, since <pretext> is non-structural -->\n            <xsl:variable name=\"parent\" select=\"parent::*[1]\" />\n            <xsl:variable name=\"structural\">\n                <xsl:apply-templates select=\"$parent\" mode=\"is-structural\" />\n            </xsl:variable>\n            <xsl:if test=\"$structural='true'\">\n                <xsl:apply-templates select=\"$parent\" mode=\"url\" />\n            </xsl:if>\n            <!-- otherwise we are off the top and quit with an empty url -->\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- found a preceding sibling, so descend right branches to a leaf -->\n            <xsl:apply-templates select=\"preceding-sibling::*[1]\" mode=\"previous-descent-url\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Descend recursively through summary pages -->\n<!-- to a leaf (content) and get URL           -->\n<xsl:template match=\"*\" mode=\"previous-descent-url\" >\n    <xsl:variable name=\"intermediate\">\n        <xsl:apply-templates select=\".\" mode=\"is-intermediate\" />\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$intermediate='false'\">\n            <xsl:apply-templates select=\".\" mode=\"url\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:variable name=\"last-structural-child\" select=\"*[&STRUCTURAL-FILTER; or ($b-division-companion-chunks and (&DIVISION-COMPANION-FILTER;))][last()]\" />\n            <xsl:apply-templates select=\"$last-structural-child\" mode=\"previous-descent-url\" />\n            <!-- remainder is a basic check, could be removed -->\n            <xsl:variable name=\"structural\">\n                <xsl:apply-templates select=\"$last-structural-child\" mode=\"is-linear-unit\" />\n            </xsl:variable>\n            <xsl:if test=\"$structural='false'\">\n                <xsl:message>PTX:ERROR: descending into last node of an intermediate page (<xsl:value-of select=\"local-name($last-structural-child)\" />) that is non-structural</xsl:message>\n            </xsl:if>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- ########## -->\n<!-- Permalinks -->\n<!-- ########## -->\n\n<xsl:template match=\"*\" mode=\"permalink\">\n    <xsl:variable name=\"permalink-description\">\n        <xsl:apply-templates select=\".\" mode=\"type-name\">\n            <xsl:with-param name=\"string-id\" select=\"'permalink-tooltip'\"/>\n        </xsl:apply-templates>\n        <xsl:text> </xsl:text>\n        <xsl:apply-templates select=\".\" mode=\"tooltip-text\"/>\n    </xsl:variable>\n    <!-- JS will selectively unhide and make tab selectable -->\n    <div class=\"autopermalink\" aria-hidden=\"true\">\n        <xsl:attribute name=\"data-description\">\n            <xsl:apply-templates select=\".\" mode=\"tooltip-text\"/>\n        </xsl:attribute>\n        <a tabindex=\"-1\">\n            <xsl:attribute name=\"href\">\n                <xsl:text>#</xsl:text>\n                <xsl:apply-templates select=\".\" mode=\"unique-id\"/>\n            </xsl:attribute>\n            <xsl:attribute name=\"title\">\n                <xsl:value-of select=\"$permalink-description\"/>\n            </xsl:attribute>\n            <xsl:attribute name=\"aria-label\">\n                <xsl:value-of select=\"$permalink-description\"/>\n            </xsl:attribute>\n            <xsl:text>🔗</xsl:text>\n        </a>\n    </div>\n</xsl:template>\n\n<!-- Asides and footnotes don't get permalinks -->\n<xsl:template match=\"fn|&ASIDE-LIKE;\" mode=\"permalink\"/>\n\n<!-- 2025-05-29: \"p\" inside a \"feedback\" of a dynamic FITB exercise -->\n<!-- are losing their context, can't look up the tree, don't know   -->\n<!-- their language, and can't make a tooltip.  This match is more  -->\n<!-- aggressive than necessary, but should suffice while we wait    -->\n<!-- for the underlying problem to be addressed.  Details may       -->\n<!-- appear at  https://github.com/PreTeXtBook/pretext/pull/2534    -->\n<xsl:template match=\"feedback/p\" mode=\"permalink\"/>\n\n<!-- 2025-10-19: elements in the label for a multiple choice  -->\n<!-- option overlaps the label itself, obscuring the content. -->\n<!-- NB: \"choices\" are in multiple-choice exercises, and in   -->\n<!-- \"query\" polling-like elements.                           -->\n<xsl:template match=\"choices//*\" mode=\"permalink\"/>\n\n<!-- 2025-11-1: elements inside Parsons problem should not get permalinks -->\n<xsl:template match=\"blocks//*\" mode=\"permalink\"/>\n\n<!-- 2025-11-9: no permalink for elements inside cardsort/matching/clickable -->\n<xsl:template match=\"cardsort//*\" mode=\"permalink\"/>\n<xsl:template match=\"matching//*\" mode=\"permalink\"/>\n<xsl:template match=\"areas//*\" mode=\"permalink\"/>\n\n\n<!--                     -->\n<!-- Navigation Sections -->\n<!--                     -->\n\n<!-- Button code, <a href=\"\"> when active   -->\n<!-- <span> with \"disabled\" class otherwise -->\n<xsl:template match=\"*\" mode=\"previous-button\">\n    <xsl:variable name=\"previous-url\">\n        <xsl:choose>\n            <xsl:when test=\"$nav-logic='linear'\">\n                <xsl:apply-templates select=\".\" mode=\"previous-linear-url\" />\n            </xsl:when>\n            <xsl:when test=\"$nav-logic='tree'\">\n                <xsl:apply-templates select=\".\" mode=\"previous-tree-url\" />\n            </xsl:when>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$previous-url!=''\">\n            <xsl:element name=\"a\">\n                <xsl:attribute name=\"class\">previous-button button</xsl:attribute>\n                <xsl:attribute name=\"href\">\n                    <xsl:value-of select=\"$previous-url\" />\n                </xsl:attribute>\n                <xsl:attribute name=\"title\">\n                    <xsl:apply-templates select=\".\" mode=\"type-name\">\n                        <xsl:with-param name=\"string-id\" select=\"'previous'\"/>\n                    </xsl:apply-templates>\n                </xsl:attribute>\n                <xsl:call-template name=\"insert-symbol\">\n                    <xsl:with-param name=\"name\" select=\"'chevron_left'\"/>\n                </xsl:call-template>\n                <span class=\"name\">\n                    <xsl:apply-templates select=\".\" mode=\"type-name\">\n                        <xsl:with-param name=\"string-id\" select=\"'previous-short'\"/>\n                    </xsl:apply-templates>\n                </span>\n            </xsl:element>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:element name=\"span\">\n                <xsl:attribute name=\"class\">previous-button button disabled</xsl:attribute>\n                <xsl:call-template name=\"insert-symbol\">\n                    <xsl:with-param name=\"name\" select=\"'chevron_left'\"/>\n                </xsl:call-template>\n                <span class=\"name\">\n                    <xsl:apply-templates select=\".\" mode=\"type-name\">\n                        <xsl:with-param name=\"string-id\" select=\"'previous-short'\"/>\n                    </xsl:apply-templates>\n                </span>\n            </xsl:element>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"index-button\">\n    <xsl:if test=\"$the-index\">\n        <xsl:variable name=\"url\">\n            <xsl:apply-templates select=\"$the-index\" mode=\"url\" />\n        </xsl:variable>\n        <xsl:element name=\"a\">\n            <xsl:attribute name=\"class\">\n                <xsl:text>index-button button</xsl:text>\n            </xsl:attribute>\n            <xsl:attribute name=\"href\">\n                <xsl:value-of select=\"$url\" />\n            </xsl:attribute>\n            <xsl:attribute name=\"title\">\n                <xsl:apply-templates select=\".\" mode=\"type-name\">\n                    <xsl:with-param name=\"string-id\" select=\"'index'\"/>\n                </xsl:apply-templates>\n            </xsl:attribute>\n            <xsl:call-template name=\"insert-symbol\">\n                <xsl:with-param name=\"name\" select=\"'info'\"/>\n            </xsl:call-template>\n            <span class=\"name\">\n                <xsl:apply-templates select=\".\" mode=\"type-name\">\n                    <xsl:with-param name=\"string-id\" select=\"'index'\"/>\n                </xsl:apply-templates>\n            </span>\n        </xsl:element>\n    </xsl:if>\n</xsl:template>\n\n<!-- The \"jump to\" navigation on a page with the index -->\n<xsl:template match=\"*\" mode=\"index-jump-nav\">\n    <div class=\"indexnav\">\n        <span class=\"mininav\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'jump-to'\"/>\n            </xsl:apply-templates>\n        </span>\n        <span class=\"indexjump\">\n            <a href=\"#indexletter-a\">A </a>\n            <a href=\"#indexletter-b\">B </a>\n            <a href=\"#indexletter-c\">C </a>\n            <a href=\"#indexletter-d\">D </a>\n            <a href=\"#indexletter-e\">E </a>\n            <a href=\"#indexletter-f\">F </a>\n            <a href=\"#indexletter-g\">G </a>\n            <a href=\"#indexletter-h\">H </a>\n            <a href=\"#indexletter-i\">I </a>\n            <a href=\"#indexletter-j\">J </a>\n            <a href=\"#indexletter-k\">K </a>\n            <a href=\"#indexletter-l\">L </a>\n            <a href=\"#indexletter-m\">M </a>\n            <br />\n            <a href=\"#indexletter-n\">N </a>\n            <a href=\"#indexletter-o\">O </a>\n            <a href=\"#indexletter-p\">P </a>\n            <a href=\"#indexletter-q\">Q </a>\n            <a href=\"#indexletter-r\">R </a>\n            <a href=\"#indexletter-s\">S </a>\n            <a href=\"#indexletter-t\">T </a>\n            <a href=\"#indexletter-u\">U </a>\n            <a href=\"#indexletter-v\">V </a>\n            <a href=\"#indexletter-w\">W </a>\n            <a href=\"#indexletter-x\">X </a>\n            <a href=\"#indexletter-y\">Y </a>\n            <a href=\"#indexletter-z\">Z </a>\n        </span>\n    </div>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"next-button\">\n    <xsl:variable name=\"next-url\">\n        <xsl:choose>\n            <xsl:when test=\"$nav-logic='linear'\">\n                <xsl:apply-templates select=\".\" mode=\"next-linear-url\" />\n            </xsl:when>\n            <xsl:when test=\"$nav-logic='tree'\">\n                <xsl:apply-templates select=\".\" mode=\"next-tree-url\" />\n            </xsl:when>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$next-url!=''\">\n            <xsl:element name=\"a\">\n                <xsl:attribute name=\"class\">next-button button</xsl:attribute>\n                <xsl:attribute name=\"href\">\n                    <xsl:value-of select=\"$next-url\" />\n                </xsl:attribute>\n                <xsl:attribute name=\"title\">\n                    <xsl:apply-templates select=\".\" mode=\"type-name\">\n                        <xsl:with-param name=\"string-id\" select=\"'next'\"/>\n                    </xsl:apply-templates>\n                </xsl:attribute>\n                <span class=\"name\">\n                    <xsl:apply-templates select=\".\" mode=\"type-name\">\n                        <xsl:with-param name=\"string-id\" select=\"'next-short'\"/>\n                    </xsl:apply-templates>\n                </span>\n                <xsl:call-template name=\"insert-symbol\">\n                    <xsl:with-param name=\"name\" select=\"'chevron_right'\"/>\n                </xsl:call-template>\n            </xsl:element>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:element name=\"span\">\n                <xsl:attribute name=\"class\">next-button button disabled</xsl:attribute>\n                <span class=\"name\">\n                    <xsl:apply-templates select=\".\" mode=\"type-name\">\n                        <xsl:with-param name=\"string-id\" select=\"'next-short'\"/>\n                    </xsl:apply-templates>\n                </span>\n                <xsl:call-template name=\"insert-symbol\">\n                    <xsl:with-param name=\"name\" select=\"'chevron_right'\"/>\n                </xsl:call-template>\n            </xsl:element>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"up-button\">\n    <!-- up URL is identical for linear, tree logic -->\n    <xsl:variable name=\"up-url\">\n        <xsl:apply-templates select=\".\" mode=\"up-url\" />\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$up-url!=''\">\n            <xsl:element name=\"a\">\n                <xsl:attribute name=\"class\">up-button button</xsl:attribute>\n                <xsl:attribute name=\"href\">\n                    <xsl:value-of select=\"$up-url\" />\n                </xsl:attribute>\n                <xsl:attribute name=\"title\">\n                    <xsl:apply-templates select=\".\" mode=\"type-name\">\n                        <xsl:with-param name=\"string-id\" select=\"'up'\"/>\n                    </xsl:apply-templates>\n                </xsl:attribute>\n                <xsl:call-template name=\"insert-symbol\">\n                    <xsl:with-param name=\"name\" select=\"'expand_less'\"/>\n                </xsl:call-template>\n                <span class=\"name\">\n                    <xsl:apply-templates select=\".\" mode=\"type-name\">\n                        <xsl:with-param name=\"string-id\" select=\"'up-short'\"/>\n                    </xsl:apply-templates>\n                </span>\n            </xsl:element>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:element name=\"span\">\n                <xsl:attribute name=\"class\">up-button button disabled</xsl:attribute>\n                <xsl:call-template name=\"insert-symbol\">\n                    <xsl:with-param name=\"name\" select=\"'expand_less'\"/>\n                </xsl:call-template>\n                <span class=\"name\">\n                    <xsl:apply-templates select=\".\" mode=\"type-name\">\n                        <xsl:with-param name=\"string-id\" select=\"'up-short'\"/>\n                    </xsl:apply-templates>\n                </span>\n            </xsl:element>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template name=\"calculator-toggle\">\n    <xsl:variable name=\"calculator-localization\">\n        <xsl:apply-templates select=\".\" mode=\"type-name\">\n            <xsl:with-param name=\"string-id\" select=\"'calculator'\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <button type=\"button\" id=\"ptx-calculator-toggle\" class=\"ptx-calculator-toggle button\" title=\"{$calculator-localization}\">\n        <xsl:call-template name=\"insert-symbol\">\n            <xsl:with-param name=\"name\" select=\"'calculate'\"/>\n        </xsl:call-template>\n        <span class=\"name\">\n            <xsl:value-of select=\"$calculator-localization\"/>\n        </span>\n    </button>\n</xsl:template>\n\n<xsl:template name=\"readability-options\">\n    <xsl:variable name=\"reading-settings-localization\">\n        <xsl:apply-templates select=\".\" mode=\"type-name\">\n            <xsl:with-param name=\"string-id\" select=\"'readability-settings'\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <xsl:variable name=\"close-localization\">\n        <xsl:apply-templates select=\".\" mode=\"type-name\">\n            <xsl:with-param name=\"string-id\" select=\"'close'\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <button id=\"ptx-readability-options-button\" class=\"ptx-readability-options-button button\" title=\"{$reading-settings-localization}\">\n        <xsl:call-template name=\"insert-symbol\">\n            <xsl:with-param name=\"name\" select=\"'match_case'\"/>\n        </xsl:call-template>\n        <span class=\"name\">\n            <xsl:value-of select=\"$reading-settings-localization\"/>\n        </span>\n    </button>\n    <dialog class=\"ptx-dialog ptx-readability-options-popup\" id=\"ptx-readability-options-popup\">\n        <div class=\"ptx-readability-options-popup-controls\">\n            <h2 class=\"heading\">\n                <xsl:value-of select=\"$reading-settings-localization\"/>\n            </h2>\n            <button class=\"ptx-readability-options-close-button button\" id=\"ptx-readability-options-close-button\" title=\"{$close-localization}\">\n                <xsl:call-template name=\"insert-symbol\">\n                    <xsl:with-param name=\"name\" select=\"'close'\"/>\n                </xsl:call-template>\n            </button>\n        </div>\n        <div class=\"ptx-readability-options-group\">\n            <label class=\"ptx-readability-slider-label\" for=\"ptx-readability-line-height\">\n                <xsl:call-template name=\"insert-symbol\">\n                    <xsl:with-param name=\"name\" select=\"'format_line_spacing'\"/>\n                </xsl:call-template>\n                <span>\n                    <xsl:apply-templates select=\".\" mode=\"type-name\">\n                        <xsl:with-param name=\"string-id\" select=\"'readability-line-height'\"/>\n                    </xsl:apply-templates>\n                </span>\n                <output id=\"ptx-readability-line-height-value\" for=\"ptx-readability-line-height\">1.35</output>\n            </label>\n            <input type=\"range\" id=\"ptx-readability-line-height\" min=\"1.10\" max=\"3\" step=\"0.05\" value=\"1.35\"/>\n        </div>\n        <div class=\"ptx-readability-options-group\">\n            <label class=\"ptx-readability-slider-label\" for=\"ptx-readability-font-size\">\n                <xsl:call-template name=\"insert-symbol\">\n                    <xsl:with-param name=\"name\" select=\"'format_size'\"/>\n                </xsl:call-template>\n                <span>\n                    <xsl:apply-templates select=\".\" mode=\"type-name\">\n                        <xsl:with-param name=\"string-id\" select=\"'readability-content-font-size'\"/>\n                    </xsl:apply-templates>\n                </span>\n                <output id=\"ptx-readability-font-size-value\" for=\"ptx-readability-font-size\">100%</output>\n            </label>\n            <input type=\"range\" id=\"ptx-readability-font-size\" min=\"0.8\" max=\"1.5\" step=\"0.05\" value=\"1\"/>\n        </div>\n        <xsl:if test=\"$b-theme-has-darkmode\">\n            <fieldset class=\"ptx-readability-options-group ptx-readability-options-group-theme\">\n                <legend>\n                    <xsl:apply-templates select=\".\" mode=\"type-name\">\n                        <xsl:with-param name=\"string-id\" select=\"'readability-theme'\"/>\n                    </xsl:apply-templates>\n                </legend>\n                <label for=\"ptx-readability-theme-system\">\n                    <input type=\"radio\" name=\"ptx-readability-theme\" id=\"ptx-readability-theme-system\" value=\"system\"/>\n                    <xsl:call-template name=\"insert-symbol\">\n                        <xsl:with-param name=\"name\" select=\"'brightness_auto'\"/>\n                    </xsl:call-template>\n                    <span>\n                        <xsl:apply-templates select=\".\" mode=\"type-name\">\n                            <xsl:with-param name=\"string-id\" select=\"'readability-theme-system'\"/>\n                        </xsl:apply-templates>\n                    </span>\n                </label>\n                <label for=\"ptx-readability-theme-light\">\n                    <input type=\"radio\" name=\"ptx-readability-theme\" id=\"ptx-readability-theme-light\" value=\"light\"/>\n                    <xsl:call-template name=\"insert-symbol\">\n                        <xsl:with-param name=\"name\" select=\"'light_mode'\"/>\n                    </xsl:call-template>\n                    <span>\n                        <xsl:apply-templates select=\".\" mode=\"type-name\">\n                            <xsl:with-param name=\"string-id\" select=\"'readability-theme-light'\"/>\n                        </xsl:apply-templates>\n                    </span>\n                </label>\n                <label for=\"ptx-readability-theme-dark\">\n                    <input type=\"radio\" name=\"ptx-readability-theme\" id=\"ptx-readability-theme-dark\" value=\"dark\"/>\n                    <xsl:call-template name=\"insert-symbol\">\n                        <xsl:with-param name=\"name\" select=\"'dark_mode'\"/>\n                    </xsl:call-template>\n                    <span>\n                        <xsl:apply-templates select=\".\" mode=\"type-name\">\n                            <xsl:with-param name=\"string-id\" select=\"'readability-theme-dark'\"/>\n                        </xsl:apply-templates>\n                    </span>\n                </label>\n            </fieldset>\n        </xsl:if>\n        <fieldset class=\"ptx-readability-options-group\">\n            <legend>\n                <xsl:apply-templates select=\".\" mode=\"type-name\">\n                    <xsl:with-param name=\"string-id\" select=\"'readability-assistive-technologies'\"/>\n                </xsl:apply-templates>\n            </legend>\n            <label for=\"ptx-readability-accessible-permalinks\">\n                <input type=\"checkbox\" id=\"ptx-readability-accessible-permalinks\"/>\n                <span>🔗</span>\n                <span>\n                    <xsl:apply-templates select=\".\" mode=\"type-name\">\n                        <xsl:with-param name=\"string-id\" select=\"'readability-expose-permalinks'\"/>\n                    </xsl:apply-templates>\n                </span>\n            </label>\n        </fieldset>\n        <div class=\"ptx-readability-options-group\">\n            <button type=\"button\" class=\"ptx-readability-reset-button button\" id=\"ptx-readability-reset-button\">\n                <xsl:call-template name=\"insert-symbol\">\n                    <xsl:with-param name=\"name\" select=\"'restart_alt'\"/>\n                </xsl:call-template>\n                <span class=\"name\">\n                    <xsl:apply-templates select=\".\" mode=\"type-name\">\n                        <xsl:with-param name=\"string-id\" select=\"'reset-all'\"/>\n                    </xsl:apply-templates>\n                </span>\n            </button>\n        </div>\n    </dialog>\n</xsl:template>\n\n<!-- Read-aloud (embedded text-to-speech): a toolbar button, a minimal      -->\n<!-- expanding player (prev, play/pause, next, continue, settings), and the  -->\n<!-- settings dialog that button opens.                                     -->\n<!--                                                                        -->\n<!-- The words below are literal English rather than localization           -->\n<!-- string-ids.  xsl/localizations is for content that reaches more than   -->\n<!-- one output format, and this is an HTML-only control surface.  Nothing  -->\n<!-- here has a LaTeX or EPUB counterpart.  The strings the player *speaks* -->\n<!-- live in js/src/read-aloud/strings.js for the same reason; a            -->\n<!-- JavaScript-side translation layer will eventually address both halves. -->\n<xsl:template name=\"read-aloud-controls\">\n    <button id=\"ptx-read-aloud-button\" class=\"ptx-read-aloud-button button\" title=\"Read aloud\" aria-expanded=\"false\">\n        <xsl:call-template name=\"insert-symbol\">\n            <xsl:with-param name=\"name\" select=\"'text_to_speech'\"/>\n        </xsl:call-template>\n        <span class=\"name\">Read aloud</span>\n    </button>\n    <!-- player-ui.js retitles the toolbar and play/pause buttons as their -->\n    <!-- states change; the titles here are the pre-JavaScript defaults.   -->\n    <div id=\"ptx-read-aloud-player\" class=\"ptx-read-aloud-player\" hidden=\"hidden\" role=\"group\" aria-label=\"Read aloud\">\n        <button id=\"ptx-read-aloud-prev\" class=\"button\" title=\"Previous sentence\">\n            <xsl:call-template name=\"insert-symbol\">\n                <xsl:with-param name=\"name\" select=\"'skip_previous'\"/>\n            </xsl:call-template>\n        </button>\n        <button id=\"ptx-read-aloud-toggle\" class=\"ptx-read-aloud-toggle button\" title=\"Play\">\n            <span class=\"ptx-read-aloud-icon-play\">\n                <xsl:call-template name=\"insert-symbol\">\n                    <xsl:with-param name=\"name\" select=\"'play_arrow'\"/>\n                </xsl:call-template>\n            </span>\n            <span class=\"ptx-read-aloud-icon-pause\">\n                <xsl:call-template name=\"insert-symbol\">\n                    <xsl:with-param name=\"name\" select=\"'pause'\"/>\n                </xsl:call-template>\n            </span>\n        </button>\n        <button id=\"ptx-read-aloud-next\" class=\"button\" title=\"Next sentence\">\n            <xsl:call-template name=\"insert-symbol\">\n                <xsl:with-param name=\"name\" select=\"'skip_next'\"/>\n            </xsl:call-template>\n        </button>\n        <a id=\"ptx-read-aloud-continue\" class=\"ptx-read-aloud-continue button\" hidden=\"hidden\">\n            <xsl:text>Continue</xsl:text>\n            <xsl:call-template name=\"insert-symbol\">\n                <xsl:with-param name=\"name\" select=\"'play_arrow'\"/>\n            </xsl:call-template>\n        </a>\n        <button id=\"ptx-read-aloud-settings-button\" class=\"ptx-read-aloud-settings-button button\" title=\"Reading settings\">\n            <xsl:call-template name=\"insert-symbol\">\n                <xsl:with-param name=\"name\" select=\"'tune'\"/>\n            </xsl:call-template>\n        </button>\n        <!-- No close button: the toolbar button that opened the player is  -->\n        <!-- a disclosure toggle and collapses it again, so a second        -->\n        <!-- dismissal control would only cost space in the navbar row.     -->\n    </div>\n    <!-- Read-aloud settings, opened from the player's own settings button.   -->\n    <!-- Deliberately a sibling of the player rather than a child: the player -->\n    <!-- is a flex row, and a dialog inside it would be a flex item.          -->\n    <dialog class=\"ptx-dialog ptx-read-aloud-settings-popup\" id=\"ptx-read-aloud-settings-popup\">\n        <div class=\"ptx-readability-options-popup-controls\">\n            <h2 class=\"heading\">Read aloud settings</h2>\n            <button class=\"ptx-read-aloud-settings-close-button button\" id=\"ptx-read-aloud-settings-close-button\" title=\"Close\">\n                <xsl:call-template name=\"insert-symbol\">\n                    <xsl:with-param name=\"name\" select=\"'close'\"/>\n                </xsl:call-template>\n            </button>\n        </div>\n        <div class=\"ptx-readability-options-group\">\n            <label for=\"ptx-read-aloud-voice\">\n                <xsl:call-template name=\"insert-symbol\">\n                    <xsl:with-param name=\"name\" select=\"'record_voice_over'\"/>\n                </xsl:call-template>\n                <span>Voice</span>\n            </label>\n            <!-- options populated by settings.js from speechSynthesis.getVoices() -->\n            <select id=\"ptx-read-aloud-voice\"></select>\n            <label class=\"ptx-readability-slider-label\" for=\"ptx-read-aloud-rate\">\n                <xsl:call-template name=\"insert-symbol\">\n                    <xsl:with-param name=\"name\" select=\"'speed'\"/>\n                </xsl:call-template>\n                <span>Reading speed</span>\n                <output id=\"ptx-read-aloud-rate-value\" for=\"ptx-read-aloud-rate\">1×</output>\n            </label>\n            <input type=\"range\" id=\"ptx-read-aloud-rate\" min=\"0.5\" max=\"2\" step=\"0.1\" value=\"1\"/>\n            <label for=\"ptx-read-aloud-asides\">\n                <xsl:call-template name=\"insert-symbol\">\n                    <xsl:with-param name=\"name\" select=\"'unfold_more'\"/>\n                </xsl:call-template>\n                <span>Collapsed content</span>\n            </label>\n            <!-- What happens to a knowl's body once its title is read. -->\n            <select id=\"ptx-read-aloud-asides\">\n                <option value=\"skip\">Announce, do not read</option>\n                <option value=\"read\">Read automatically</option>\n            </select>\n            <label for=\"ptx-read-aloud-autoscroll\">\n                <input type=\"checkbox\" id=\"ptx-read-aloud-autoscroll\" checked=\"checked\"/>\n                <span>Follow along (auto-scroll)</span>\n            </label>\n            <!-- Unchecked by default: this one navigates, so it is opt-in. -->\n            <label for=\"ptx-read-aloud-autocontinue\">\n                <input type=\"checkbox\" id=\"ptx-read-aloud-autocontinue\"/>\n                <span>Continue to the next page automatically</span>\n            </label>\n        </div>\n    </dialog>\n</xsl:template>\n\n<xsl:template name=\"embed-button\">\n    <xsl:variable name=\"embed-localization\">\n        <xsl:apply-templates select=\".\" mode=\"type-name\">\n            <xsl:with-param name=\"string-id\" select=\"'embed'\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <xsl:variable name=\"embed-page-localization\">\n        <xsl:apply-templates select=\".\" mode=\"type-name\">\n            <xsl:with-param name=\"string-id\" select=\"'embed-this-page'\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <xsl:variable name=\"close-embed-localization\">\n        <xsl:apply-templates select=\".\" mode=\"type-name\">\n            <xsl:with-param name=\"string-id\" select=\"'close'\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <xsl:variable name=\"copy-localization\">\n        <xsl:apply-templates select=\".\" mode=\"type-name\">\n            <xsl:with-param name=\"string-id\" select=\"'copy'\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <button id=\"ptx-embed-button\" class=\"ptx-embed-button button\" title=\"{$embed-page-localization}\">\n        <xsl:call-template name=\"insert-symbol\">\n            <xsl:with-param name=\"name\" select=\"'code'\"/>\n        </xsl:call-template>\n        <span class=\"name\">\n            <xsl:value-of select=\"$embed-localization\"/>\n        </span>\n    </button>\n    <dialog class=\"ptx-dialog ptx-embed-popup\" id=\"ptx-embed-popup\">\n        <div class=\"ptx-embed-popup-controls\">\n            <p>Copy the code below to embed this page in your own website or LMS page.</p>\n            <button class=\"ptx-embed-close-button button\" id=\"ptx-embed-close-button\" title=\"{$close-embed-localization}\">\n                <xsl:call-template name=\"insert-symbol\">\n                    <xsl:with-param name=\"name\" select=\"'close'\"/>\n                </xsl:call-template>\n            </button>\n        </div>\n        <div class=\"ptx-embed-code-container\">\n            <textarea class=\"ptx-embed-code-textbox\" id=\"ptx-embed-code-textbox\" readonly=\"true\" aria-label=\"{$embed-localization}\">\n                <iframe src=\"https://example.com/embed\" width=\"100%\" height=\"1000\"></iframe>\n            </textarea>\n            <button autofocus=\"autofocus\" class=\"ptx-embed-copy-button button\" id=\"ptx-embed-copy-button\" title=\"{$copy-localization}\">\n                <xsl:call-template name=\"insert-symbol\">\n                    <xsl:with-param name=\"name\" select=\"'content_copy'\"/>\n                </xsl:call-template>\n                <span class=\"name\">\n                    <xsl:value-of select=\"$copy-localization\"/>\n                </span>\n            </button>\n        </div>\n    </dialog>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"print-button\">\n    <xsl:variable name=\"print-text\">\n        <xsl:apply-templates select=\".\" mode=\"type-name\">\n            <xsl:with-param name=\"string-id\" select=\"'print'\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <button class=\"print-button\" title=\"{$print-text}\" onClick=\"window.print()\">\n        <xsl:call-template name=\"insert-symbol\">\n            <xsl:with-param name=\"name\" select=\"'print'\"/>\n        </xsl:call-template>\n        <span class=\"name\">\n            <xsl:value-of select=\"$print-text\"/>\n        </span>\n    </button>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"print-preview-header\">\n    <div class=\"print-preview-header\">\n        <h2 class=\"print-preview\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'print-preview'\"/>\n            </xsl:apply-templates>\n        </h2>\n        <div class=\"print-controls\">\n            <div class=\"print-controls-toggles\">\n                <xsl:apply-templates select=\".\" mode=\"papersize-toggle\"/>\n                <xsl:apply-templates select=\".\" mode=\"printing-options\"/>\n            </div>\n            <xsl:apply-templates select=\".\" mode=\"print-button\"/>\n        </div>\n    </div>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"papersize-toggle\">\n    <xsl:variable name=\"papersize\">\n        <xsl:apply-templates select=\".\" mode=\"type-name\">\n            <xsl:with-param name=\"string-id\" select=\"'papersize'\"/>\n        </xsl:apply-templates>\n    </xsl:variable>\n    <form class=\"papersize-select\" id=\"papersize-select\">\n        <span class=\"name\"><xsl:value-of select=\"$papersize\"/></span>\n        <label>\n            <input type=\"radio\" name=\"papersize\" value=\"a4\"/>A4\n        </label>\n        <label>\n            <input type=\"radio\" name=\"papersize\" value=\"letter\"/>Letter\n        </label>\n    </form>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"printing-options\">\n    <details class=\"print-options\">\n        <summary>\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'printing-options'\"/>\n            </xsl:apply-templates>\n        </summary>\n        <xsl:apply-templates select=\".\" mode=\"hide-solutions\"/>\n        <xsl:apply-templates select=\".\" mode=\"header-footer-toggles\"/>\n        <xsl:apply-templates select=\".\" mode=\"highlight-workspace-toggle\"/>\n    </details>\n</xsl:template>\n\n<!-- We provide a checkboxes to hide hints, answers, and solution -->\n<!-- but only if the worksheet contains these elements.           -->\n<xsl:template match=\"*\" mode=\"hide-solutions\">\n    <xsl:if test=\".//solution or .//answer or .//hint\">\n        <div class=\"hide-solutions-options\">\n            <xsl:if test=\".//hint\">\n                <div class=\"hide-option\">\n                    <label for=\"hide-hint-checkbox\">\n                        <xsl:apply-templates select=\".\" mode=\"type-name\">\n                            <xsl:with-param name=\"string-id\" select=\"'hide-hints'\"/>\n                        </xsl:apply-templates>\n                    </label>\n                    <input type=\"checkbox\" id=\"hide-hint-checkbox\"/>\n                </div>\n            </xsl:if>\n            <xsl:if test=\".//answer\">\n                <div class=\"hide-option\">\n                    <label for=\"hide-answer-checkbox\">\n                        <xsl:apply-templates select=\".\" mode=\"type-name\">\n                            <xsl:with-param name=\"string-id\" select=\"'hide-answers'\"/>\n                        </xsl:apply-templates>\n                    </label>\n                    <input type=\"checkbox\" id=\"hide-answer-checkbox\"/>\n                </div>\n            </xsl:if>\n            <xsl:if test=\".//solution\">\n                <div class=\"hide-option\">\n                    <label for=\"hide-solution-checkbox\">\n                        <xsl:apply-templates select=\".\" mode=\"type-name\">\n                            <xsl:with-param name=\"string-id\" select=\"'hide-solutions'\"/>\n                        </xsl:apply-templates>\n                    </label>\n                    <input type=\"checkbox\" id=\"hide-solution-checkbox\"/>\n                </div>\n            </xsl:if>\n        </div>\n    </xsl:if>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"header-footer-toggles\">\n    <div class=\"header-footer-options\">\n        <div class=\"header-option\">\n            <span class=\"title\">\n                <xsl:apply-templates select=\".\" mode=\"type-name\">\n                    <xsl:with-param name=\"string-id\" select=\"'print-header'\"/>\n                </xsl:apply-templates>\n            </span>\n            <label>\n                <xsl:apply-templates select=\".\" mode=\"type-name\">\n                    <xsl:with-param name=\"string-id\" select=\"'first-page'\"/>\n                </xsl:apply-templates>\n                <input type=\"checkbox\" id=\"print-first-page-header-checkbox\" checked=\"checked\"/>\n            </label>\n            <label>\n                <xsl:apply-templates select=\".\" mode=\"type-name\">\n                    <xsl:with-param name=\"string-id\" select=\"'running'\"/>\n                </xsl:apply-templates>\n                <input type=\"checkbox\" id=\"print-running-header-checkbox\" checked=\"checked\"/>\n            </label>\n        </div>\n        <div class=\"footer-option\">\n            <span class=\"title\">\n                <xsl:apply-templates select=\".\" mode=\"type-name\">\n                    <xsl:with-param name=\"string-id\" select=\"'print-footer'\"/>\n                </xsl:apply-templates>\n            </span>\n            <label>\n                <xsl:apply-templates select=\".\" mode=\"type-name\">\n                    <xsl:with-param name=\"string-id\" select=\"'first-page'\"/>\n                </xsl:apply-templates>\n                <input type=\"checkbox\" id=\"print-first-page-footer-checkbox\" checked=\"checked\"/>\n            </label>\n            <label>\n                <xsl:apply-templates select=\".\" mode=\"type-name\">\n                    <xsl:with-param name=\"string-id\" select=\"'running'\"/>\n                </xsl:apply-templates>\n                <input type=\"checkbox\" id=\"print-running-footer-checkbox\" checked=\"checked\"/>\n            </label>\n        </div>\n    </div>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"highlight-workspace-toggle\">\n    <div class=\"highlight-workspace-option\">\n        <label for=\"highlight-workspace-checkbox\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'highlight-workspace'\"/>\n            </xsl:apply-templates>\n        </label>\n        <input type=\"checkbox\" id=\"highlight-workspace-checkbox\"/>\n    </div>\n</xsl:template>\n\n<!-- Primary Navigation Panels -->\n<!-- ToC, Prev/Up/Next/Annotation buttons  -->\n<!-- Also organized for small screen modes -->\n<xsl:template match=\"*\" mode=\"primary-navigation\">\n\n    <nav id=\"ptx-navbar\">\n        <xsl:attribute name=\"class\">\n            <xsl:text>ptx-navbar navbar</xsl:text>\n        </xsl:attribute>\n\n        <div class=\"ptx-navbar-contents\">\n            <!-- Pick an ordering for the nav components based on layout needs -->\n            <xsl:apply-templates select=\".\" mode=\"primary-navigation-toc\" />\n            <xsl:apply-templates select=\".\" mode=\"primary-navigation-index\" />\n            <xsl:apply-templates select=\".\" mode=\"primary-navigation-search\" />\n            <xsl:apply-templates select=\".\" mode=\"primary-navigation-other-controls\" />\n            <xsl:apply-templates select=\".\" mode=\"primary-navigation-treebuttons\" />\n            <xsl:apply-templates select=\".\" mode=\"primary-navigation-runestone\" />\n\n            <!-- Annotations button was once here, see GitHub issue -->\n            <!-- https://github.com/rbeezer/mathbook/issues/1010    -->\n        </div>\n    </nav>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"primary-navigation-search\">\n    <xsl:call-template name=\"google-search-box\" />\n    <xsl:call-template name=\"native-search-box\" />\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"primary-navigation-treebuttons\">\n    <!-- Span to encase Prev/Up/Next buttons and float right    -->\n    <!-- Each button gets an id for keypress recognition/action -->\n    <span class=\"treebuttons\">\n        <xsl:apply-templates select=\".\" mode=\"previous-button\"/>\n        <xsl:if test=\"$nav-upbutton='yes'\">\n            <xsl:apply-templates select=\".\" mode=\"up-button\"/>\n        </xsl:if>\n        <xsl:apply-templates select=\".\" mode=\"next-button\"/>\n    </span>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"primary-navigation-runestone\">\n    <!-- Runestone user menu -->\n    <xsl:if test=\"not($b-debug-react) and ($b-host-runestone or $b-has-scratch-activecode)\">\n        <span class=\"nav-runestone-controls\">\n            <!-- A scratch ActiveCode via a pencil icon, always -->\n            <xsl:call-template name=\"runestone-scratch-activecode\"/>\n            <!-- Conditional on a build for Runestone hosting -->\n            <xsl:call-template name=\"runestone-bust-menu\"/>\n        </span>\n    </xsl:if>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"primary-navigation-other-controls\">\n    <span class=\"nav-other-controls\">\n        <!-- Button to show/hide the calculator -->\n        <xsl:if test=\"$b-has-calculator\">\n            <xsl:call-template name=\"calculator-toggle\" />\n            <xsl:call-template name=\"calculator\" />\n        </xsl:if>\n        <!-- Button to show code for embedding in an LMS or webpage  -->\n         <xsl:if test=\"$b-has-embed-button\">\n             <xsl:call-template name=\"embed-button\" />\n        </xsl:if>\n        <!-- Read-aloud button and expanding player  -->\n        <xsl:if test=\"$b-read-aloud\">\n            <xsl:call-template name=\"read-aloud-controls\" />\n        </xsl:if>\n        <xsl:call-template name=\"readability-options\" />\n    </span>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"primary-navigation-index\">\n    <!-- A page either has an/the index as    -->\n    <!-- a child, and gets the \"jump to\" bar, -->\n    <!-- or it deserves an index button       -->\n    <xsl:choose>\n        <xsl:when test=\"index-list\">\n            <xsl:apply-templates select=\".\" mode=\"index-jump-nav\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\".\" mode=\"index-button\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"primary-navigation-toc\">\n    <button id=\"ptx-toc-toggle\" type=\"button\" aria-controls=\"ptx-sidebar\">\n        <xsl:attribute name=\"class\">\n            <xsl:text>toc-toggle button</xsl:text>\n            <xsl:if test=\"$toc-level = 0\">\n                <xsl:text> hidden</xsl:text>\n            </xsl:if>\n        </xsl:attribute>\n        <xsl:attribute name=\"title\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'toc'\"/>\n            </xsl:apply-templates>\n        </xsl:attribute>\n        <xsl:call-template name=\"insert-symbol\">\n            <xsl:with-param name=\"name\" select=\"'menu'\"/>\n        </xsl:call-template>\n        <span class=\"name\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'toc'\"/>\n            </xsl:apply-templates>\n        </span>\n    </button>\n</xsl:template>\n\n<!-- ToC sidebar                                                -->\n<xsl:template match=\"*\" mode=\"sidebars\">\n    <div id=\"ptx-sidebar\" role=\"complementary\">\n        <xsl:attribute name=\"class\">\n            <xsl:text>ptx-sidebar</xsl:text>\n            <xsl:if test=\"$toc-level = 0\">\n                <xsl:text> hidden</xsl:text>\n            </xsl:if>\n        </xsl:attribute>\n        <nav id=\"ptx-toc\" tabindex=\"-1\">\n            <xsl:attribute name=\"aria-label\">\n                <xsl:apply-templates select=\".\" mode=\"type-name\">\n                    <xsl:with-param name=\"string-id\" select=\"'toc'\"/>\n                </xsl:apply-templates>\n            </xsl:attribute>\n            <xsl:attribute name=\"class\">\n                <xsl:text>ptx-toc</xsl:text>\n                <!-- A class indicates how much of the ToC we want   -->\n                <!-- to see, as set in the publication file. Always. -->\n                <xsl:text> depth</xsl:text>\n                <xsl:value-of select=\"$toc-level\"/>\n                <!-- Optionally place a class name to allow for numbering  -->\n                <!-- parts and chapters, when parts are present (w/ space) -->\n                <xsl:if test=\"$b-has-parts\">\n                    <xsl:text> parts</xsl:text>\n                </xsl:if>\n                <xsl:if test=\"$b-html-toc-focused\">\n                    <xsl:text> focused</xsl:text>\n                </xsl:if>\n            </xsl:attribute>\n            <!-- if focused, add info for js to pick up about levels -->\n            <xsl:if test=\"$b-html-toc-focused\">\n                <xsl:attribute name=\"data-preexpanded-levels\">\n                    <xsl:value-of select=\"$html-toc-preexpanded-levels\"/>\n                </xsl:attribute>\n                <xsl:attribute name=\"data-max-levels\">\n                    <xsl:value-of select=\"$toc-level\"/>\n                </xsl:attribute>\n            </xsl:if>\n            <!-- now, all the actual ToC entries -->\n            <xsl:apply-templates select=\".\" mode=\"customized-toc-items\"/>\n        </nav>\n    </div>\n </xsl:template>\n\n<xsl:template name=\"calculator\">\n    <xsl:if test=\"contains($html-calculator,'geogebra')\">\n        <xsl:variable name=\"calculator-localization\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'calculator'\"/>\n            </xsl:apply-templates>\n        </xsl:variable>\n        <dialog id=\"ptx-calculator-container\" class=\"ptx-dialog ptx-calculator-container\" aria-label=\"{$calculator-localization}\">\n            <div id=\"ptx-geogebra-calculator\" class=\"ptx-geogebra-calculator\"></div>\n            <script id=\"ptx-geogebra-calculator-params\">\n                <!-- params for Geogebra that can be set from PTX -->\n                <xsl:text>&#xa;</xsl:text>\n                <xsl:text>let ggbParams = {&#xa;</xsl:text>\n                <xsl:text>    \"appName\": \"</xsl:text>\n                <xsl:value-of select=\"substring-after($html-calculator,'-')\"/>\n                <xsl:text>\"&#xa;</xsl:text>\n                <xsl:text>};&#xa;</xsl:text>\n            </script>\n        </dialog>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- Table of Contents Contents (Items)                            -->\n<!-- This is the pre-computed TOC that is on every page. It will   -->\n<!-- be customized later as it is rendered to each page.           -->\n<xsl:variable name=\"toc-cache-rtf\">\n    <xsl:apply-templates select=\"/\" mode=\"toc-items\"/>\n</xsl:variable>\n\n<xsl:template match=\"*\" mode=\"toc-items\">\n    <!-- start recursion at the top, since the  -->\n    <!-- ToC is global for the whole document   -->\n    <ul class=\"structural toc-item-list\">\n        <xsl:apply-templates select=\"$document-root\" mode=\"toc-item\"/>\n    </ul>\n</xsl:template>\n\n<!-- NB no \"book\", \"article\" -->\n<xsl:template match=\"frontmatter|abstract|frontmatter/colophon|biography|dedication|acknowledgement|preface|contributors|part|chapter|section|subsection|subsubsection|exercises|solutions|reading-questions|references|glossary|worksheet|handout|backmatter|appendix|index|backmatter/colophon\" mode=\"toc-item\">\n    <li>\n        <xsl:apply-templates select=\".\" mode=\"toc-item-properties\"/>\n        <!-- Recurse into children divisions (if any)-->\n        <xsl:variable name=\"child-list\" select=\"frontmatter|abstract|frontmatter/colophon|biography|dedication|acknowledgement|preface|contributors|part|chapter|section|subsection|subsubsection|exercises|solutions|reading-questions|references|glossary|worksheet|handout|backmatter|appendix|index|backmatter/colophon\"/>\n        <xsl:if test=\"$child-list\">\n            <ul>\n                <!-- visible id for element - needed for accessibility wiring -->\n                <xsl:attribute name=\"id\">\n                    <xsl:text>ptx-toc-group-</xsl:text>\n                    <xsl:apply-templates select=\".\" mode=\"unique-id\"/>\n                </xsl:attribute>\n                <!-- copy id of this ui for use in customization pass, will remove there -->\n                <xsl:attribute name=\"uid\">\n                    <xsl:apply-templates select=\".\" mode=\"unique-id\"/>\n                </xsl:attribute>\n                <xsl:attribute name=\"class\">\n                    <xsl:text>structural toc-item-list</xsl:text>\n                </xsl:attribute>\n                <xsl:apply-templates select=\"*\" mode=\"toc-item\"/>\n            </ul>\n        </xsl:if>\n    </li>\n</xsl:template>\n\n<!-- A division companion earns a ToC entry when it is a page -->\n<xsl:template match=\"&DIVISION-COMPANION;\" mode=\"toc-item\">\n    <xsl:variable name=\"chunk\">\n        <xsl:apply-templates select=\".\" mode=\"is-chunk\"/>\n    </xsl:variable>\n    <xsl:if test=\"$chunk = 'true'\">\n        <xsl:variable name=\"the-url\">\n            <xsl:apply-templates select=\".\" mode=\"url\"/>\n        </xsl:variable>\n        <li>\n            <xsl:attribute name=\"class\">\n                <xsl:text>toc-item toc-</xsl:text>\n                <xsl:value-of select=\"local-name()\"/>\n            </xsl:attribute>\n            <!-- copy id of this li for use in customization pass -->\n            <xsl:attribute name=\"uid\">\n                <xsl:value-of select=\"@pi:unique-id\"/>\n            </xsl:attribute>\n            <div class=\"toc-title-box\">\n                <a href=\"{$the-url}\" class=\"internal\">\n                    <span class=\"title\">\n                        <xsl:apply-templates select=\".\" mode=\"division-companion-text\"/>\n                    </span>\n                </a>\n            </div>\n        </li>\n    </xsl:if>\n</xsl:template>\n\n<!-- Recurse through un-interesting elements -->\n<!-- NB: pass along current page -->\n<!-- Will pickup blocks, etc on unstructured divisions while picking up specialized divisions -->\n<xsl:template match=\"*\" mode=\"toc-item\">\n    <xsl:apply-templates select=\"*\" mode=\"toc-item\"/>\n</xsl:template>\n\n<!-- The contents of a division's \"li\" -->\n<xsl:template match=\"*\" mode=\"toc-item-properties\">\n    <xsl:variable name=\"the-url\">\n        <xsl:apply-templates select=\".\" mode=\"url\"/>\n    </xsl:variable>\n    <xsl:variable name=\"the-number\">\n        <xsl:apply-templates select=\".\" mode=\"number\" />\n    </xsl:variable>\n    <xsl:attribute name=\"class\">\n        <xsl:text>toc-item</xsl:text>\n        <xsl:text> toc-</xsl:text><xsl:value-of select=\"translate(local-name(), '/', '-')\"/>\n    </xsl:attribute>\n    <!-- copy id of this li for use in customization pass, will remove there -->\n    <xsl:attribute name=\"uid\">\n        <xsl:value-of select=\"@pi:unique-id\"/>\n    </xsl:attribute>\n    <div class=\"toc-title-box\">\n        <a href=\"{$the-url}\" class=\"internal\">\n            <xsl:if test=\"not($the-number = '')\">\n                <span class=\"codenumber\">\n                    <xsl:value-of select=\"$the-number\" />\n                    <xsl:apply-templates select=\".\" mode=\"division-number-separator\"/>\n                </span>\n                <!-- separating space, only if needed -->\n                <xsl:text> </xsl:text>\n            </xsl:if>\n            <!-- *always* a title for divisions -->\n            <span class=\"title\">\n                <xsl:apply-templates select=\".\" mode=\"title-short\" />\n            </span>\n        </a>\n    </div>\n</xsl:template>\n\n<!-- Table of Contents per-page customization      -->\n<xsl:template match=\"*\" mode=\"customized-toc-items\">\n    <!-- get a copy of the toc-cach that we will decorate -->\n    <xsl:variable name=\"toc-contents-rtf\">\n        <xsl:copy-of select=\"$toc-cache-rtf\"/>\n    </xsl:variable>\n    <xsl:variable name=\"toc-contents\" select=\"exsl:node-set($toc-contents-rtf)\"/>\n\n    <!-- get the unique id of the current page -->\n    <xsl:variable name=\"uid\" select=\"@pi:unique-id\"/>\n    <!-- use that to find the ToC node for that page -->\n    <xsl:variable name=\"this-page-node\" select=\"$toc-contents//*[@uid = $uid]\"/>\n    <!-- ancestor list will allow us to identify when we are in the path to the page -->\n    <xsl:variable name=\"this-page-ancestors\" select=\"$this-page-node/ancestor::*\" />\n\n    <!-- begin copying ToC at root element -->\n    <xsl:apply-templates select=\"$toc-contents\" mode=\"customized-toc-item\">\n        <xsl:with-param name=\"this-page\" select=\"$this-page-node\"/>\n        <xsl:with-param name=\"this-page-ancestors\" select=\"$this-page-ancestors\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- boring element (span, etc...) -->\n<xsl:template match=\"@*|*\" mode=\"customized-toc-item\">\n    <xsl:param name=\"this-page\"/>\n    <xsl:param name=\"this-page-ancestors\"/>\n    <xsl:copy>\n        <!-- process all other attributes, nodes, and text-->\n        <xsl:apply-templates select=\"@*|*|text()\" mode=\"customized-toc-item\">\n            <xsl:with-param name=\"this-page\" select=\"$this-page\"/>\n            <xsl:with-param name=\"this-page-ancestors\" select=\"$this-page-ancestors\"/>\n        </xsl:apply-templates>\n    </xsl:copy>\n</xsl:template>\n\n<!-- items that may need to be customized-->\n<xsl:template match=\"ul|li\" mode=\"customized-toc-item\">\n    <xsl:param name=\"this-page\"/>\n    <xsl:param name=\"this-page-ancestors\"/>\n\n    <!-- root ul in toc should always be considered \"is-ancestor\"     -->\n    <!-- even if there is no active page (e.g. index.html)            -->\n    <xsl:variable name=\"is-ancestor\" select=\"not(ancestor::ul) or count($this-page-ancestors|.) = count($this-page-ancestors)\"/>\n    <xsl:variable name=\"is-page\" select=\"count($this-page|.) = count($this-page)\"/>\n    <xsl:choose>\n        <!-- ToC item contains or is active page -->\n        <xsl:when test=\"$is-ancestor or $is-page\">\n            <!-- need to copy with modified class list -->\n            <xsl:copy>\n                <!-- reconstruct class attr -->\n                <xsl:variable name=\"old-class\" select=\"@class\"/>\n                <xsl:attribute name=\"class\">\n                    <xsl:value-of select=\"$old-class\"/>\n                    <xsl:choose>\n                        <xsl:when test=\"$is-ancestor\">\n                            <xsl:text> contains-active</xsl:text>\n                        </xsl:when>\n                        <xsl:otherwise>\n                            <xsl:text> active</xsl:text>\n                        </xsl:otherwise>\n                    </xsl:choose>\n                </xsl:attribute>\n                <!-- filter the uids and class, process all other attributes, nodes, and text-->\n                <xsl:apply-templates select=\"@*[name() != 'uid' and name() != 'class']|*|text()\" mode=\"customized-toc-item\">\n                    <xsl:with-param name=\"this-page\" select=\"$this-page\"/>\n                    <xsl:with-param name=\"this-page-ancestors\" select=\"$this-page-ancestors\"/>\n                </xsl:apply-templates>\n            </xsl:copy>\n        </xsl:when>\n        <!-- ToC item is not on path to active page, simple copy minus uid-->\n        <xsl:otherwise>\n            <xsl:copy>\n                <xsl:apply-templates select=\"@*[name() != 'uid']|*|text()\" mode=\"customized-toc-item\">\n                    <xsl:with-param name=\"this-page\" select=\"$this-page\"/>\n                    <xsl:with-param name=\"this-page-ancestors\" select=\"$this-page-ancestors\"/>\n                </xsl:apply-templates>\n            </xsl:copy>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- A standalone XML file with ToC necessities  -->\n<!-- Infrastructure for file, initiate recursion -->\n<xsl:template name=\"doc-manifest\">\n    <xsl:if test=\"$b-debug-react\">\n        <exsl:document href=\"doc-manifest.xml\" method=\"xml\" indent=\"yes\" encoding=\"UTF-8\">\n            <toc>\n                <xsl:apply-templates select=\"$document-root\" mode=\"toc-item-list\"/>\n            </toc>\n        </exsl:document>\n    </xsl:if>\n</xsl:template>\n\n<!-- The top-level organization is of two flavors:                  -->\n<!--                                                                -->\n<!-- (1a) For a book with no parts                                  -->\n<!--                                                                -->\n<!-- frontmatter                                                    -->\n<!-- mainmatter                                                     -->\n<!--   chapter                                                      -->\n<!--   chapter                                                      -->\n<!-- backmatter                                                     -->\n<!--                                                                -->\n<!-- (1b) For an article                                            -->\n<!--                                                                -->\n<!-- frontmatter                                                    -->\n<!-- mainmatter                                                     -->\n<!--   section                                                      -->\n<!--   section                                                      -->\n<!-- backmatter                                                     -->\n<!--                                                                -->\n<!-- (2) For a book with parts                                      -->\n<!--                                                                -->\n<!--   frontmatter                                                  -->\n<!--   part                                                         -->\n<!--   part                                                         -->\n<!--   backmatter                                                   -->\n<!--                                                                -->\n<!-- So there are four top-level divisions for the ToC:             -->\n<!--                                                                -->\n<!--   frontmatter, mainmatter, backmatter, part                    -->\n<!--                                                                -->\n<!-- which are always peers.  Then, for example, a book chapter     -->\n<!-- and a book appendix are always at the same depth, parts or     -->\n<!-- not.  The \"mainmatter\" division is a fiction, so not rendered. -->\n\n<xsl:template match=\"article|book\" mode=\"toc-item-list\">\n    <division>\n        <xsl:apply-templates select=\".\" mode=\"doc-manifest-division-attributes\"/>\n        <xsl:choose>\n            <xsl:when test=\"$b-has-parts\">\n                <!-- identical to general recursion below, see comments -->\n                <xsl:apply-templates select=\"*\" mode=\"toc-item-list\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:apply-templates select=\"frontmatter\" mode=\"toc-item-list\"/>\n                <!-- insert a faux \"mainmatter\" division to coordinate the levels -->\n                <!-- of similar divisions, such a chapter and appendix in a book  -->\n                <!-- attributes are sensible defaults                             -->\n                <division type=\"mainmatter\" number=\"\" id=\"mainmatter\">\n                    <!-- form URL of \"mainmatter\" to be the document root -->\n                    <xsl:variable name=\"the-url\">\n                        <xsl:apply-templates select=\".\" mode=\"url\"/>\n                    </xsl:variable>\n                    <xsl:attribute name=\"url\">\n                        <xsl:value-of select=\"$the-url\"/>\n                        <!-- add the HTML id as a fragment identifier when absent, -->\n                        <!-- which is the case where the division is a chunk/page  -->\n                        <xsl:if test=\"not(contains($the-url, '#'))\">\n                            <xsl:text>#</xsl:text>\n                            <xsl:apply-templates select=\".\" mode=\"html-id\"/>\n                        </xsl:if>\n                    </xsl:attribute>\n                    <!-- title not localized, not expected to be displayed -->\n                    <title>Main Matter</title>\n                    <xsl:apply-templates select=\"*[not(self::frontmatter or self::backmatter)]\" mode=\"toc-item-list\"/>\n                </division>\n                <xsl:apply-templates select=\"backmatter\" mode=\"toc-item-list\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </division>\n</xsl:template>\n\n<!-- Every item that could be a TOC entry, mined from the schema. -->\n<xsl:template match=\"frontmatter|frontmatter/colophon|biography|dedication|acknowledgement|preface|contributors|part|chapter|section|subsection|subsubsection|exercises|solutions|reading-questions|references|glossary|worksheet|handout|backmatter|appendix|index|backmatter/colophon\" mode=\"toc-item-list\">\n    <division>\n        <xsl:apply-templates select=\".\" mode=\"doc-manifest-division-attributes\"/>\n        <!-- Recurse into children divisions (if any)                 -->\n        <!-- NB: the select here could match the one above and this   -->\n        <!-- would be much more efficient.  But we may include blocks -->\n        <!-- in the future, which could complicate how this is done   -->\n        <!-- (perhaps a \"block-item\" call right here which recurses   -->\n        <!-- through an entire division? -->\n        <xsl:apply-templates select=\"*\" mode=\"toc-item-list\"/>\n    </division>\n</xsl:template>\n\n<!-- Recurse through un-interesting elements                -->\n<!-- NB: this could be unnecessary in context of note above -->\n<xsl:template match=\"*\" mode=\"toc-item-list\">\n    <xsl:apply-templates select=\"*\" mode=\"toc-item-list\"/>\n</xsl:template>\n\n<!-- Coordinate changes here with faux division, \"mainmatter\", above -->\n<xsl:template match=\"*\" mode=\"doc-manifest-division-attributes\">\n        <xsl:attribute name=\"type\">\n            <xsl:value-of select=\"local-name(.)\"/>\n        </xsl:attribute>\n        <xsl:attribute name=\"number\">\n            <xsl:apply-templates select=\".\" mode=\"number\"/>\n        </xsl:attribute>\n        <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n        <xsl:variable name=\"the-url\">\n            <xsl:apply-templates select=\".\" mode=\"url\"/>\n        </xsl:variable>\n        <xsl:attribute name=\"url\">\n            <xsl:value-of select=\"$the-url\"/>\n            <!-- add the HTML id as a fragment identifier when absent, -->\n            <!-- which is the case where the division is a chunk/page  -->\n            <xsl:if test=\"not(contains($the-url, '#'))\">\n                <xsl:text>#</xsl:text>\n                <xsl:apply-templates select=\".\" mode=\"html-id\"/>\n            </xsl:if>\n        </xsl:attribute>\n        <title>\n            <xsl:apply-templates select=\".\" mode=\"title-short\"/>\n        </title>\n</xsl:template>\n\n<!-- ###### -->\n<!-- Search -->\n<!-- ###### -->\n\n<!-- We build a collection of what Lunr calls \"search documents\" -->\n<!-- as a Javascript object stored in a file.  For Runestone, it -->\n<!-- needs to go in a different directory than the HTML files.   -->\n<xsl:variable name=\"lunr-search-file\">\n    <xsl:if test=\"$b-host-runestone\">\n        <xsl:text>_static/</xsl:text>\n    </xsl:if>\n    <xsl:text>lunr-pretext-search-index.js</xsl:text>\n</xsl:variable>\n\n<xsl:template name=\"search-page-construction\">\n    <!-- The a Javascript file with the Lunr search index (non-portable builds).  -->\n    <exsl:document href=\"{$lunr-search-file}\" method=\"text\" encoding=\"UTF-8\">\n        <xsl:call-template name=\"search-script-contents\"/>\n    </exsl:document>\n</xsl:template>\n\n<xsl:template name=\"embedded-search-construction\">\n    <!-- For portable html builds, we include the contents of what    -->\n    <!-- what would otherwise go in the lunr-search-file inside the   -->\n    <!-- HTML file itself, inside script tags (to be placed as the    -->\n    <!-- last script tag in the body).                                -->\n    <script>\n        <xsl:call-template name=\"search-script-contents\"/>\n    </script>\n</xsl:template>\n\n<xsl:template name=\"search-script-contents\">\n    <!-- The contents of either the lunr-search-page or the script  -->\n    <!-- embedded in HTML. This defines  the raw \"documents\"        -->\n    <!-- of the eventual index, and then converted by Lunr into     -->\n    <!-- a Javascript variable , ptx_lunr_idx.  This index variable -->\n    <!-- is included later in the search page via a script element, -->\n    <!-- for use/consumption by the Lunr search() method.           -->\n    <xsl:text>var ptx_lunr_search_style = \"</xsl:text>\n    <xsl:value-of select=\"$native-search-variant\"/>\n    <xsl:text>\";&#xa;</xsl:text>\n    <!-- the actual search documents in one HUGE variable, then a list -->\n    <xsl:variable name=\"json-docs\">\n        <xsl:apply-templates select=\"$document-root\" mode=\"search-page-docs\"/>\n    </xsl:variable>\n    <xsl:text>var ptx_lunr_docs = [&#xa;</xsl:text>\n    <!-- Strip a trailing comma, and a newline, to be proper JSON -->\n    <xsl:value-of select=\"substring($json-docs, 1, string-length($json-docs) - 2)\"/>\n    <!-- restore newline just stripped -->\n    <xsl:text>&#xa;]&#xa;</xsl:text>\n    <xsl:text>&#xa;</xsl:text>\n    <!-- the Javascript function to make the index -->\n    <xsl:text>var ptx_lunr_idx = lunr(function () {&#xa;</xsl:text>\n    <xsl:text>  this.ref('id')&#xa;</xsl:text>\n    <xsl:text>  this.field('title')&#xa;</xsl:text>\n    <xsl:text>  this.field('body')&#xa;</xsl:text>\n    <xsl:text>  this.metadataWhitelist = ['position']&#xa;</xsl:text>\n    <xsl:text>&#xa;</xsl:text>\n    <xsl:text>  ptx_lunr_docs.forEach(function (doc) {&#xa;</xsl:text>\n    <xsl:text>    this.add(doc)&#xa;</xsl:text>\n    <xsl:text>  }, this)&#xa;</xsl:text>\n    <xsl:text>})&#xa;</xsl:text>\n</xsl:template>\n\n\n<!-- The modal template \"search-page-docs\" traverses the structural   -->\n<!-- elements (divisions), stopping when a division is a chunk of the -->\n<!-- HTML ouput (as configured by the publisher).  A search document  -->\n<!-- is created for the content of such HTML output page.  This is    -->\n<!-- one collection of possible search results, in correspondence     -->\n<!-- with the actual pages of the output, and displayed at level 1    -->\n<!-- (no indentation).  Each such page then gives rise to more        -->\n<!-- detailed results, which are primarily \"blocks\" of the page.      -->\n\n<xsl:template match=\"&STRUCTURAL;\" mode=\"search-page-docs\">\n    <xsl:variable name=\"chunk\">\n        <xsl:apply-templates select=\".\" mode=\"is-chunk\"/>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$chunk = 'true'\">\n            <!-- stop and build a search document for the page,    -->\n            <!-- as a first-level indentation in the outline-style -->\n            <!-- of the search results                             -->\n            <xsl:apply-templates select=\".\" mode=\"search-document\">\n                <xsl:with-param name=\"level\" select=\"'1'\"/>\n            </xsl:apply-templates>\n            <!-- recursively cruise the *children* of the page for   -->\n            <!-- blocks that will be second-level indentation in the -->\n            <!-- outline-style of the search results                 -->\n            <!-- This is where we adjust our priorities on what      -->\n            <!-- becomes a search document, see descriptions of      -->\n            <!-- the modal templates for those priorities.           -->\n            <xsl:choose>\n                <xsl:when test=\"$native-search-variant = 'textbook'\">\n                    <xsl:apply-templates select=\"*\" mode=\"search-block-docs-textbook\"/>\n                </xsl:when>\n                <xsl:when test=\"$native-search-variant = 'reference'\">\n                    <xsl:apply-templates select=\"*\" mode=\"search-block-docs-reference\"/>\n                </xsl:when>\n                <xsl:otherwise/>\n            </xsl:choose>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\"&STRUCTURAL;\" mode=\"search-page-docs\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Textbook search -->\n<!-- The modal \"search-block-docs-textbook\" traverses all the elements      -->\n<!-- (of a page), starting with the children of the page's division,        -->\n<!-- stopping to create a search document for selected blocks. Generally    -->\n<!-- these are elements that admit/display titles. These are assigned       -->\n<!-- level 2, so they can be displayed with an indentation.  We do not      -->\n<!-- recurse into blocks.  So only \"first-class\" paragraphs are considered, -->\n<!-- and only if they have a definition (\"term\" element) within.            -->\n\n<xsl:template match=\"*\" mode=\"search-block-docs-textbook\">\n    <xsl:apply-templates select=\"*\" mode=\"search-block-docs-textbook\"/>\n</xsl:template>\n\n<!-- Note: could add &STRUCTURAL; here in order to make a    -->\n<!-- search-document for each SUBDIVISION on the page/chunk. -->\n<xsl:template match=\"&DEFINITION-LIKE;|&THEOREM-LIKE;|&PROOF-LIKE;|&AXIOM-LIKE;|&REMARK-LIKE;|&COMPUTATION-LIKE;|&OPENPROBLEM-LIKE;|&EXAMPLE-LIKE;|&PROJECT-LIKE;|&GOAL-LIKE;|&FIGURE-LIKE;|exercise|p[descendant::term]\" mode=\"search-block-docs-textbook\">\n    <!-- build a search document and dead-end -->\n    <xsl:apply-templates select=\".\" mode=\"search-document\">\n        <xsl:with-param name=\"level\" select=\"'2'\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Reference search -->\n<!-- The modal \"search-block-docs-textbook\" traverses all the elements -->\n<!-- (of a page), starting with the children of the page's division,   -->\n<!-- stopping to create a search document for subdivisions, blocks,    -->\n<!-- and first-class paragraphs (plus block quotes and pre-formatted   -->\n<!-- paragraphs.  This relies more on division structure, and *all*    -->\n<!-- of the content.                                                   -->\n\n<xsl:template match=\"*\" mode=\"search-block-docs-reference\">\n    <xsl:apply-templates select=\"*\" mode=\"search-block-docs-reference\"/>\n</xsl:template>\n\n<xsl:template match=\"&STRUCTURAL;|&DEFINITION-LIKE;|&THEOREM-LIKE;|&PROOF-LIKE;|&AXIOM-LIKE;|&REMARK-LIKE;|&COMPUTATION-LIKE;|&OPENPROBLEM-LIKE;|&EXAMPLE-LIKE;|&PROJECT-LIKE;|&GOAL-LIKE;|&FIGURE-LIKE;|exercise|p|blockquote|pre\" mode=\"search-block-docs-reference\">\n    <!-- build a search document and dead-end -->\n    <xsl:apply-templates select=\".\" mode=\"search-document\">\n        <xsl:with-param name=\"level\" select=\"'2'\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- For any node, be it a page or a block, a \"search document\"  -->\n<!-- data structure is created, the actual content is realized   -->\n<!-- by the \"search-node-text\" template, which is designed to be -->\n<!-- overridden in some situations.  The level comes in as a     -->\n<!-- parameter and is recorded in the data structure.            -->\n\n<xsl:template match=\"*\" mode=\"search-document\">\n    <xsl:param name=\"level\"/>\n\n    <!-- With \"textbook\" search, paragraphs using a \"term\" -->\n    <!-- to make a definition have some exceptions below.  -->\n    <xsl:variable name=\"b-is-definition-paragraph\"\n                  select=\"($native-search-variant = 'textbook') and self::p and descendant::term\"/>\n\n    <xsl:text>{&#xa;</xsl:text>\n    <!-- string to identify results with original docs -->\n    <xsl:text>  \"id\": \"</xsl:text>\n    <xsl:call-template name=\"escape-json-string\">\n        <xsl:with-param name=\"text\">\n            <xsl:apply-templates select=\".\" mode=\"html-id\"/>\n        </xsl:with-param>\n    </xsl:call-template>\n    <xsl:text>\",&#xa;</xsl:text>\n    <!-- level 2 indicates need for indentation -->\n    <xsl:text>  \"level\": \"</xsl:text>\n    <xsl:value-of select=\"$level\"/>\n    <xsl:text>\",&#xa;</xsl:text>\n    <!-- filename relative to search page -->\n    <xsl:text>  \"url\": \"</xsl:text>\n    <xsl:call-template name=\"escape-json-string\">\n        <xsl:with-param name=\"text\">\n            <xsl:apply-templates select=\".\" mode=\"url\"/>\n        </xsl:with-param>\n    </xsl:call-template>\n    <xsl:text>\",&#xa;</xsl:text>\n    <!-- the type of the division -->\n    <xsl:text>  \"type\": \"</xsl:text>\n    <xsl:call-template name=\"escape-json-string\">\n        <xsl:with-param name=\"text\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\"/>\n        </xsl:with-param>\n    </xsl:call-template>\n    <xsl:if test=\"$b-is-definition-paragraph\">\n        <xsl:text> (with a defined term)</xsl:text>\n    </xsl:if>\n    <xsl:text>\",&#xa;</xsl:text>\n    <!-- the number of the division -->\n    <xsl:text>  \"number\": \"</xsl:text>\n    <xsl:call-template name=\"escape-json-string\">\n        <xsl:with-param name=\"text\">\n            <xsl:apply-templates select=\".\" mode=\"number\"/>\n        </xsl:with-param>\n    </xsl:call-template>\n    <xsl:text>\",&#xa;</xsl:text>\n    <!-- title of division that is a page -->\n    <xsl:text>  \"title\": \"</xsl:text>\n    <!-- title might have HTML markup          -->\n    <!-- e.g. emphasis, span.process-math      -->\n    <!-- RTF -> node-set ->  serialized string -->\n    <xsl:variable name=\"title-html\">\n        <xsl:apply-templates select=\".\" mode=\"title-full\"/>\n    </xsl:variable>\n    <xsl:call-template name=\"escape-json-string\">\n        <xsl:with-param name=\"text\">\n            <xsl:apply-templates select=\"exsl:node-set($title-html)\" mode=\"xml-to-string\"/>\n        </xsl:with-param>\n    </xsl:call-template>\n    <xsl:text>\",&#xa;</xsl:text>\n    <!-- all text on the page, more or less, duplicates title -->\n    <xsl:text>  \"body\": \"</xsl:text>\n    <!-- Some elements need special treatment, for specific forms of   -->\n    <!-- search, when they *are* the search document, rather than when -->\n    <!-- they are *a part of* some other larger search document.  We   -->\n    <!-- intercept them here, most-specific first.                     -->\n    <xsl:choose>\n        <!-- \"textbook\" search treats first-class -->\n        <!-- paragraphs with a term specially     -->\n        <xsl:when test=\"$b-is-definition-paragraph\">\n            <xsl:apply-templates select=\".\" mode=\"search-term-paragraph-text\"/>\n        </xsl:when>\n        <!-- for most elements, just extract text -->\n        <!-- nodes with various adjustments       -->\n        <xsl:otherwise>\n            <xsl:apply-templates select=\".\" mode=\"search-node-text\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n    <!-- text here, sanitized -->\n    <xsl:text>\"&#xa;</xsl:text>\n    <!-- NB: final comma AND newline are stripped above -->\n    <xsl:text>},&#xa;</xsl:text>\n</xsl:template>\n\n<!-- The \"search-node-text\" templates basically recurses into elements -->\n<!-- with no effect and duplicate the text() nodes, properly escaped   -->\n<!-- for use in a big old JSON data structure.  This is the place to   -->\n<!-- make adjustments by ignoring or modifying certain aspects of the  -->\n<!-- content of an element.                                            -->\n\n<xsl:template match=\"*\" mode=\"search-node-text\">\n    <xsl:apply-templates select=\"node()\" mode=\"search-node-text\"/>\n</xsl:template>\n\n<!-- \"Generators\" need content, LaTeX and TeX avoid goofy CSS -->\n<xsl:template match=\"pretext|webwork[not(node())]\" mode=\"search-node-text\">\n    <xsl:apply-templates select=\".\"/>\n    <xsl:text> </xsl:text>\n</xsl:template>\n<xsl:template match=\"latex\" mode=\"search-node-text\">\n    <xsl:text>latex </xsl:text>\n</xsl:template>\n<xsl:template match=\"tex\" mode=\"search-node-text\">\n    <xsl:text>tex </xsl:text>\n</xsl:template>\n<xsl:template match=\"copyright\" mode=\"search-node-text\">\n    <xsl:text>copyright </xsl:text>\n</xsl:template>\n<xsl:template match=\"copyleft\" mode=\"search-node-text\">\n    <xsl:text>copyleft </xsl:text>\n</xsl:template>\n\n<!-- tags need angle brackets -->\n<!-- Empty tag version needs JSON escaping, otherwise -->\n<!-- this shouldn't be necessary - but for tag abuse. -->\n<xsl:template match=\"tag|tage\" mode=\"search-node-text\">\n    <xsl:call-template name=\"escape-json-string\">\n        <xsl:with-param name=\"text\">\n            <xsl:text>&lt;</xsl:text>\n            <xsl:value-of select=\"text()\"/>\n            <xsl:if test=\"self::tage\">\n                <xsl:text>/</xsl:text>\n            </xsl:if>\n            <xsl:text>&gt; </xsl:text>\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- First-class paragraphs (children of divisions or \"paragraphs\",    -->\n<!-- and not in blocks) containing \"term\" are considered differently   -->\n<!-- in a textbook search.  Without a \"term\" they are ignored, while   -->\n<!-- with \"term\" the search document is just the content of the terms. -->\n<xsl:template match=\"p[descendant::term]\" mode=\"search-term-paragraph-text\">\n    <xsl:apply-templates select=\".//term\" mode=\"search-node-text\"/>\n</xsl:template>\n\n<!-- Lots of stuff can make very misleading search documents. -->\n<!-- Examples have included: \"\\subset\" in math and \"limits\"   -->\n<!-- in a WW problem to specify a domain.  So we kill stuff.  -->\n\n<xsl:template match=\"m|md[mrow]\" mode=\"search-node-text\"/>\n<xsl:template match=\"latex-image|asymptote|sageplot\" mode=\"search-node-text\"/>\n<xsl:template match=\"sage\" mode=\"search-node-text\"/>\n<!-- \"slate\" in an \"interactive\" can have JS code, GeoGebra too, etc -->\n<xsl:template match=\"interactive\" mode=\"search-node-text\"/>\n\n<!-- WeBWorK exercises, as output of the pre-processor, include    -->\n<!-- a \"webwork-reps\" element with three elements:                 -->\n<!--                                                               -->\n<!--   \"static\": meant for LaTeX, but we *will* index this version -->\n<!--   \"server-data\": base64 versions, empty element with just     -->\n<!--                  attributes, so harmless for search           -->\n<!--   \"pg\": native WW version (for problem archives), which will  -->\n<!--         be misleading                                         -->\n<!--                                                               -->\n<!-- NB: ideally the \"pg\" version will not make it here after some -->\n<!-- pre-processor work.  Parsing \"static\" in the pre-processor    -->\n<!-- and labeling the result with a \"pi:\" prefix would make sense. -->\n<xsl:template match=\"pg\" mode=\"search-node-text\"/>\n\n<!--\nTODO:\n  hints, answers, solutions (only if elected by publisher in text)\n-->\n\n<xsl:template match=\"text()\" mode=\"search-node-text\">\n    <xsl:choose>\n        <!-- collapse authored whitespace, and structural whitespace -->\n        <!-- that is being preserved with whitespace declarations    -->\n        <!-- Replaced by universal addition at end of the template.  -->\n        <!-- Reduces file size by 40%. (sample article)              -->\n        <xsl:when test=\"normalize-space() = ''\"/>\n        <xsl:otherwise>\n            <xsl:call-template name=\"escape-json-string\">\n                <!-- normalize-space adds another 2% reduction -->\n                <xsl:with-param name=\"text\" select=\"normalize-space(.)\"/>\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n    <!-- a space seems necessary to separate some text() nodes, -->\n    <!-- like consecutive (simple) list items.  Presumably it   -->\n    <!-- can't hurt to have too many?                           -->\n    <xsl:text> </xsl:text>\n</xsl:template>\n\n\n<!-- Feedback Button goes in page-footer                -->\n<!-- Values of variables set in publisher-variables.xsl -->\n<!-- Context influences default button text language    -->\n<xsl:template match=\"*\" mode=\"feedback-button\">\n    <xsl:if test=\"$b-has-feedback-button\">\n        <a class=\"feedback-link\" href=\"{$feedback-button-href}\" target=\"_blank\">\n            <xsl:choose>\n                <xsl:when test=\"not($feedback-button-text = '')\">\n                    <xsl:value-of select=\"$feedback-button-text\" />\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:apply-templates select=\".\" mode=\"type-name\">\n                        <xsl:with-param name=\"string-id\" select=\"'feedback'\"/>\n                    </xsl:apply-templates>\n                </xsl:otherwise>\n            </xsl:choose>\n        </a>\n    </xsl:if>\n</xsl:template>\n\n<!-- Branding in page-footer, mostly hard-coded     -->\n<!-- HTTPS for authors delivering from secure sites -->\n<xsl:template name=\"pretext-link\">\n    <a class=\"pretext-link\" href=\"https://pretextbook.org\" title=\"PreTeXt\">\n        <div class=\"logo\">\n            <!-- explicitly only have a height here to prevent rendering issue in Safari -->\n            <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"100%\" viewBox=\"338 3000 8772 6866\" role=\"img\">\n            <!-- Use @role=\"img\" and <title> elements for accessibility -->\n                <title>PreTeXt logo</title>\n                <g style=\"stroke-width:.025in; stroke:currentColor; fill:none\">\n                    <polyline points=\"472,3590 472,9732 \" style=\"stroke-width:174; stroke-linejoin:miter; stroke-linecap:round; \"/>\n                    <path style=\"stroke-width:126;stroke-linecap:butt;\"  d=\"M 4724,9448 A 4660 4660  0  0  1  8598  9259\"/>\n                    <path style=\"stroke-width:174;stroke-linecap:butt;\"  d=\"M 4488,9685 A 4228 4228  0  0  0   472  9732\"/>\n                    <path style=\"stroke-width:126;stroke-linecap:butt;\"  d=\"M 4724,3590 A 4241 4241  0  0  1  8598  3496\"/>\n                    <path style=\"stroke-width:126;stroke-linecap:round;\" d=\"M 850,3496  A 4241 4241  0  0  1  4724  3590\"/>\n                    <path style=\"stroke-width:126;stroke-linecap:round;\" d=\"M 850,9259  A 4507 4507  0  0  1  4724  9448\"/>\n                    <polyline points=\"5385,4299 4062,8125\"           style=\"stroke-width:300; stroke-linejoin:miter; stroke-linecap:round;\"/>\n                    <polyline points=\"8598,3496 8598,9259\"           style=\"stroke-width:126; stroke-linejoin:miter; stroke-linecap:round;\"/>\n                    <polyline points=\"850,3496 850,9259\"             style=\"stroke-width:126; stroke-linejoin:miter; stroke-linecap:round;\"/>\n                    <polyline points=\"4960,9685 4488,9685\"           style=\"stroke-width:174; stroke-linejoin:miter; stroke-linecap:round;\"/>\n                    <polyline points=\"3070,4582 1889,6141 3070,7700\" style=\"stroke-width:300; stroke-linejoin:miter; stroke-linecap:round;\"/>\n                    <polyline points=\"6418,4582 7600,6141 6418,7700\" style=\"stroke-width:300; stroke-linejoin:miter; stroke-linecap:round;\"/>\n                    <polyline points=\"8976,3590 8976,9732\"           style=\"stroke-width:174; stroke-linejoin:miter; stroke-linecap:round;\"/>\n                    <path style=\"stroke-width:174;stroke-linecap:butt;\" d=\"M 4960,9685 A 4228 4228  0  0  1  8976  9732\"/>\n                </g>\n            </svg>\n        </div>\n    </a>\n</xsl:template>\n\n<xsl:template name=\"runestone-link\">\n    <a class=\"runestone-link\" href=\"https://runestone.academy\" title=\"Runestone Academy\">\n        <img class=\"logo\" src=\"https://runestone.academy/runestone/static/images/RAIcon_cropped.png\" alt=\"Runstone Academy logo\"/>\n    </a>\n</xsl:template>\n\n<xsl:template name=\"mathjax-link\">\n    <a class=\"mathjax-link\" href=\"https://www.mathjax.org\" title=\"MathJax\">\n        <img class=\"logo\" src=\"https://www.mathjax.org/badge/badge-square-2.png\" alt=\"MathJax logo\"/>\n    </a>\n</xsl:template>\n\n<!-- Runestone build only, revenue generator -->\n<xsl:template name=\"runestone-ethical-ads\">\n    <xsl:if test=\"$b-host-runestone\">\n        <xsl:text>{% if show_ethical_ad %}</xsl:text>\n        <div style=\"width: 100%\">\n            <div data-ea-publisher=\"runestoneacademy\" data-ea-type=\"image\" style=\"display: flex; justify-content: center\"/>\n        </div>\n        <xsl:text>{% endif %}</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<!-- Tooltip Text -->\n<!-- Text for an HTML \"title\" attribute      -->\n<!-- Always leverage the PreTeXt title, e.g. -->\n<!-- don't use \"caption\", it could be BIG    -->\n<xsl:template match=\"*\" mode=\"tooltip-text\">\n    <xsl:apply-templates select=\".\" mode=\"type-name\" />\n    <xsl:variable name=\"num\">\n        <xsl:apply-templates select=\".\" mode=\"number\" />\n    </xsl:variable>\n    <xsl:if test=\"not($num = '')\">\n        <xsl:text> </xsl:text>\n        <xsl:value-of select=\"$num\" />\n    </xsl:if>\n    <xsl:if test=\"title\">\n        <xsl:text>: </xsl:text>\n        <xsl:apply-templates select=\".\" mode=\"title-plain\" />\n    </xsl:if>\n</xsl:template>\n\n<!-- MathJax header                                             -->\n<!-- XML manages equation numbers                               -->\n<!-- Config MathJax to make anchor names on equations           -->\n<!--   these are just the contents of the \\label on an equation -->\n<!--   which we provide as the xml:id of the equation           -->\n<!-- Note: we could set \\label with something different         -->\n<!-- extpfeil.js provides extensible arrows: \\xmapsto, \\xtofrom -->\n<!--   \\xtwoheadrightarrow, \\xtwoheadleftarrow, \\xlongequal     -->\n<!--   equivalent to the LaTeX package of the same name         -->\n<!-- Autobold extension is critical for captions (bold'ed) that -->\n<!-- have mathematics in them (suggested by P. Krautzberger)    -->\n<xsl:template name=\"mathjax\">\n    <!-- MathJax 4 configuration via JavaScript module -->\n    <script type=\"module\">\n        <!-- A module specifier is either an absolute URL or a relative      -->\n        <!-- reference beginning \"/\", \"./\", or \"../\" - a bare path will not  -->\n        <!-- resolve.  So a local build, where \"html.js.dir\" is relative,    -->\n        <!-- needs the \"./\", while a CDN build, where the prefix has already -->\n        <!-- made it absolute, must not have it: the \"./\" would make the     -->\n        <!-- whole URL relative to the page.                                 -->\n        <xsl:text>import { startMathJax } from '</xsl:text>\n        <xsl:if test=\"$cdn-prefix = ''\">\n            <xsl:text>./</xsl:text>\n        </xsl:if>\n        <xsl:value-of select=\"$html.js.dir\"/>\n        <xsl:text>/mathjax_startup.js';&#xa;</xsl:text>\n        <xsl:text>startMathJax({&#xa;</xsl:text>\n            <xsl:text>hasWebworkReps: </xsl:text><xsl:value-of select=\"$b-has-webwork-reps\"/><xsl:text>,&#xa;</xsl:text>\n            <xsl:text>hasSage: </xsl:text><xsl:value-of select=\"$b-has-sage\"/><xsl:text>,&#xa;</xsl:text>\n            <xsl:text>isReact: </xsl:text><xsl:value-of select=\"$b-debug-react\"/><xsl:text>,&#xa;</xsl:text>\n            <xsl:text>htmlPresentation: </xsl:text><xsl:value-of select=\"$b-html-presentation\"/><xsl:text>,&#xa;</xsl:text>\n            <!-- Added to support read-aloud functionality; shouldn't hurt anything else -->\n            <xsl:text>lang: \"</xsl:text><xsl:value-of select=\"$document-language\"/><xsl:text>\",&#xa;</xsl:text>\n        <xsl:text>});&#xa;</xsl:text>\n    </script>\n    <!-- MathJax 4 CDN -->\n    <script defer=\"true\">\n        <xsl:attribute name=\"src\">\n            <xsl:text>https://cdn.jsdelivr.net/npm/mathjax@4/</xsl:text>\n            <xsl:choose>\n                <xsl:when test=\"$debug.mathjax.svg = 'yes'\">\n                    <xsl:text>tex-svg.js</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:text>tex-mml-chtml.js</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:attribute>\n    </script>\n</xsl:template>\n\n<!-- SageCell Javascript-->\n<!-- We never know if a Sage cell might be inside a knowl, -->\n<!-- so we load the relevant JavaScript onto every page if -->\n<!-- a cell occurs *anywhere* in the entire document       -->\n<xsl:template name=\"sagecell-code\">\n    <xsl:if test=\"$b-has-sage\">\n        <script src=\"https://sagecell.sagemath.org/static/embedded_sagecell.js\"></script>\n    </xsl:if>\n</xsl:template>\n\n<!-- Sage Cell Setup -->\n<!-- TODO: internationalize button labels, strings below -->\n<!-- TODO: make an initialization cell which links with the sage-compute cells -->\n\n<!-- A template for a generic makeSageCell script element -->\n<!-- Parameters: language, evaluate-button text -->\n<xsl:template name=\"makesagecell\">\n    <xsl:param name=\"language-attribute\" />\n    <xsl:param name=\"b-autoeval\" select=\"false()\"/>\n    <xsl:param name=\"language-text\" />\n\n    <xsl:element name=\"script\">\n        <xsl:text>// Make *any* div with class '</xsl:text>\n        <xsl:call-template name=\"sagecell-class-name\">\n            <xsl:with-param name=\"language-attribute\" select=\"$language-attribute\"/>\n            <xsl:with-param name=\"b-autoeval\" select=\"$b-autoeval\"/>\n        </xsl:call-template>\n        <xsl:text>' an executable Sage cell&#xa;</xsl:text>\n        <xsl:text>// Their results will be linked, only within language type&#xa;</xsl:text>\n        <xsl:text>sagecell.makeSagecell(</xsl:text>\n        <xsl:call-template name=\"json\">\n            <xsl:with-param name=\"content\">\n                <map xmlns=\"http://www.w3.org/2005/xpath-functions\">\n                    <string key=\"inputLocation\">\n                        <xsl:text>div.</xsl:text>\n                        <xsl:call-template name=\"sagecell-class-name\">\n                            <xsl:with-param name=\"language-attribute\" select=\"$language-attribute\"/>\n                            <xsl:with-param name=\"b-autoeval\" select=\"$b-autoeval\"/>\n                        </xsl:call-template>\n                    </string>\n                    <boolean key=\"linked\">true</boolean>\n                    <string key=\"linkKey\">\n                        <xsl:text>linked-</xsl:text>\n                        <xsl:value-of select=\"$language-attribute\" />\n                    </string>\n                    <boolean key=\"autoeval\">\n                        <xsl:value-of select=\"$b-autoeval\"/>\n                    </boolean>\n                    <array key=\"languages\">\n                        <string>\n                            <xsl:value-of select=\"$language-attribute\" />\n                        </string>\n                    </array>\n                    <string key=\"evalButtonText\">\n                        <xsl:apply-templates select=\".\" mode=\"type-name\">\n                            <xsl:with-param name=\"string-id\" select=\"'evaluate'\"/>\n                        </xsl:apply-templates>\n                        <xsl:text> (</xsl:text>\n                        <xsl:value-of select=\"$language-text\" />\n                        <xsl:text>)</xsl:text>\n                    </string>\n                    <xsl:if test=\"$b-autoeval\">\n                        <array key=\"hide\">\n                            <string>evalButton</string>\n                        </array>\n                    </xsl:if>\n                </map>\n            </xsl:with-param>\n        </xsl:call-template>\n        <xsl:text>);&#xa;</xsl:text>\n    </xsl:element>\n</xsl:template>\n\n<!-- template for a \"display only\" version -->\n<xsl:template name=\"sagecell-display\">\n    <xsl:element name=\"script\">\n        <xsl:text>// Make *any* div with class 'sage-display' a visible, uneditable Sage cell&#xa;</xsl:text>\n        <xsl:text>sagecell.makeSagecell(</xsl:text>\n        <xsl:call-template name=\"json\">\n            <xsl:with-param name=\"content\">\n                <map xmlns=\"http://www.w3.org/2005/xpath-functions\">\n                    <string key=\"inputLocation\">div.sage-display</string>\n                    <string key=\"editor\">codemirror-readonly</string>\n                    <array key=\"hide\">\n                        <string>evalButton</string>\n                        <string>editorToggle</string>\n                        <string>language</string>\n                    </array>\n                </map>\n            </xsl:with-param>\n        </xsl:call-template>\n        <xsl:text>);&#xa;</xsl:text>\n    </xsl:element>\n</xsl:template>\n\n<!-- All languages, linked only to similar   -->\n<!-- Generic button, drop-down for languages -->\n<xsl:template name=\"sagecell-practice\">\n    <xsl:element name=\"script\">\n        <xsl:text>// Make *any* div with class 'sagecell-practice' an executable Sage cell&#xa;</xsl:text>\n        <xsl:text>// Their results will be linked, only within language type&#xa;</xsl:text>\n        <xsl:text>sagecell.makeSagecell(</xsl:text>\n        <xsl:call-template name=\"json\">\n            <xsl:with-param name=\"content\">\n                <map xmlns=\"http://www.w3.org/2005/xpath-functions\">\n                    <string key=\"inputLocation\">div.sagecell-practice</string>\n                    <boolean key=\"linked\">true</boolean>\n                    <string key=\"evalButtonText\">\n                        <xsl:apply-templates select=\".\" mode=\"type-name\">\n                            <xsl:with-param name=\"string-id\" select=\"'evaluate'\"/>\n                        </xsl:apply-templates>\n                    </string>\n                    <!-- drop-down allows practice with all possible languages -->\n                    <raw key=\"languages\">sagecell.allLanguages</raw>\n                </map>\n            </xsl:with-param>\n        </xsl:call-template>\n        <xsl:text>);&#xa;</xsl:text>\n    </xsl:element>\n</xsl:template>\n\n\n<!-- Make Sage Cell Server headers on a per-language basis -->\n<!-- Examine the subtree of the page, which can still be   -->\n<!-- excessive for summary pages, so room for improvement  -->\n<!-- Note: this template employs the context given in a    -->\n<!-- \"select\" attribute so that only the Javascript        -->\n<!-- necessary for a page is invoked.  Further,            -->\n<!-- cross-reference knowls also have these bits of set-up -->\n<!-- javascript, but only for what the knowl content needs.-->\n<xsl:template match=\"*\" mode=\"sagecell\">\n    <!-- only check for all the special types if there is actually a sage element -->\n    <xsl:if test=\"$b-has-sage\">\n        <!-- special types -->\n        <xsl:if test=\".//sage[@type='display']\">\n            <xsl:call-template name=\"sagecell-display\" />\n        </xsl:if>\n\n        <xsl:if test=\".//sage[@type='practice']\">\n            <xsl:call-template name=\"sagecell-practice\" />\n        </xsl:if>\n\n        <!-- 2016-06-13: sage, gap, gp, html, maxima, octave, python, r, and singular -->\n        <!-- 2024-02-07: add macaulay2                                                -->\n\n        <xsl:if test=\".//sage[not(@type) and (not(@language) or @language='sage') and not(@auto-evaluate = 'yes')]\">\n            <xsl:call-template name=\"makesagecell\">\n                <xsl:with-param name=\"language-attribute\">\n                    <xsl:text>sage</xsl:text>\n                </xsl:with-param>\n                <xsl:with-param name=\"b-autoeval\" select=\"false()\"/>\n                <xsl:with-param name=\"language-text\">Sage</xsl:with-param>\n            </xsl:call-template>\n        </xsl:if>\n\n        <xsl:if test=\".//sage[not(@type) and (not(@language) or @language='sage') and (@auto-evaluate = 'yes')]\">\n            <xsl:call-template name=\"makesagecell\">\n                <xsl:with-param name=\"language-attribute\">\n                    <xsl:text>sage</xsl:text>\n                </xsl:with-param>\n                <xsl:with-param name=\"b-autoeval\" select=\"true()\"/>\n                <xsl:with-param name=\"language-text\">Sage</xsl:with-param>\n            </xsl:call-template>\n        </xsl:if>\n\n        <xsl:if test=\".//sage[@language='gap' and not(@auto-evaluate = 'yes')]\">\n            <xsl:call-template name=\"makesagecell\">\n                <xsl:with-param name=\"language-attribute\">\n                    <xsl:text>gap</xsl:text>\n                </xsl:with-param>\n                <xsl:with-param name=\"b-autoeval\" select=\"false()\"/>\n                <xsl:with-param name=\"language-text\">GAP</xsl:with-param>\n            </xsl:call-template>\n        </xsl:if>\n\n        <xsl:if test=\".//sage[@language='gap' and (@auto-evaluate = 'yes')]\">\n            <xsl:call-template name=\"makesagecell\">\n                <xsl:with-param name=\"language-attribute\">\n                    <xsl:text>gap</xsl:text>\n                </xsl:with-param>\n                <xsl:with-param name=\"b-autoeval\" select=\"true()\"/>\n                <xsl:with-param name=\"language-text\">GAP</xsl:with-param>\n            </xsl:call-template>\n        </xsl:if>\n\n        <xsl:if test=\".//sage[@language='gp' and not(@auto-evaluate = 'yes')]\">\n            <xsl:call-template name=\"makesagecell\">\n                <xsl:with-param name=\"language-attribute\">\n                    <xsl:text>gp</xsl:text>\n                </xsl:with-param>\n                <xsl:with-param name=\"b-autoeval\" select=\"false()\"/>\n                <xsl:with-param name=\"language-text\">GP</xsl:with-param>\n            </xsl:call-template>\n        </xsl:if>\n\n        <xsl:if test=\".//sage[@language='gp' and (@auto-evaluate = 'yes')]\">\n            <xsl:call-template name=\"makesagecell\">\n                <xsl:with-param name=\"language-attribute\">\n                    <xsl:text>gp</xsl:text>\n                </xsl:with-param>\n                <xsl:with-param name=\"b-autoeval\" select=\"true()\"/>\n                <xsl:with-param name=\"language-text\">GP</xsl:with-param>\n            </xsl:call-template>\n        </xsl:if>\n\n        <xsl:if test=\".//sage[@language='html' and not(@auto-evaluate = 'yes')]\">\n            <xsl:call-template name=\"makesagecell\">\n                <xsl:with-param name=\"language-attribute\">\n                    <xsl:text>html</xsl:text>\n                </xsl:with-param>\n                <xsl:with-param name=\"b-autoeval\" select=\"false()\"/>\n                <xsl:with-param name=\"language-text\">HTML</xsl:with-param>\n            </xsl:call-template>\n        </xsl:if>\n\n        <xsl:if test=\".//sage[@language='html' and (@auto-evaluate = 'yes')]\">\n            <xsl:call-template name=\"makesagecell\">\n                <xsl:with-param name=\"language-attribute\">\n                    <xsl:text>html</xsl:text>\n                </xsl:with-param>\n                <xsl:with-param name=\"b-autoeval\" select=\"true()\"/>\n                <xsl:with-param name=\"language-text\">HTML</xsl:with-param>\n            </xsl:call-template>\n        </xsl:if>\n\n        <xsl:if test=\".//sage[@language='macaulay2' and not(@auto-evaluate = 'yes')]\">\n            <xsl:call-template name=\"makesagecell\">\n                <xsl:with-param name=\"language-attribute\">\n                    <xsl:text>macaulay2</xsl:text>\n                </xsl:with-param>\n                <xsl:with-param name=\"b-autoeval\" select=\"false()\"/>\n                <xsl:with-param name=\"language-text\">Macaulay2</xsl:with-param>\n            </xsl:call-template>\n        </xsl:if>\n\n        <xsl:if test=\".//sage[@language='macaulay2' and (@auto-evaluate = 'yes')]\">\n            <xsl:call-template name=\"makesagecell\">\n                <xsl:with-param name=\"language-attribute\">\n                    <xsl:text>macaulay2</xsl:text>\n                </xsl:with-param>\n                <xsl:with-param name=\"b-autoeval\" select=\"true()\"/>\n                <xsl:with-param name=\"language-text\">Macaulay2</xsl:with-param>\n            </xsl:call-template>\n        </xsl:if>\n\n        <xsl:if test=\".//sage[@language='maxima' and not(@auto-evaluate = 'yes')]\">\n            <xsl:call-template name=\"makesagecell\">\n                <xsl:with-param name=\"language-attribute\">\n                    <xsl:text>maxima</xsl:text>\n                </xsl:with-param>\n                <xsl:with-param name=\"b-autoeval\" select=\"false()\"/>\n                <xsl:with-param name=\"language-text\">Maxima</xsl:with-param>\n            </xsl:call-template>\n        </xsl:if>\n\n        <xsl:if test=\".//sage[@language='maxima' and (@auto-evaluate = 'yes')]\">\n            <xsl:call-template name=\"makesagecell\">\n                <xsl:with-param name=\"language-attribute\">\n                    <xsl:text>maxima</xsl:text>\n                </xsl:with-param>\n                <xsl:with-param name=\"b-autoeval\" select=\"true()\"/>\n                <xsl:with-param name=\"language-text\">Maxima</xsl:with-param>\n            </xsl:call-template>\n        </xsl:if>\n\n        <xsl:if test=\".//sage[@language='octave' and not(@auto-evaluate = 'yes')]\">\n            <xsl:call-template name=\"makesagecell\">\n                <xsl:with-param name=\"language-attribute\">\n                    <xsl:text>octave</xsl:text>\n                </xsl:with-param>\n                <xsl:with-param name=\"b-autoeval\" select=\"false()\"/>\n                <xsl:with-param name=\"language-text\">Octave</xsl:with-param>\n            </xsl:call-template>\n        </xsl:if>\n\n        <xsl:if test=\".//sage[@language='octave' and (@auto-evaluate = 'yes')]\">\n            <xsl:call-template name=\"makesagecell\">\n                <xsl:with-param name=\"language-attribute\">\n                    <xsl:text>octave</xsl:text>\n                </xsl:with-param>\n                <xsl:with-param name=\"b-autoeval\" select=\"true()\"/>\n                <xsl:with-param name=\"language-text\">Octave</xsl:with-param>\n            </xsl:call-template>\n        </xsl:if>\n\n        <xsl:if test=\".//sage[@language='python' and not(@auto-evaluate = 'yes')]\">\n            <xsl:call-template name=\"makesagecell\">\n                <xsl:with-param name=\"language-attribute\">\n                    <xsl:text>python</xsl:text>\n                </xsl:with-param>\n                <xsl:with-param name=\"b-autoeval\" select=\"false()\"/>\n                <xsl:with-param name=\"language-text\">Python</xsl:with-param>\n            </xsl:call-template>\n        </xsl:if>\n\n        <xsl:if test=\".//sage[@language='python' and (@auto-evaluate = 'yes')]\">\n            <xsl:call-template name=\"makesagecell\">\n                <xsl:with-param name=\"language-attribute\">\n                    <xsl:text>python</xsl:text>\n                </xsl:with-param>\n                <xsl:with-param name=\"b-autoeval\" select=\"true()\"/>\n                <xsl:with-param name=\"language-text\">Python</xsl:with-param>\n            </xsl:call-template>\n        </xsl:if>\n\n        <xsl:if test=\".//sage[@language='r' and not(@auto-evaluate = 'yes')]\">\n            <xsl:call-template name=\"makesagecell\">\n                <xsl:with-param name=\"language-attribute\">\n                    <xsl:text>r</xsl:text>\n                </xsl:with-param>\n                <xsl:with-param name=\"b-autoeval\" select=\"false()\"/>\n                <xsl:with-param name=\"language-text\">R</xsl:with-param>\n            </xsl:call-template>\n        </xsl:if>\n\n        <xsl:if test=\".//sage[@language='r' and (@auto-evaluate = 'yes')]\">\n            <xsl:call-template name=\"makesagecell\">\n                <xsl:with-param name=\"language-attribute\">\n                    <xsl:text>r</xsl:text>\n                </xsl:with-param>\n                <xsl:with-param name=\"b-autoeval\" select=\"true()\"/>\n                <xsl:with-param name=\"language-text\">R</xsl:with-param>\n            </xsl:call-template>\n        </xsl:if>\n\n        <xsl:if test=\".//sage[@language='singular' and not(@auto-evaluate = 'yes')]\">\n            <xsl:call-template name=\"makesagecell\">\n                <xsl:with-param name=\"language-attribute\">\n                    <xsl:text>singular</xsl:text>\n                </xsl:with-param>\n                <xsl:with-param name=\"b-autoeval\" select=\"false()\"/>\n                <xsl:with-param name=\"language-text\">Singular</xsl:with-param>\n            </xsl:call-template>\n        </xsl:if>\n\n        <xsl:if test=\".//sage[@language='singular' and (@auto-evaluate = 'yes')]\">\n            <xsl:call-template name=\"makesagecell\">\n                <xsl:with-param name=\"language-attribute\">\n                    <xsl:text>singular</xsl:text>\n                </xsl:with-param>\n                <xsl:with-param name=\"b-autoeval\" select=\"true()\"/>\n                <xsl:with-param name=\"language-text\">Singular</xsl:with-param>\n            </xsl:call-template>\n        </xsl:if>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- Program Listings highlighted by Prism -->\n<xsl:template name=\"syntax-highlight\">\n    <xsl:if test=\"$b-has-program and not($b-debug-react)\">\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/prism/1.26.0/components/prism-core.min.js\"></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/prism/1.26.0/plugins/autoloader/prism-autoloader.min.js\"></script>\n        <xsl:if test=\"$b-has-gdscript\">\n            <script src=\"{$html.js.dir}/prism/gdscript-prism.js\"></script>\n        </xsl:if>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/prism/1.26.0/plugins/line-numbers/prism-line-numbers.min.js\" integrity=\"sha512-dubtf8xMHSQlExGRQ5R7toxHLgSDZ0K7AunqPWHXmJQ8XyVIG19S1T95gBxlAeGOK02P4Da2RTnQz0Za0H0ebQ==\" crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\"></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/prism/1.26.0/plugins/line-highlight/prism-line-highlight.min.js\" integrity=\"sha512-93uCmm0q+qO5Lb1huDqr7tywS8A2TFA+1/WHvyiWaK6/pvsFl6USnILagntBx8JnVbQH5s3n0vQZY6xNthNfKA==\" crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\"></script>\n        <xsl:if test=\"$b-html-theme-legacy or $b-reveal-build\" >\n            <!-- Legacy themes rely on external css for prism, but newer ones have it built in -->\n            <link href=\"https://cdnjs.cloudflare.com/ajax/libs/prism/1.26.0/themes/prism.css\" rel=\"stylesheet\"/>\n            <!-- We could conditionally load the following based on line number -->\n            <!-- requests, but have chosen not to enact that efficiency         -->\n            <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/prism/1.26.0/plugins/line-numbers/prism-line-numbers.min.css\" integrity=\"sha512-cbQXwDFK7lj2Fqfkuxbo5iD1dSbLlJGXGpfTDqbggqjHJeyzx88I3rfwjS38WJag/ihH7lzuGlGHpDBymLirZQ==\" crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\" />\n            <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/prism/1.26.0/plugins/line-highlight/prism-line-highlight.min.css\" integrity=\"sha512-nXlJLUeqPMp1Q3+Bd8Qds8tXeRVQscMscwysJm821C++9w6WtsFbJjPenZ8cQVMXyqSAismveQJc0C1splFDCA==\" crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\" />\n        </xsl:if>\n    </xsl:if>\n</xsl:template>\n\n<!-- JS setup for a Google Custom Search Engine box -->\n<!-- Empty if not enabled via presence of cx number -->\n<xsl:template name=\"google-search-box-js\">\n    <xsl:if test=\"$b-google-cse and not($b-debug-react)\">\n        <script async=\"\">\n            <xsl:attribute name=\"src\">\n                <xsl:text>https://cse.google.com/cse.js?cx=</xsl:text>\n                <xsl:value-of select=\"$google-search-cx\"/>\n            </xsl:attribute>\n        </script>\n    </xsl:if>\n</xsl:template>\n\n<!-- Div for Google Search -->\n<!-- https://developers.google.com/custom-search/docs/element -->\n<!-- Empty if not enabled via presence of cx number           -->\n<xsl:template name=\"google-search-box\">\n    <xsl:if test=\"$b-google-cse\">\n        <!-- ARIA: \"search\" role for Google Search div/wrapper -->\n        <div class=\"searchwrapper\" role=\"search\">\n            <div class=\"gcse-search\" />\n        </div>\n    </xsl:if>\n</xsl:template>\n\n<!-- JS for native search -->\n<!-- The async attribute may help with slow downloads,  -->\n<!-- especially the project-specific search-file which  -->\n<!-- can be as large as several megabytes.              -->\n<!-- NB: async attribute also on Lunr and PTX-JS        -->\n<!-- resulted in console errors (2022-02-08)            -->\n<xsl:template name=\"native-search-box-js\">\n    <xsl:if test=\"$has-native-search and not($b-debug-react)\">\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/lunr.js/2.3.9/lunr.min.js\" integrity=\"sha512-4xUl/d6D6THrAnXAwGajXkoWaeMNwEKK4iNfq5DotEbLPAfk6FSxSP3ydNxqDgCw1c/0Z1Jg6L8h2j+++9BZmg==\" crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\"/>\n        <!-- document-specific variables with search documents -->\n        <script src=\"{$lunr-search-file}\" async=\"\"/>\n        <!-- PreTeXt Javascript and CSS to form and render results of a search -->\n        <script src=\"{$html.js.dir}/pretext_search.js\"/>\n        <!-- CSS for search is bundled into theme.css -->\n    </xsl:if>\n</xsl:template>\n\n\n<!-- Div for native search -->\n<xsl:template name=\"native-search-box\">\n    <xsl:if test=\"$has-native-search\">\n        <xsl:variable name=\"search-book-localization\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'search-book'\"/>\n            </xsl:apply-templates>\n        </xsl:variable>\n        <div class=\"ptx-search-box\">\n            <div class=\"ptx-search-widget\">\n                <button id=\"ptx-search-button\" type=\"button\" class=\"ptx-search-button button\" title=\"{$search-book-localization}\">\n                    <xsl:call-template name=\"insert-symbol\">\n                        <xsl:with-param name=\"name\" select=\"'search'\"/>\n                    </xsl:call-template>\n                    <span class=\"name\">\n                        <xsl:value-of select=\"$search-book-localization\"/>\n                    </span>\n                </button>\n            </div>\n            <xsl:call-template name=\"native-search-results\"/>\n        </div>\n    </xsl:if>\n</xsl:template>\n\n<!-- Div for native search results -->\n<xsl:template name=\"native-search-results\">\n    <xsl:if test=\"$has-native-search\">\n        <dialog id=\"ptx-search-dialog\" class=\"ptx-dialog ptx-search-dialog\">\n            <xsl:variable name=\"close-localization\">\n                <xsl:apply-templates select=\".\" mode=\"type-name\">\n                    <xsl:with-param name=\"string-id\" select=\"'close'\"/>\n                </xsl:apply-templates>\n            </xsl:variable>\n            <div class=\"ptx-search-dialog-controls\">\n                <input aria-label=\"Search term\" id=\"ptx-search-terms\" class=\"ptx-search-terms\" type=\"text\" name=\"terms\" placeholder=\"Search terms\"/>\n                <button aria-label=\"{$close-localization}\" id=\"ptx-search-close\" class=\"ptx-search-close\">\n                    <xsl:call-template name=\"insert-symbol\">\n                        <xsl:with-param name=\"name\" select=\"'close'\"/>\n                    </xsl:call-template>\n                </button>\n            </div>\n            <!-- Will contain notice about how many results there are for screen readers to announce-->\n            <div id=\"ptx-search-status\" class=\"ptx-search-status\" aria-live=\"polite\" aria-atomic=\"true\">\n            </div>\n            <h2 class=\"heading ptx-search-results-heading\">\n                <xsl:apply-templates select=\".\" mode=\"type-name\">\n                    <xsl:with-param name=\"string-id\" select=\"'search-results-heading'\"/>\n                </xsl:apply-templates>\n                <xsl:text>: </xsl:text>\n            </h2>\n            <!-- div#ptx-search-empty is not visible when there are results -->\n            <div id=\"ptx-search-empty\" class=\"ptx-search-empty\">\n                <span>\n                    <xsl:apply-templates select=\".\" mode=\"type-name\">\n                        <xsl:with-param name=\"string-id\" select=\"'no-search-results'\"/>\n                    </xsl:apply-templates>\n                    <xsl:text>.</xsl:text>\n                </span>\n            </div>\n            <ol id=\"ptx-search-results\" class=\"ptx-search-results\">\n            </ol>\n        </dialog>\n    </xsl:if>\n</xsl:template>\n\n<!-- Knowl header -->\n<xsl:template match=\"*\" mode=\"knowl\">\n    <xsl:if test=\"not($b-debug-react)\">\n        <!-- knowl.js is bundled into pretext-core.js; no separate <script> needed here -->\n        <!-- Variables are defined to defaults in knowl.js and  -->\n        <!-- we can override them with new values here          -->\n        <xsl:comment>knowl.js code controls Sage Cells within knowls</xsl:comment>\n        <script>\n            <!-- button text, internationalized -->\n            <xsl:text>sagecellEvalName='</xsl:text>\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'evaluate'\"/>\n            </xsl:apply-templates>\n            <xsl:text> (</xsl:text>\n            <!-- $language-text hard-coded since language  -->\n            <!-- support within knowls is not yet settled -->\n            <xsl:text>Sage</xsl:text>\n            <xsl:text>)</xsl:text>\n            <xsl:text>';&#xa;</xsl:text>\n        </script>\n    </xsl:if>\n</xsl:template>\n\n<!-- Header information for favicon -->\n<!-- Presently: needs two image files placeed in  HTML output     -->\n<!-- Publisher file could be extended to allow for other schemes. -->\n<!--      See: https://realfavicongenerator.net/faq               -->\n<!-- for one such option and ideas for others.                    -->\n<xsl:template name=\"favicon\">\n    <!-- $docinfo/html/favicon indicator is legacy code.  We do -->\n    <!-- not rewrite the publisher file as part of the assembly -->\n    <!-- (pre-processor) phase, so we leave this in.  Removal   -->\n    <!-- will require a sterner deprecation message that the    -->\n    <!-- current, gentle, reminder.                             -->\n    <xsl:if test=\"($favicon-scheme = 'simple') or $docinfo/html/favicon\">\n        <!-- Expects publisher to provide both -->\n        <!--     favicon/favicon-32x32.png     -->\n        <!--     favicon/favicon-16x16.png     -->\n        <!-- in the external images directory  -->\n        <xsl:variable name=\"res32\">\n            <!-- empty when not using managed directories -->\n            <xsl:value-of select=\"$external-directory\"/>\n            <xsl:text>favicon/favicon-32x32.png</xsl:text>\n        </xsl:variable>\n        <xsl:variable name=\"res16\">\n            <!-- empty when not using managed directories -->\n            <xsl:value-of select=\"$external-directory\"/>\n            <xsl:text>favicon/favicon-16x16.png</xsl:text>\n        </xsl:variable>\n        <link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"{$res32}\"/>\n        <link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"{$res16}\"/>\n    </xsl:if>\n</xsl:template>\n\n<!-- SCORM tracking script -->\n<!-- Emits a <script> tag that loads ptx-scorm-events.js only when the   -->\n<!-- build target has html.scorm = 'yes' (i.e. compression=\"scorm\").     -->\n<!-- ptx-scorm-events.js hooks into RunestoneBase.prototype.logBookEvent -->\n<!-- to capture exercise submissions and report them to the LMS via the  -->\n<!-- SCORM 1.2 / SCORM 2004 JavaScript API.                              -->\n<xsl:template name=\"scorm-js\">\n    <xsl:if test=\"$b-host-scorm\">\n        <script src=\"{$html.js.dir}/ptx_scorm_events.js\"></script>\n    </xsl:if>\n</xsl:template>\n\n<!-- PreTeXt Javascript header -->\n<xsl:template name=\"pretext-js\">\n    <xsl:choose>\n        <xsl:when test=\"not($b-debug-react)\">\n            <!-- jQuery: loaded from the js/ root (not dist/) since it is a\n                 third-party library, not a built artifact.  Required by the\n                 WeBWorK integration scripts and by Runestone. -->\n            <script src=\"{$html.js.root}/jquery.min.js\"></script>\n            <!-- Core bundle: pretext.js + pretext_add_on.js + knowl.js combined.\n                 Built by script/jsbuilder/jsbuilder.mjs; source lives in js/src/pretext-core.js.\n                 ?v= query string busts the browser cache when the CLI version changes,\n                 restoring the cache-busting that pretext_add_on.js?x=1 previously provided. -->\n            <script src=\"{$html.js.dir}/pretext-core.js?v={$cli.version}\"></script>\n            <!-- Read-aloud bundle: only when the publication option is on,\n                 so an opted-out build ships zero text-to-speech bytes. -->\n            <xsl:if test=\"$b-read-aloud\">\n                <script src=\"{$html.js.dir}/pretext-read-aloud.js?v={$cli.version}\"></script>\n            </xsl:if>\n        </xsl:when>\n        <xsl:when test=\"$b-debug-react-local\">\n            <script type=\"module\" defer=\"\" src=\"./static/js/main.js\"></script>\n            <link href=\"./static/css/main.css\" rel=\"stylesheet\"/>\n        </xsl:when>\n        <!-- provisional implementation -->\n        <xsl:when test=\"$b-debug-react-global\">\n            <xsl:variable name=\"prefix\" select=\"'https://siefkenj.github.io/pretext-react'\"/>\n            <script type=\"module\" defer=\"\" src=\"{$prefix}/static/js/main.js\"></script>\n            <link href=\"{$prefix}/static/css/main.css\" rel=\"stylesheet\"/>\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Font header -->\n<!-- Google Fonts -->\n<!-- Text: Open Sans by default (was: Istok Web font, regular and italic (400), bold (700)) -->\n<!-- Code: Inconsolata, regular (400), bold (700) (was: Source Code Pro regular (400))      -->\n<!-- (SourceCodePro being removed) -->\n<xsl:template name=\"fonts\">\n    <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\"/>\n    <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin=\"\"/>\n    <!-- Material Symbols font used for symbols -->\n    <link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0\" />\n    <!-- Legacy themes need these fonts, modern ones load them on their own -->\n    <xsl:if test=\"$b-html-theme-legacy\">\n            <!-- DejaVu Serif from an alternate CDN -->\n            <link href=\"https://fonts.cdnfonts.com/css/dejavu-serif\" rel=\"stylesheet\"/>\n            <!-- A variable font from Google, with serifs -->\n            <link href=\"https://fonts.googleapis.com/css2?family=PT+Serif:ital,wght@0,400;0,700;1,400;1,700&amp;display=swap\" rel=\"stylesheet\"></link>\n            <!-- A variable font from Google, sans serif -->\n            <link href=\"https://fonts.googleapis.com/css2?family=Open+Sans:wdth,wght@75..100,300..800&amp;display=swap\" rel=\"stylesheet\"/>\n            <!-- NB: not loading (binary) italic axis for variable fonts, tests seem to indicate this is OK -->\n            <link href=\"https://fonts.googleapis.com/css2?family=Inconsolata:wght@400;700&amp;\" rel=\"stylesheet\"/>\n    </xsl:if>\n</xsl:template>\n\n<!-- Hypothes.is Annotations -->\n<!-- Configurations are the defaults as of 2016-11-04   -->\n<!-- async=\"\" is a guessed-hack, docs have no attribute -->\n<xsl:template name=\"hypothesis-annotation\">\n    <xsl:if test=\"$b-activate-hypothesis\">\n        <script type=\"application/json\" class=\"js-hypothesis-config\">\n        <xsl:text>{&#xa;</xsl:text>\n        <xsl:text>    \"openSidebar\": false,</xsl:text>\n        <xsl:text>    \"showHighlights\": true,</xsl:text>\n        <xsl:text>}</xsl:text>\n        </script>\n        <script src=\"https://hypothes.is/embed.js\" async=\"\"></script>\n    </xsl:if>\n</xsl:template>\n\n<!-- GeoGebra -->\n<!-- The JS necessary to load the \"App\" for a generic calculator -->\n<xsl:template name=\"geogebra\">\n    <xsl:if test=\"$b-has-calculator and contains($html-calculator,'geogebra')\">\n        <script src=\"https://cdn.geogebra.org/apps/deployggb.js\"></script>\n    </xsl:if>\n</xsl:template>\n\n<!-- JSXGraph -->\n<xsl:template name=\"jsxgraph\">\n    <xsl:if test=\"$b-has-jsxgraph\">\n        <link rel=\"stylesheet\" type=\"text/css\" href=\"https://cdnjs.cloudflare.com/ajax/libs/jsxgraph/0.99.6/jsxgraph.css\" />\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/jsxgraph/0.99.6/jsxgraphcore.js\"></script>\n    </xsl:if>\n</xsl:template>\n\n<!-- Mermaid header libraries -->\n<xsl:template name=\"mermaid-header\">\n    <xsl:if test=\"$b-has-mermaid\">\n        <script type=\"module\">\n            import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';\n            import elkLayouts from 'https://cdn.jsdelivr.net/npm/@mermaid-js/layout-elk/dist/mermaid-layout-elk.esm.min.mjs';\n            mermaid.registerLayoutLoaders(elkLayouts);\n            let theme = '<xsl:value-of select=\"$mermaid-theme\"/>';\n            let layout = '<xsl:value-of select=\"$mermaid-layout-engine\"/>';\n            if (isDarkMode())\n                theme = 'dark';\n            mermaid.initialize({\n                securityLevel: 'loose',\n                theme: theme,\n                layout: layout,\n            });\n        </script>\n    </xsl:if>\n</xsl:template>\n\n<!-- Diagcess header library -->\n<xsl:template name=\"diagcess-header\">\n    <xsl:if test=\"$b-has-prefigure-annotations\">\n        <script src=\"{$html.js.dir}/diagcess/diagcess.js\"></script>\n    </xsl:if>\n</xsl:template>\n\n<!-- Diagcess footer initialization -->\n<xsl:template name=\"diagcess-footer\">\n    <xsl:if test=\"$b-has-prefigure-annotations\">\n        <script>diagcess.Base.init()</script>\n    </xsl:if>\n</xsl:template>\n\n<!-- CSS header -->\n<xsl:template name=\"css-common\">\n    <!-- Temporary until css handling overhaul by ascholer complete -->\n    <xsl:if test=\"$b-needs-custom-marker-css\">\n        <xsl:choose>\n            <!-- These styles are derived from the source, so they are not on  -->\n            <!-- the CDN and \"$html.css.dir\" does not point at them.  Inline   -->\n            <!-- them: there is one short rule per unique author-supplied      -->\n            <!-- marker, and portable HTML has no place to link out to anyway. -->\n            <xsl:when test=\"$b-cdn-resources\">\n                <style>\n                    <xsl:apply-templates select=\"exsl:node-set($ol-markers)//ol-marker\" mode=\"ol-marker-style\"/>\n                </style>\n            </xsl:when>\n            <xsl:otherwise>\n                <link href=\"{$html.css.dir}/ol-markers.css\" rel=\"stylesheet\" type=\"text/css\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:if>\n    <!-- If extra CSS is specified, then unpack multiple CSS files -->\n    <xsl:if test=\"not($html.css.extra = '')\">\n        <xsl:variable name=\"csses\" select=\"str:tokenize($html.css.extra, ', ')\"/>\n        <!-- $scripts is a collection of \"token\" and does not have -->\n        <!-- a root, which implies the form of the \"for-each\"      -->\n        <xsl:for-each select=\"$csses\">\n            <link rel=\"stylesheet\" type=\"text/css\">\n                <xsl:attribute name=\"href\">\n                    <xsl:value-of select=\".\" />\n                </xsl:attribute>\n            </link>\n        </xsl:for-each>\n    </xsl:if>\n    <!-- For testing purposes a developer can set the stringparam -->\n    <!-- \"debug.developer.css\" to the value \"yes\" and provide a   -->\n    <!-- CSS file to be loaded last.                              -->\n    <xsl:if test=\"$debug.developer.css = 'yes'\">\n        <xsl:comment> This HTML version has been built with elective CSS strictly </xsl:comment>\n        <xsl:comment> for testing purposes, and the developer who chose to use it </xsl:comment>\n        <xsl:comment> must supply it.                                             </xsl:comment>\n        <link href=\"developer.css\" rel=\"stylesheet\" type=\"text/css\" />\n    </xsl:if>\n</xsl:template>\n\n<xsl:template name=\"css\">\n    <xsl:if test=\"not($b-debug-react)\">\n        <link href=\"{$html.css.dir}/{$html-css-theme-file}\" rel=\"stylesheet\" type=\"text/css\"/>\n    </xsl:if>\n    <xsl:call-template name=\"css-common\"/>\n</xsl:template>\n\n<!-- Inject classes into the root div of a book. Only for used for   -->\n<!-- legacy styles - handles old css@colors and dark-mode disabling  -->\n<xsl:template name=\"html-theme-attributes\">\n    <!-- check for use of old css color sheets -->\n    <xsl:if test=\"$b-html-theme-legacy\">\n        <xsl:attribute name=\"data-legacy-colorscheme\">\n            <xsl:choose>\n                <xsl:when test=\"not($debug.colors = '')\">\n                    <xsl:value-of select=\"$debug.colors\"/>\n                </xsl:when>\n                <xsl:when test=\"not($html.css.colors = '')\">\n                    <xsl:value-of select=\"$html.css.colors\"/>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:text>default</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:attribute>\n    </xsl:if>\n    <xsl:if test=\"not($b-theme-has-darkmode)\">\n        <xsl:attribute name=\"data-darkmode\">\n            <xsl:text>disabled</xsl:text>\n        </xsl:attribute>\n    </xsl:if>\n</xsl:template>\n\n<!-- Treated as characters, these could show up often, -->\n<!-- so load into every possible HTML page instance    -->\n<xsl:template name=\"font-awesome\">\n    <xsl:if test=\"$b-has-icon\">\n        <!-- CDNJS is an alternative for obtaining this CSS -->\n        <link rel=\"stylesheet\" href=\"https://use.fontawesome.com/releases/v5.15.4/css/all.css\" crossorigin=\"anonymous\"/>\n    </xsl:if>\n</xsl:template>\n\n<!-- A place to put *one* Javascript file at the *end* of an  -->\n<!-- HTML page/file.  Not present in *every* page implemented -->\n<!-- in this file, such as knowls.                            -->\n<xsl:template name=\"extra-js-footer\">\n    <xsl:if test=\"not($html.js.extra = '')\">\n        <script src=\"{$html.js.extra}\"></script>\n    </xsl:if>\n</xsl:template>\n\n<!-- ################## -->\n<!-- Language Direction -->\n<!-- ################## -->\n\n<!-- Note: perhaps this should begin in a localization file, -->\n<!-- and come through as a key; but perhaps this template    -->\n<!-- can stay as is.                                         -->\n<xsl:template name=\"language-attributes\">\n    <xsl:attribute name=\"lang\">\n        <xsl:value-of select=\"$document-language\"/>\n    </xsl:attribute>\n    <xsl:attribute name=\"dir\">\n        <xsl:value-of select=\"$document-language-direction\"/>\n    </xsl:attribute>\n</xsl:template>\n\n\n<!-- ############## -->\n<!-- LaTeX Preamble -->\n<!-- ############## -->\n\n<!-- First a variable to massage the author-supplied -->\n<!-- package list to the form MathJax expects        -->\n<xsl:variable name=\"latex-packages-mathjax\">\n    <xsl:for-each select=\"$docinfo/math-package\">\n        <!-- must be specified, but can be empty/null -->\n        <xsl:if test=\"not(normalize-space(@mathjax-name)) = ''\">\n            <xsl:text>\\require{</xsl:text>\n            <xsl:value-of select=\"@mathjax-name\"/>\n            <xsl:apply-templates/>\n            <xsl:text>}</xsl:text>\n            <!-- all on one line, not very readable, but historical -->\n        </xsl:if>\n    </xsl:for-each>\n</xsl:variable>\n\n<!-- MathJax expects math wrapping, and we place in   -->\n<!-- a hidden div so not visible and take up no space -->\n<!-- Inline CSS added because a \"flash\" was visible   -->\n<!-- between HTML loading and CSS taking effect.      -->\n<!-- We could rename this properly, since we are      -->\n<!-- sneaking in packages, which load first, in       -->\n<!-- case authors want to build on these macros       -->\n<!-- NB: \"math support\" macros (fillin-math, sfrac) must  -->\n<!-- be defined here AND in the \"extraction-wrapper\"      -->\n<!-- template in  support/extract-math.xsl                -->\n<xsl:template match=\"*\" mode=\"latex-macros\">\n    <div id=\"latex-macros\" class=\"hidden-content process-math\" style=\"display:none\">\n        <xsl:call-template name=\"inline-math-wrapper\">\n            <xsl:with-param name=\"math\">\n                <xsl:value-of select=\"$latex-packages-mathjax\"/>\n                <xsl:value-of select=\"$latex-macros\"/>\n                <xsl:call-template name=\"fillin-math\"/>\n                <!-- legacy built-in support for \"slanted|beveled|nice\" fractions -->\n                <xsl:if test=\"$b-has-sfrac\">\n                    <xsl:text>\\newcommand{\\sfrac}[2]{{#1}/{#2}}&#xa;</xsl:text>\n                </xsl:if>\n            </xsl:with-param>\n        </xsl:call-template>\n    </div>\n</xsl:template>\n\n\n<!-- Brand Logo -->\n<!-- Place image in masthead -->\n<!-- We either create a link with an image, or just an image. -->\n<!-- NB: This template does nothing unless a brand logo has   -->\n<!-- been elected (publication file, or the deprecated        -->\n<!-- \"docinfo\" location), which requires its @source.         -->\n<xsl:template name=\"brand-logo\">\n    <xsl:if test=\"$b-brandlogo\">\n        <xsl:variable name=\"location\">\n            <!-- empty when not using managed directories -->\n            <xsl:value-of select=\"$external-directory\"/>\n            <xsl:value-of select=\"$brandlogo-source\"/>\n        </xsl:variable>\n\n        <xsl:choose>\n            <xsl:when test=\"not($brandlogo-url = '')\">\n                <a id=\"logo-link\" class=\"logo-link\" target=\"_blank\" >\n                    <xsl:attribute name=\"href\">\n                        <xsl:value-of select=\"$brandlogo-url\"/>\n                    </xsl:attribute>\n                    <img src=\"{$location}\" alt=\"Logo image\"/>\n                </a>\n            </xsl:when>\n            <xsl:otherwise>\n                <span id=\"logo-link\" class=\"logo-link\">\n                    <img src=\"{$location}\" alt=\"Logo image\"/>\n                </span>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:if>\n</xsl:template>\n\n<!-- Analytics Footers -->\n\n<!-- Google Analytics                     -->\n<!-- \"Classic\", not compared to Universal -->\n<xsl:template name=\"google-classic\">\n    <xsl:if test=\"$b-google-classic\">\n        <xsl:comment>Start: Google Classic code</xsl:comment>\n        <xsl:comment>*** DO NOT COPY ANOTHER PROJECT'S MAGIC NUMBERS/ID ***</xsl:comment>\n        <xsl:comment>***           GET YOUR OWN FROM GOOGLE             ***</xsl:comment>\n        <xsl:text>&#xa;</xsl:text>\n        <script>\n            <xsl:text>&#xa;</xsl:text>\n            <xsl:text>var _gaq = _gaq || [];&#xa;</xsl:text>\n            <xsl:text>_gaq.push(['_setAccount', '</xsl:text>\n            <xsl:value-of select=\"$google-classic-tracking\" />\n            <xsl:text>']);&#xa;</xsl:text>\n            <xsl:text>_gaq.push(['_trackPageview']);&#xa;</xsl:text>\n            <xsl:text>(function() {&#xa;</xsl:text>\n            <xsl:text>var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;&#xa;</xsl:text>\n            <xsl:text>ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'https://www') + '.google-analytics.com/ga.js';&#xa;</xsl:text>\n            <xsl:text>var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);&#xa;</xsl:text>\n            <xsl:text>})();&#xa;</xsl:text>\n        </script>\n        <xsl:text>&#xa;</xsl:text>\n        <xsl:comment>End: Google Classic code</xsl:comment>\n        <xsl:text>&#xa;</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<xsl:template name=\"google-universal\">\n    <xsl:if test=\"$b-google-universal\">\n        <xsl:comment>Start: Google Universal code</xsl:comment>\n        <xsl:comment>*** DO NOT COPY ANOTHER PROJECT'S MAGIC NUMBERS/ID ***</xsl:comment>\n        <xsl:comment>***           GET YOUR OWN FROM GOOGLE             ***</xsl:comment>\n        <xsl:text>&#xa;</xsl:text>\n        <script>\n            <xsl:text>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){&#xa;</xsl:text>\n            <xsl:text>(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),&#xa;</xsl:text>\n            <xsl:text>m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)&#xa;</xsl:text>\n            <xsl:text>})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');&#xa;</xsl:text>\n            <xsl:text>ga('create', '</xsl:text>\n            <xsl:value-of select=\"$google-universal-tracking\" />\n            <xsl:text>', 'auto');&#xa;</xsl:text>\n            <xsl:text>ga('send', 'pageview');&#xa;</xsl:text>\n        </script>\n        <xsl:text>&#xa;</xsl:text>\n        <xsl:comment>End: Google Universal code</xsl:comment>\n        <xsl:text>&#xa;</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<!-- Google says use first in <head>, seems fine in foot -->\n<xsl:template name=\"google-gst\">\n    <xsl:if test=\"$b-google-gst\">\n        <xsl:variable name=\"gst-url\">\n            <xsl:text>https://www.googletagmanager.com/gtag/js?id=</xsl:text>\n            <xsl:value-of select=\"$google-gst-tracking\"/>\n        </xsl:variable>\n        <xsl:comment>Start: Google Global Site Tag code</xsl:comment>\n        <xsl:comment>*** DO NOT COPY ANOTHER PROJECT'S MAGIC NUMBERS/ID ***</xsl:comment>\n        <xsl:comment>***           GET YOUR OWN FROM GOOGLE             ***</xsl:comment>\n        <xsl:text>&#xa;</xsl:text>\n        <script async=\"\" src=\"{$gst-url}\"></script>\n        <script>\n            <xsl:text>  window.dataLayer = window.dataLayer || [];&#xa;</xsl:text>\n            <xsl:text>  function gtag(){dataLayer.push(arguments);}&#xa;</xsl:text>\n            <xsl:text>  gtag('js', new Date());&#xa;</xsl:text>\n            <xsl:text>  gtag('config', '</xsl:text>\n            <xsl:value-of select=\"$google-gst-tracking\"/>\n            <xsl:text>');&#xa;</xsl:text>\n        </script>\n        <xsl:comment>End: Google Global Site Tag code</xsl:comment>\n    </xsl:if>\n</xsl:template>\n\n<!-- StatCounter                                -->\n<!-- Set sc_invisible to 1                      -->\n<!-- In noscript URL, final 1 is an edit from 0 -->\n<xsl:template name=\"statcounter\">\n    <xsl:if test=\"$b-statcounter\">\n        <xsl:variable name=\"noscript_url\">\n            <xsl:text>https://c.statcounter.com/</xsl:text>\n            <xsl:value-of select=\"$statcounter-project\" />\n            <xsl:text>/0/</xsl:text>\n            <xsl:value-of select=\"$statcounter-security\" />\n            <xsl:text>/1/</xsl:text>\n        </xsl:variable>\n        <xsl:comment>Start: StatCounter code</xsl:comment>\n        <xsl:comment>*** DO NOT COPY ANOTHER PROJECT'S MAGIC NUMBERS/ID ***</xsl:comment>\n        <xsl:comment>***        GET YOUR OWN FROM STATCOUNTER           ***</xsl:comment>\n        <script>\n        <xsl:text>&#xa;</xsl:text>\n        <xsl:text>var sc_project=</xsl:text>\n        <xsl:value-of select=\"$statcounter-project\" />\n        <xsl:text>;&#xa;</xsl:text>\n        <xsl:text>var sc_invisible=1;&#xa;</xsl:text>\n        <xsl:text>var sc_security=\"</xsl:text>\n        <xsl:value-of select=\"$statcounter-security\" />\n        <xsl:text>\";&#xa;</xsl:text>\n        <xsl:text>var scJsHost = ((\"https:\" == document.location.protocol) ? \"https://secure.\" : \"https://www.\");&#xa;</xsl:text>\n        <xsl:text>document.write(\"&lt;sc\"+\"ript src='\" + scJsHost+ \"statcounter.com/counter/counter.js'&gt;&lt;/\"+\"script&gt;\");&#xa;</xsl:text>\n        </script>\n        <noscript>\n        <div class=\"statcounter\">\n        <a title=\"web analytics\" href=\"https://statcounter.com/\" target=\"_blank\">\n        <img class=\"statcounter\" src=\"{$noscript_url}\" alt=\"web analytics\" /></a>\n        </div>\n        </noscript>\n        <xsl:comment>End: StatCounter code</xsl:comment>\n        <xsl:text>&#xa;</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<!-- ############################################# -->\n<!-- Worksheet Margins, Headers/Footers, and Pages -->\n<!-- ############################################# -->\n\n<!-- We put page-margins-attributes only on printout sections -->\n<xsl:template match=\"*\" mode=\"page-margins-attribute\"/>\n\n<!-- A PROJECT-LIKE acting as a standalone printout is paginated by the -->\n<!-- same javascript, so it needs the same data.  It has no margin      -->\n<!-- attributes of its own, so \"printout-margin\" falls through to the   -->\n<!-- publisher's worksheet defaults for all four sides.                 -->\n<xsl:template match=\"&PROJECT-LIKE;\" mode=\"page-margins-attribute\">\n    <xsl:variable name=\"b-standalone-printout\">\n        <xsl:apply-templates select=\".\" mode=\"is-standalone-printout\"/>\n    </xsl:variable>\n    <xsl:if test=\"$b-standalone-printout = 'true'\">\n        <xsl:call-template name=\"printout-margins-attribute\"/>\n    </xsl:if>\n</xsl:template>\n\n<xsl:template match=\"&PRINTOUT;\" mode=\"page-margins-attribute\">\n    <xsl:call-template name=\"printout-margins-attribute\"/>\n</xsl:template>\n\n<xsl:template name=\"printout-margins-attribute\">\n    <xsl:attribute name=\"data-margins\">\n        <!-- A space-separated list for top, right, bottom, and left margins -->\n        <xsl:apply-templates select=\".\" mode=\"printout-margin\">\n            <xsl:with-param name=\"author-side\" select=\"@top\"/>\n            <xsl:with-param name=\"publisher-side\" select=\"$ws-margin-top\"/>\n        </xsl:apply-templates>\n        <xsl:text> </xsl:text>\n        <xsl:apply-templates select=\".\" mode=\"printout-margin\">\n            <xsl:with-param name=\"author-side\" select=\"@right\"/>\n            <xsl:with-param name=\"publisher-side\" select=\"$ws-margin-right\"/>\n        </xsl:apply-templates>\n        <xsl:text> </xsl:text>\n        <xsl:apply-templates select=\".\" mode=\"printout-margin\">\n            <xsl:with-param name=\"author-side\" select=\"@bottom\"/>\n            <xsl:with-param name=\"publisher-side\" select=\"$ws-margin-bottom\"/>\n        </xsl:apply-templates>\n        <xsl:text> </xsl:text>\n        <xsl:apply-templates select=\".\" mode=\"printout-margin\">\n            <xsl:with-param name=\"author-side\" select=\"@left\"/>\n            <xsl:with-param name=\"publisher-side\" select=\"$ws-margin-left\"/>\n        </xsl:apply-templates>\n    </xsl:attribute>\n</xsl:template>\n\n<!-- Add data-* attributes for headers and footers -->\n<xsl:template match=\"*\" mode=\"page-header-footer-attributes\"/>\n\n<xsl:template match=\"&PROJECT-LIKE;\" mode=\"page-header-footer-attributes\">\n    <xsl:variable name=\"b-standalone-printout\">\n        <xsl:apply-templates select=\".\" mode=\"is-standalone-printout\"/>\n    </xsl:variable>\n    <xsl:if test=\"$b-standalone-printout = 'true'\">\n        <xsl:call-template name=\"printout-header-footer-attributes\"/>\n    </xsl:if>\n</xsl:template>\n\n<xsl:template match=\"&PRINTOUT;\" mode=\"page-header-footer-attributes\">\n    <xsl:call-template name=\"printout-header-footer-attributes\"/>\n</xsl:template>\n\n<xsl:template name=\"printout-header-footer-attributes\">\n    <xsl:if test=\"not($ws-header-first-left = '')\">\n        <xsl:attribute name=\"data-header-first-left\">\n            <xsl:value-of select=\"normalize-space($ws-header-first-left)\"/>\n        </xsl:attribute>\n    </xsl:if>\n    <xsl:if test=\"not($ws-header-first-center = '')\">\n        <xsl:attribute name=\"data-header-first-center\">\n            <xsl:value-of select=\"normalize-space($ws-header-first-center)\"/>\n        </xsl:attribute>\n    </xsl:if>\n    <xsl:if test=\"not($ws-header-first-right = '')\">\n        <xsl:attribute name=\"data-header-first-right\">\n            <xsl:value-of select=\"normalize-space($ws-header-first-right)\"/>\n        </xsl:attribute>\n    </xsl:if>\n    <xsl:if test=\"not($ws-header-running-left = '')\">\n        <xsl:attribute name=\"data-header-running-left\">\n            <xsl:value-of select=\"normalize-space($ws-header-running-left)\"/>\n        </xsl:attribute>\n    </xsl:if>\n    <xsl:if test=\"not($ws-header-running-center = '')\">\n        <xsl:attribute name=\"data-header-running-center\">\n            <xsl:value-of select=\"normalize-space($ws-header-running-center)\"/>\n        </xsl:attribute>\n    </xsl:if>\n    <xsl:if test=\"not($ws-header-running-right = '')\">\n        <xsl:attribute name=\"data-header-running-right\">\n            <xsl:value-of select=\"normalize-space($ws-header-running-right)\"/>\n        </xsl:attribute>\n    </xsl:if>\n    <xsl:if test=\"not($ws-footer-first-left = '')\">\n        <xsl:attribute name=\"data-footer-first-left\">\n            <xsl:value-of select=\"normalize-space($ws-footer-first-left)\"/>\n        </xsl:attribute>\n    </xsl:if>\n    <xsl:if test=\"not($ws-footer-first-center = '')\">\n        <xsl:attribute name=\"data-footer-first-center\">\n            <xsl:value-of select=\"normalize-space($ws-footer-first-center)\"/>\n        </xsl:attribute>\n    </xsl:if>\n    <xsl:if test=\"not($ws-footer-first-right = '')\">\n        <xsl:attribute name=\"data-footer-first-right\">\n            <xsl:value-of select=\"normalize-space($ws-footer-first-right)\"/>\n        </xsl:attribute>\n    </xsl:if>\n    <xsl:if test=\"not($ws-footer-running-left = '')\">\n        <xsl:attribute name=\"data-footer-running-left\">\n            <xsl:value-of select=\"normalize-space($ws-footer-running-left)\"/>\n        </xsl:attribute>\n    </xsl:if>\n    <xsl:if test=\"not($ws-footer-running-center = '')\">\n        <xsl:attribute name=\"data-footer-running-center\">\n            <xsl:value-of select=\"normalize-space($ws-footer-running-center)\"/>\n        </xsl:attribute>\n    </xsl:if>\n    <xsl:if test=\"not($ws-footer-running-right = '')\">\n        <xsl:attribute name=\"data-footer-running-right\">\n            <xsl:value-of select=\"normalize-space($ws-footer-running-right)\"/>\n        </xsl:attribute>\n    </xsl:if>\n</xsl:template>\n\n<!-- A printout is (mostly) structured by \"page\", which translates    -->\n<!-- into an HTML section.onepage.  Note that an \"introduction\" and    -->\n<!-- \"objectives\" can precede the first \"page\" as HTML output, and the -->\n<!-- final \"page\" may be followed by a \"conclusion\" and \"outcomes\"     -->\n<xsl:template match=\"worksheet/page|handout/page\">\n    <xsl:param name=\"heading-level\"/>\n    <section class=\"onepage\">\n        <xsl:apply-templates select=\".\" mode=\"html-id-attribute\"/>\n        <xsl:apply-templates select=\"*\">\n            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n        </xsl:apply-templates>\n    </section>\n</xsl:template>\n\n<!-- 2020-03-17: Empty element, since originally a       -->\n<!-- \"page\" element interrupted numbering of contents.   -->\n<!-- Now deprecated in favor of a proper \"page\" element. -->\n<xsl:template match=\"worksheet/pagebreak\">\n    <hr class=\"pagebreak\"/>\n</xsl:template>\n\n<!-- Miscellaneous -->\n\n<!-- Inline warnings go into text, no matter what -->\n<!-- They are colored for an author's report -->\n<xsl:template name=\"inline-warning\">\n    <xsl:param name=\"warning\" />\n    <xsl:element name=\"span\">\n        <!-- Color for author tools version -->\n        <xsl:if test=\"$author-tools-new = 'yes'\" >\n            <xsl:attribute name=\"style\">color:red</xsl:attribute>\n        </xsl:if>\n        <xsl:text>(((</xsl:text>\n        <xsl:value-of select=\"$warning\" />\n        <xsl:text>)))</xsl:text>\n    </xsl:element>\n</xsl:template>\n\n<!-- Marginal notes are only for author's report                     -->\n<!-- and are always colored red.  Marginpar's from                   -->\n<!-- http://www.sitepoint.com/web-foundations/floating-clearing-css/ -->\n<xsl:template name=\"margin-warning\">\n    <xsl:param name=\"warning\" />\n    <xsl:if test=\"$author-tools-new = 'yes'\" >\n        <xsl:element name=\"span\">\n            <xsl:attribute name=\"style\">color:red;float:right;width:20em;margin-right:-25em;</xsl:attribute>\n            <xsl:value-of select=\"$warning\" />\n        </xsl:element>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- SCORM manifest -->\n<!-- Generate a simple xml file describing a minimal SCORM \"course\". -->\n<!-- Besides some boiler plate, we include the title of the course   -->\n<!-- (under the main organization), a single item (since the entire  -->\n<!-- document is a single iframe), and the entry point for that item -->\n<!-- (the resource with its file).  It appears that while other files-->\n<!-- can be listed as files for that resource, this is not required. -->\n\n<!-- The only customization we do here is setting the main title to  -->\n<!-- the title of the document.  We could easily expand this.        -->\n<xsl:template name=\"scorm-manifest\">\n    <xsl:variable name=\"root-filename\">\n        <xsl:apply-templates select=\"$document-root\" mode=\"containing-filename\" />\n    </xsl:variable>\n    <exsl:document href=\"imsmanifest.xml\" method=\"xml\" omit-xml-declaration=\"no\" indent=\"yes\">\n        <manifest identifier=\"ptx-scorm-test\" version=\"1\" xmlns=\"http://www.imsglobal.org/xsd/imscp_v1p1\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:adlcp=\"http://www.adlnet.org/xsd/adlcp_v1p3\" xmlns:adlseq=\"http://www.adlnet.org/xsd/adlseq_v1p3\" xmlns:adlnav=\"http://www.adlnet.org/xsd/adlnav_v1p3\" xmlns:imsss=\"http://www.imsglobal.org/xsd/imsss\" xsi:schemaLocation=\"http://www.imsglobal.org/xsd/imscp_v1p1 imscp_v1p1.xsd http://www.adlnet.org/xsd/adlcp_v1p3 adlcp_v1p3.xsd http://www.adlnet.org/xsd/adlseq_v1p3 adlseq_v1p3.xsd http://www.adlnet.org/xsd/adlnav_v1p3 adlnav_v1p3.xsd http://www.imsglobal.org/xsd/imsss imsss_v1p0.xsd\">\n            <!--The metadata node simply declares which SCORM version this course operates under.-->\n            <metadata>\n                <schema>ADL SCORM</schema>\n                <schemaversion>2004 3rd Edition</schemaversion>\n            </metadata>\n            <!-- There is just one organization. The organization contains just one item.-->\n            <organizations default=\"main\">\n                <organization identifier=\"main\">\n                    <title>\n                        <xsl:apply-templates select=\"$document-root\" mode=\"title-full\"/>\n                    </title>\n                    <item identifier=\"item_1\" identifierref=\"main-resource\">\n                        <!-- \"Main\" here is a generic name.  Only visible when importing a into LMS -->\n                        <!-- (at least in Canvas), sort of a sole entry in the table of contents.   -->\n                        <title>Main</title>\n                    </item>\n                </organization>\n            </organizations>\n            <!-- There is just one resource that represents the single SCO that comprises the entirety of this course. The href attribute points to the launch URL for the course and all of the files required by the course are listed. -->\n            <resources>\n                <!-- We use the index.html file pretext produces, as this always points to the right place.  -->\n                <!-- NB we could point to any entry filename, as long as it is in the resulting zip          -->\n                <resource identifier=\"main-resource\" type=\"webcontent\" adlcp:scormType=\"sco\" href=\"index.html\">\n                <file href=\"index.html\"/>\n                </resource>\n            </resources>\n        </manifest>\n    </exsl:document>\n</xsl:template>\n\n</xsl:stylesheet>\n","pretext-numbers.xsl":"<?xml version='1.0'?>\n\n<!DOCTYPE xsl:stylesheet [\n    <!ENTITY % entities SYSTEM \"entities.ent\">\n    %entities;\n]>\n\n<!--********************************************************************\nCopyright (C) 2020-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<xsl:stylesheet\n    xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\"\n    xmlns:xml=\"http://www.w3.org/XML/1998/namespace\"\n    xmlns:pi=\"http://pretextbook.org/2020/pretext/internal\"\n    xmlns:exsl=\"http://exslt.org/common\"\n    xmlns:date=\"http://exslt.org/dates-and-times\"\n    extension-element-prefixes=\"exsl date\"\n    exclude-result-prefixes=\"pi\"\n>\n\n<!-- Intend output as plain text (numbers) -->\n<xsl:output method=\"text\" encoding=\"UTF-8\"/>\n\n<!-- Read documentation in the \"-assembly\" stylesheet to understand -->\n<!-- employment/purpose of these templates there.                   -->\n<!--                                                                -->\n<!-- 2021-12-22: moving the computation of serial numbers out of    -->\n<!-- the \"-common\" stylesheet, so as to be pre-computed.            -->\n\n\n<!-- ######################## -->\n<!-- Block Structure Numbers  -->\n<!-- ######################## -->\n\n<!-- Given a block element, produce its structure number prefix      -->\n<!-- by reading the pre-computed @pi:block-struct from the nearest   -->\n<!-- ancestor division, then truncating or padding to the configured -->\n<!-- number of levels.  The @pi:block-struct chain already excludes  -->\n<!-- parts (they are squelched in assembly), so when parts are       -->\n<!-- present the caller's $levels (which counts from \"part\" depth)   -->\n<!-- must be reduced by one to match the shorter chain.              -->\n<xsl:template name=\"block-structure-number\">\n    <xsl:param name=\"levels\"/>\n    <xsl:variable name=\"raw-struct\"\n        select=\"ancestor::*[@pi:block-struct][1]/@pi:block-struct\"/>\n    <!-- The @pi:block-struct chain already excludes parts, so when -->\n    <!-- parts are present the $levels count (which includes the    -->\n    <!-- part depth) must be reduced by one.  But only for          -->\n    <!-- blocks actually inside a part or backmatter — blocks       -->\n    <!-- in frontmatter have no part ancestor and should use        -->\n    <!-- $levels unmodified.                                        -->\n    <xsl:variable name=\"effective-levels\">\n        <xsl:choose>\n            <xsl:when test=\"not($parts = 'absent') and ancestor::*[self::part or self::backmatter]\">\n                <xsl:choose>\n                    <xsl:when test=\"$levels > 0\">\n                        <xsl:value-of select=\"$levels - 1\"/>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:value-of select=\"0\"/>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$levels\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:call-template name=\"truncate-pad-struct\">\n        <xsl:with-param name=\"struct\" select=\"$raw-struct\"/>\n        <xsl:with-param name=\"levels\" select=\"$effective-levels\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- Truncate a dotted-number string to a given number of     -->\n<!-- components, padding with \".0\" if fewer components exist.  -->\n<xsl:template name=\"truncate-pad-struct\">\n    <xsl:param name=\"struct\"/>\n    <xsl:param name=\"levels\"/>\n    <xsl:param name=\"count\" select=\"0\"/>\n\n    <xsl:choose>\n        <!-- Emitted enough levels, halt -->\n        <xsl:when test=\"$count = $levels\"/>\n        <!-- Components remaining in the string -->\n        <xsl:when test=\"$struct != ''\">\n            <xsl:if test=\"$count > 0\">\n                <xsl:text>.</xsl:text>\n            </xsl:if>\n            <xsl:choose>\n                <xsl:when test=\"contains($struct, '.')\">\n                    <xsl:value-of select=\"substring-before($struct, '.')\"/>\n                    <xsl:call-template name=\"truncate-pad-struct\">\n                        <xsl:with-param name=\"struct\"\n                            select=\"substring-after($struct, '.')\"/>\n                        <xsl:with-param name=\"levels\" select=\"$levels\"/>\n                        <xsl:with-param name=\"count\" select=\"$count + 1\"/>\n                    </xsl:call-template>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:value-of select=\"$struct\"/>\n                    <xsl:call-template name=\"truncate-pad-struct\">\n                        <xsl:with-param name=\"struct\" select=\"''\"/>\n                        <xsl:with-param name=\"levels\" select=\"$levels\"/>\n                        <xsl:with-param name=\"count\" select=\"$count + 1\"/>\n                    </xsl:call-template>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- Out of components, pad with zero -->\n        <xsl:otherwise>\n            <xsl:if test=\"$count > 0\">\n                <xsl:text>.</xsl:text>\n            </xsl:if>\n            <xsl:text>0</xsl:text>\n            <xsl:call-template name=\"truncate-pad-struct\">\n                <xsl:with-param name=\"struct\" select=\"''\"/>\n                <xsl:with-param name=\"levels\" select=\"$levels\"/>\n                <xsl:with-param name=\"count\" select=\"$count + 1\"/>\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- ##### Division levels ##### -->\n<!-- 2021-12-22: we are transitioning to selected (and eventually universal) -->\n<!-- use of levels computed during the \"assembly\" phase.  So we use careful  -->\n<!-- matches and we use careful choices for application.  At every           -->\n<!-- application we compute the \"old\" level to test for consistency.         -->\n\n<!-- ####################################################################### -->\n<xsl:template match=\"part|chapter|appendix|section|subsection|subsubsection|exercises|solutions|reading-questions|references|glossary|worksheet|handout\" mode=\"new-level\">\n    <xsl:variable name=\"old-level\">\n        <xsl:apply-templates select=\".\" mode=\"level\"/>\n    </xsl:variable>\n    <xsl:if test=\"not($old-level = @pi:level)\">\n        <xsl:message>PTX:BUG:  development bug, new level does not match old level for \"<xsl:value-of select=\"local-name(.)\"/>\"</xsl:message>\n        <xsl:apply-templates select=\".\" mode=\"location-report\" />\n    </xsl:if>\n    <!-- actual value here, above is debugging -->\n    <xsl:value-of select=\"@pi:level\"/>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"new-level\">\n    <xsl:message>PTX:BUG:   an element (\"<xsl:value-of select=\"local-name(.)\"/>\") does not know its *new* level</xsl:message>\n    <xsl:apply-templates select=\".\" mode=\"location-report\" />\n</xsl:template>\n<!-- ####################################################################### -->\n\n <!-- Specific top-level divisions -->\n<!-- article/frontmatter, article/backmatter are faux divisions, but   -->\n<!-- will function as a terminating condition in recursive count below -->\n<xsl:template match=\"book|article|slideshow|letter|memo|article/frontmatter|article/backmatter\" mode=\"level\">\n    <xsl:value-of select=\"0\"/>\n</xsl:template>\n\n<!-- A book/part will divide the mainmatter, so a \"chapter\" is at -->\n<!-- level 2, so we also put the faux divisions at level 1 in the -->\n<!-- case of parts, to again terminate recursive count            -->\n<xsl:template match=\"book/part|book/frontmatter|book/backmatter\" mode=\"level\">\n    <xsl:choose>\n        <xsl:when test=\"$b-has-parts\">\n            <xsl:value-of select=\"1\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"0\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Remaining divisions will follow a strict progression from their    -->\n<!-- parents.  We have front matter divisions of a book first, which    -->\n<!-- will have the same level as a chapter, then traditional divisions, -->\n<!-- which may structure a chapter of a book, section of an article,    -->\n<!-- or an appendix (structured as a chapter in a book or a sections    -->\n<!-- in an article).  Then follows specialized divisions of the back    -->\n<!-- matter, which are peers of an appendix.  Finally we have the       -->\n<!-- \"specialized divisions\" of PreTeXt, which can be descendants of    -->\n<!-- chapters of books, sections of articles, or in the case of         -->\n<!-- solutions or references, children of an appendix.                  -->\n\n<xsl:template match=\"colophon|biography|dedication|acknowledgement|preface|chapter|section|subsection|subsubsection|slide|appendix|index|colophon|exercises|reading-questions|references|solutions|glossary|worksheet|handout\" mode=\"level\">\n    <xsl:variable name=\"level-above\">\n        <xsl:apply-templates select=\"parent::*\" mode=\"level\"/>\n    </xsl:variable>\n    <xsl:value-of select=\"$level-above + 1\"/>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"level\">\n    <xsl:message>PTX:BUG:   an element (\"<xsl:value-of select=\"local-name(.)\"/>\") does not know its level</xsl:message>\n    <xsl:apply-templates select=\".\" mode=\"location-report\" />\n</xsl:template>\n\n\n<!-- Enclosing Level -->\n\n<!-- ##### Serial / structure / full number ##### -->\n<!-- Backmatter references and glossary are unique and un-numbered, -->\n<!-- so an empty serial number.  These matches supersede the above. -->\n<xsl:template match=\"backmatter/references\" mode=\"serial-number\" />\n<xsl:template match=\"backmatter/glossary\" mode=\"serial-number\" />\n\n<!-- Serial number of a block: read the @pi:serial that the assembly -->\n<!-- \"serial-stamp\" pass stamped.  That pass decides, from the       -->\n<!-- publication \"@distinct\" switches, whether a group shares the    -->\n<!-- overall blocks counter or runs on its own distinct counter.     -->\n<xsl:template match=\"&DEFINITION-LIKE;|&THEOREM-LIKE;|&AXIOM-LIKE;|&REMARK-LIKE;|&COMPUTATION-LIKE;|&EXAMPLE-LIKE;|&PROJECT-LIKE;|&FIGURE-LIKE;|&OPENPROBLEM-LIKE;|exercise\" mode=\"serial-number\">\n    <xsl:value-of select=\"@pi:serial\"/>\n</xsl:template>\n\n<!-- Proofs may be numbered (for cross-reference knowls) -->\n<xsl:template match=\"&PROOF-LIKE;\" mode=\"serial-number\">\n    <xsl:number count=\"&PROOF-LIKE;\"/>\n</xsl:template>\n\n\n<!-- Serial Numbers: Equations                                             -->\n<!-- The assembly equation-serial pass stamps @pi:serial on every numbered -->\n<!-- <mrow>; here we just read it back.  Scope rules and pad/truncate      -->\n<!-- behaviour live in the assembly pass.                                  -->\n<xsl:template match=\"mrow[@pi:numbered = 'yes']\" mode=\"serial-number\">\n    <xsl:value-of select=\"@pi:serial\"/>\n</xsl:template>\n\n<!-- An authored bare \"md\" may carry an @xml:id, and so may be cross-referenced. -->\n<!-- We consider its number, as a target of a cross-reference to be that of the  -->\n<!-- contained, single \"mrow\".  This may be an actual number or may be an empty  -->\n<!-- string, depending on how the \"md\" was meant to be numbered.                 -->\n<xsl:template match=\"md[@pi:authored-one-line]\" mode=\"serial-number\">\n    <xsl:apply-templates select=\"mrow\" mode=\"serial-number\"/>\n</xsl:template>\n\n<!-- Serial Numbers: Exercises in Exercises or Worksheet or Reading Question Divisions -->\n<!-- Note: numbers may be hard-coded for longevity        -->\n<!-- exercisegroups  and future lightweight divisions may -->\n<!-- be intermediate, but should not hinder the count     -->\n<!-- NB: there are three historical \"apply-templates\"     -->\n<!-- here which might now be written as \"value-of\",       -->\n<!-- but perhaps it is irrelevant                         -->\n<xsl:template match=\"exercises//exercise\" mode=\"serial-number\">\n    <xsl:number from=\"exercises\" level=\"any\" count=\"exercise\" />\n</xsl:template>\n\n<xsl:template match=\"exercises//exercise[@number]\" mode=\"serial-number\">\n    <xsl:apply-templates select=\"@number\" />\n</xsl:template>\n\n<xsl:template match=\"worksheet//exercise\" mode=\"serial-number\">\n    <xsl:number from=\"worksheet\" level=\"any\" count=\"exercise\" />\n</xsl:template>\n\n<xsl:template match=\"worksheet//exercise[@number]\" mode=\"serial-number\">\n    <xsl:apply-templates select=\"@number\" />\n</xsl:template>\n\n<xsl:template match=\"reading-questions//exercise\" mode=\"serial-number\">\n    <xsl:number from=\"reading-questions\" level=\"any\" count=\"exercise\" />\n</xsl:template>\n\n<xsl:template match=\"reading-questions//exercise[@number]\" mode=\"serial-number\">\n    <xsl:apply-templates select=\"@number\" />\n</xsl:template>\n\n<!-- Serial Numbers: Solutions -->\n<!-- Hints, answers, solutions may be numbered (for cross-reference knowls) -->\n<xsl:template match=\"&SOLUTION-LIKE;\" mode=\"serial-number\">\n    <xsl:number />\n</xsl:template>\n\n<!-- Serial Numbers: Bibliographic Items -->\n<!-- Always sequential within a References section -->\n<xsl:template match=\"biblio\" mode=\"serial-number\">\n    <xsl:number from=\"references\" level=\"any\" count=\"biblio\" />\n</xsl:template>\n<!-- Notes may be numbered (for cross-reference knowls) -->\n<xsl:template match=\"biblio/note\" mode=\"serial-number\">\n    <xsl:number />\n</xsl:template>\n\n<!-- Hints, answers, solutions, notes are often singletons.     -->\n<!-- This utility returns the serial number, or if a singleton, -->\n<!-- returns an empty string.  Employing templates will need    -->\n<!-- to check if they want to react accordingly, or they should -->\n<!-- just ask for the serial number itself if they don't care.  -->\n<xsl:template match=\"&SOLUTION-LIKE;|biblio/note\" mode=\"non-singleton-number\">\n    <xsl:variable name=\"the-number\">\n        <xsl:apply-templates select=\".\" mode=\"serial-number\" />\n    </xsl:variable>\n    <xsl:choose>\n        <!-- non-singletons always of interest/use -->\n        <xsl:when test=\"not($the-number = 1)\">\n            <xsl:value-of select=\"$the-number\" />\n        </xsl:when>\n        <!-- now being careful with \"1\" -->\n        <xsl:otherwise>\n            <xsl:variable name=\"elt-name\" select=\"local-name(.)\" />\n            <!-- We go to the parent, get all like children, then     -->\n            <!-- filter by name, since hints and answers, etc all mix -->\n            <xsl:variable name=\"siblings-and-self\" select=\"parent::*/*[local-name(.) = $elt-name]\" />\n            <!-- maybe \"1\" is interesting too -->\n            <!-- if not, no result whatsoever -->\n            <xsl:if test=\"count($siblings-and-self) > 1\">\n                <xsl:value-of select=\"$the-number\" />\n            </xsl:if>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Serial Numbers: Footnotes                                                -->\n<!-- We determine the appropriate subtree to count within                     -->\n<!-- given the document root and the configured depth                         -->\n<!-- @pi:serial is stamped on every fn during assembly; here we read it back. -->\n<xsl:template match=\"fn\" mode=\"serial-number\">\n    <xsl:value-of select=\"@pi:serial\"/>\n</xsl:template>\n\n<!-- Serial Numbers: Subfigures, Subtables, Sublisting-->\n<!-- Subnumbering only happens with figures            -->\n<!-- or tables arranged in a sidebyside, which         -->\n<!-- is again contained inside a figure, the           -->\n<!-- element providing the overall caption             -->\n<!-- The serial number is a sub-number, (a), (b), (c), -->\n<!-- *Always* with the parenthetical formatting        -->\n<!-- Debatable if parentheses should come from here    -->\n\n\n<!-- In this case the structure number is the          -->\n<!-- full number of the enclosing figure               -->\n\n<!-- a lone sidebyside, not in a sbsgroup -->\n<xsl:template match=\"figure/sidebyside/figure | figure/sidebyside/table | figure/sidebyside/listing | figure/sidebyside/list\" mode=\"serial-number\">\n    <xsl:text>(</xsl:text>\n    <xsl:number format=\"a\" count=\"&FIGURE-LIKE;\"/>\n    <xsl:text>)</xsl:text>\n</xsl:template>\n\n<!-- when inside a sbsgroup, subnumbers range across entire group -->\n<xsl:template match=\"figure/sbsgroup/sidebyside/figure | figure/sbsgroup/sidebyside/table | figure/sbsgroup/sidebyside/listing | figure/sbsgroup/sidebyside/list\" mode=\"serial-number\">\n    <xsl:text>(</xsl:text>\n    <xsl:number format=\"a\" count=\"&FIGURE-LIKE;\" level=\"any\" from=\"sbsgroup\"/>\n    <xsl:text>)</xsl:text>\n</xsl:template>\n\n<!-- Serial Numbers: List Items -->\n\n<!-- First, the number of a list item within its own ordered list.  This -->\n<!-- trades on the PTX format codes being identical to the XSLT codes.   -->\n<xsl:template match=\"ol/li\" mode=\"item-number\">\n    <xsl:variable name=\"code\" select=\"../@pi:format-code\" />\n    <xsl:number format=\"{$code}\" />\n</xsl:template>\n\n<!-- Second, the serial number computed recursively.  The       -->\n<!-- entire hierarchy should be ordered lists, since otherwise, -->\n<!-- the template just below will apply instead.                -->\n<xsl:template match=\"ol/li\" mode=\"serial-number\">\n    <xsl:if test=\"ancestor::li\">\n        <xsl:apply-templates select=\"ancestor::li[1]\" mode=\"serial-number\" />\n        <xsl:text>.</xsl:text>\n    </xsl:if>\n    <xsl:apply-templates select=\".\" mode=\"item-number\" />\n</xsl:template>\n\n<!-- If any ancestor of a list item is not ordered, this     -->\n<!-- template should match first, and the serial number      -->\n<!-- will be empty, the signal that an object has no number. -->\n<xsl:template match=\"ul//li|dl//li\" mode=\"serial-number\" />\n\n\n<!-- Serial Numbers: Exercise Groups -->\n<!-- We provide the range of the     -->\n<!-- group as its serial number.     -->\n<xsl:template match=\"exercisegroup\" mode=\"serial-number\">\n    <xsl:apply-templates select=\"exercise[1]\" mode=\"serial-number\" />\n    <xsl:call-template name=\"character\">\n        <xsl:with-param name=\"name\" select=\"'ndash'\"/>\n    </xsl:call-template>\n    <xsl:apply-templates select=\"exercise[last()]\" mode=\"serial-number\" />\n</xsl:template>\n\n<!-- Serial Numbers: Tasks (in Projects) -->\n<!-- Tasks have \"list\" numbers, which we use on labels -->\n<!-- (we could use serial numbers for a more complex look) -->\n<xsl:template match=\"task\" mode=\"list-number\">\n    <xsl:number format=\"a\" />\n</xsl:template>\n<xsl:template match=\"task/task\" mode=\"list-number\">\n    <xsl:number format=\"i\" />\n</xsl:template>\n<xsl:template match=\"task/task/task\" mode=\"list-number\">\n    <xsl:number format=\"A\" />\n</xsl:template>\n<!-- concatenate list numbers to get serial numbers, eg a.i.A -->\n<xsl:template match=\"task\" mode=\"serial-number\">\n    <xsl:apply-templates select=\".\" mode=\"list-number\" />\n</xsl:template>\n<xsl:template match=\"task/task\" mode=\"serial-number\">\n    <xsl:apply-templates select=\"parent::task\" mode=\"serial-number\" />\n    <xsl:text>.</xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"list-number\" />\n</xsl:template>\n<xsl:template match=\"task/task/task\" mode=\"serial-number\">\n    <xsl:apply-templates select=\"parent::task\" mode=\"serial-number\" />\n    <xsl:text>.</xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"list-number\" />\n</xsl:template>\n\n<!-- Serial Numbers: fragments -->\n<!-- Simply numbered sequentially, globally. -->\n<xsl:template match=\"fragment\" mode=\"serial-number\">\n    <xsl:number level=\"any\"/>\n</xsl:template>\n\n\n<!-- Serial Numbers: the unnumbered     -->\n<!-- Empty string signifies not numbered -->\n\n<!-- We choose not to number unique, or semi-unique      -->\n<!-- (eg prefaces, colophons), elements.  Other elements -->\n<!-- are meant as local commentary, and may also carry   -->\n<!-- a title for identification and cross-referencing.   -->\n<xsl:template match=\"book|article|letter|memo|paragraphs|blockquote|preface|abstract|acknowledgement|biography|foreword|dedication|contributors|index-part|index[index-list]|colophon|webwork|p|assemblage|aside|biographical|historical|case|contributor\" mode=\"serial-number\" />\n\n<!-- Some divisions, like \"exercises\", \"solutions\", \"references\",     -->\n<!-- are part of the hierarchical numbering scheme, and look simply   -->\n<!-- to their parent.  Which could be the top-level when in th main   -->\n<!-- matter (we handle cases of children of \"backmatter\" carefully    -->\n<!-- elsewhere or it does not happen).  So we need an empty structure -->\n<!-- number for these cases.                                          -->\n<xsl:template match=\"book|article|letter|memo\" mode=\"structure-number\" />\n\n<!-- Some items are \"containers\".  They are not numbered, you  -->\n<!-- cannot point to them, they are invisible to the reader    -->\n<!-- in a way.  We kill their serial numbers explicitly here.  -->\n<!-- Lists live in paragraphs, exercises, objectives, so       -->\n<!-- should be referenced as part of some enclosing element.   -->\n<!-- \"mathbook\" helps some tree-climbing routines halt -->\n<xsl:template match=\"mathbook|pretext|frontmatter|backmatter|sidebyside|sbsgroup|ol|ul|dl|statement\" mode=\"serial-number\" />\n\n<!-- An \"introduction\" or \"conclusion\" of a structured division (a   -->\n<!-- \"division companion\") occurs at most once per division, and so   -->\n<!-- takes its number from the parent, exactly as GOAL-LIKE does.    -->\n<!-- The number is never displayed where born; it only serves to     -->\n<!-- identify the target of a cross-reference.  Every other flavor   -->\n<!-- (in blocks, tasks, exercise groups, ...) has no number at all.  -->\n<xsl:template match=\"introduction|conclusion\" mode=\"serial-number\"/>\n\n<xsl:template match=\"introduction[parent::article or parent::chapter or parent::appendix or parent::section or parent::subsection]|conclusion[parent::article or parent::chapter or parent::appendix or parent::section or parent::subsection]\" mode=\"serial-number\">\n    <xsl:apply-templates select=\"parent::*\" mode=\"serial-number\"/>\n</xsl:template>\n\n<xsl:template match=\"introduction[parent::article or parent::chapter or parent::appendix or parent::section or parent::subsection]|conclusion[parent::article or parent::chapter or parent::appendix or parent::section or parent::subsection]\" mode=\"structure-number\">\n    <xsl:apply-templates select=\"parent::*\" mode=\"structure-number\"/>\n</xsl:template>\n\n<!-- Poems go by their titles, not numbers -->\n<xsl:template match=\"poem\" mode=\"serial-number\" />\n\n<!-- Preformatted (\"pre\") appear in search results by name -->\n<xsl:template match=\"pre\" mode=\"serial-number\" />\n\n<!-- List items, subordinate to an unordered list, or a description  -->\n<!-- list, will have numbers that are especically ambiguous, perhaps -->\n<!-- even very clsoe within a multi-level list. They are unnumbered  -->\n<!-- in the vicinity of computing serial numbers of list items in    -->\n<!-- ordered lists.                                                  -->\n\n<!-- Every displayed equation eventually lands inside an \"mrow\" and  -->\n<!-- the pre-processor identifies it as numbered or not, so the      -->\n<!-- unnumbered ones are straightforward.  A local tag (@tag)        -->\n<!-- authored on an \"mrow\" is considered an unnumbered equation.     -->\n<xsl:template match=\"mrow[@pi:numbered = 'no']\" mode=\"serial-number\"/>\n\n<!-- WeBWorK problems are never numbered, because they live    -->\n<!-- in (numbered) exercises.  But they have identically named -->\n<!-- components of exercises, so we might need to explicitly   -->\n<!-- make webwork/solution, etc to be unnumbered.              -->\n\n<!-- Glossary items (\"gi\"), in a \"glossary\", are known by their title -->\n<xsl:template match=\"gi\" mode=\"serial-number\"/>\n\n<!-- GOAL-LIKE are one-per-subdivision,               -->\n<!-- and so get their serial number from their parent -->\n<xsl:template match=\"&GOAL-LIKE;\" mode=\"serial-number\">\n    <xsl:apply-templates select=\"parent::*\" mode=\"serial-number\" />\n</xsl:template>\n\n<!-- A subexercises is meant to be minimal, and does not have a number -->\n<xsl:template match=\"subexercises\" mode=\"serial-number\"/>\n\n<!-- We only allow one \"instructions\" for an \"interactive\" -->\n<xsl:template match=\"interactive/instructions\" mode=\"serial-number\"/>\n\n<!-- Multi-part WeBWorK problems have PTX elements        -->\n<!-- called \"stage\" which typically render as \"Part...\"   -->\n<!-- Their serial numbers are useful, there is no attempt -->\n<!-- above to integrate these into our general scheme     -->\n<!-- These are just counted among enclosing \"webwork\"     -->\n<xsl:template match=\"webwork/stage\" mode=\"serial-number\">\n    <xsl:number count=\"stage\" from=\"webwork\" />\n</xsl:template>\n\n<!-- But when a problem is part of the OPL and is retrieved -->\n<!-- from the server, then we don't see the \"stage\" element -->\n<!-- until we merge in the \"static\" version as part of the  -->\n<!-- \"webwork-reps\" collection                              -->\n<xsl:template match=\"webwork-reps/static/stage\" mode=\"serial-number\">\n    <xsl:number count=\"stage\" from=\"static\" />\n</xsl:template>\n\n<!-- OPENPROBLEM-LIKE are blocks: their serial number is read from @pi:serial, -->\n<!-- alongside the other block families above.  Their structure number         -->\n<!-- follows the figure/project pattern: the open-problem level when they      -->\n<!-- run on a distinct counter, otherwise the shared \"blocks\" level.           -->\n<xsl:template match=\"&OPENPROBLEM-LIKE;\" mode=\"structure-number\">\n    <xsl:variable name=\"openproblem-levels\">\n        <xsl:choose>\n            <xsl:when test=\"$b-number-openproblem-distinct\">\n                <xsl:value-of select=\"$numbering-openproblems\" />\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$numbering-blocks\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:call-template name=\"block-structure-number\">\n        <xsl:with-param name=\"levels\" select=\"$openproblem-levels\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- DISCUSSION-LIKE are appendages; their number is inherited from the parent. -->\n<xsl:template match=\"&DISCUSSION-LIKE;\" mode=\"serial-number\">\n    <xsl:number select=\"parent::*\" count=\"&DISCUSSION-LIKE;\"/>\n</xsl:template>\n<xsl:template match=\"&DISCUSSION-LIKE;\" mode=\"structure-number\">\n    <xsl:apply-templates select=\"parent::*\" mode=\"number\"/>\n</xsl:template>\n\n<!-- No numbers on pages of worksheets -->\n<xsl:template match=\"page\" mode=\"serial-number\"/>\n\n<!-- Should not drop in here.  Ever. -->\n<xsl:template match=\"*\" mode=\"serial-number\">\n    <xsl:text>[NUM]</xsl:text>\n    <xsl:message>PTX:BUG:   An object (<xsl:value-of select=\"local-name(.)\" />) lacks a serial number, search output for \"[NUM]\"</xsl:message>\n    <xsl:apply-templates select=\".\" mode=\"location-report\" />\n</xsl:template>\n\n<!--                       -->\n<!-- Multi-Numbers Utility -->\n<!--                       -->\n\n<!--                         -->\n<!-- Structure Numbers       -->\n<!--                         -->\n\n<!-- We compute multi-part numbers to the necessary,  -->\n<!-- or configured, number of components              -->\n<!-- NB: *every* structure number should finish with  -->\n<!-- a period as a separator, which is often provided -->\n<!-- by the \"multi-number\" template.  Some of the     -->\n<!-- cross-reference text code adds a period before   -->\n<!-- testing equality of strings                      -->\n\n<!-- Structure Numbers: Divisions -->\n<!-- NB: this is number of the *container* of the division,   -->\n<!-- a serial number for the division itself will be appended -->\n<xsl:template match=\"part|chapter|appendix|section|subsection|subsubsection|backmatter/solutions\" mode=\"structure-number\">\n    <xsl:value-of select=\"@pi:struct\"/>\n</xsl:template>\n\n<!-- Structure Numbers: Specialized Divisions -->\n<!-- Some divisions get their numbers from their parents, or  -->\n<!-- in other ways.  We are careful to do this by determining -->\n<!-- the serial-numer and the structure-number, so that other -->\n<!-- devices (like local numbers) will behave correctly.      -->\n<!-- Serial numbers are computed elsewhere, but in tandem.    -->\n<xsl:template match=\"exercises|solutions[not(parent::backmatter)]|worksheet|handout|reading-questions|references[not(parent::backmatter)]|glossary[not(parent::backmatter)]\" mode=\"structure-number\">\n    <xsl:variable name=\"is-numbered\">\n        <xsl:apply-templates select=\".\" mode=\"is-specialized-own-number\"/>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$is-numbered = 'true'\">\n            <xsl:value-of select=\"@pi:struct\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\"parent::*\" mode=\"structure-number\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n<!-- \"references\" and \"glossary\" are solo in main matter -->\n<!-- divisions, unique and not numbered in back matter   -->\n<xsl:template match=\"backmatter/references\" mode=\"structure-number\" />\n<xsl:template match=\"backmatter/glossary\" mode=\"structure-number\" />\n\n\n<!-- Structure Numbers: Theorems, Examples, Projects, Figures -->\n<xsl:template match=\"&DEFINITION-LIKE;|&THEOREM-LIKE;|&AXIOM-LIKE;|&REMARK-LIKE;|&COMPUTATION-LIKE;|&EXAMPLE-LIKE;\" mode=\"structure-number\">\n    <xsl:call-template name=\"block-structure-number\">\n        <xsl:with-param name=\"levels\" select=\"$numbering-blocks\"/>\n    </xsl:call-template>\n</xsl:template>\n<!-- PROJECT-LIKE is now independent, under control of $numbering-projects -->\n<!-- But all ready to become elective -->\n<xsl:template match=\"&PROJECT-LIKE;\"  mode=\"structure-number\">\n    <xsl:variable name=\"project-levels\">\n        <xsl:choose>\n            <xsl:when test=\"$b-number-project-distinct\">\n                <xsl:value-of select=\"$numbering-projects\" />\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$numbering-blocks\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:call-template name=\"block-structure-number\">\n        <xsl:with-param name=\"levels\" select=\"$project-levels\"/>\n    </xsl:call-template>\n</xsl:template>\n<!-- FIGURE-LIKE get a structure number from default $numbering-blocks -->\n<!-- or from \"docinfo\" independent numbering configuration             -->\n<xsl:template match=\"&FIGURE-LIKE;\"  mode=\"structure-number\">\n    <xsl:variable name=\"figure-levels\">\n        <xsl:choose>\n            <xsl:when test=\"$b-number-figure-distinct\">\n                <xsl:value-of select=\"$numbering-figures\" />\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$numbering-blocks\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:call-template name=\"block-structure-number\">\n        <xsl:with-param name=\"levels\" select=\"$figure-levels\"/>\n    </xsl:call-template>\n</xsl:template>\n<!-- Proofs get structure number from parent theorem -->\n<!-- NB: assumes proofs are not detached? Maybe not.      -->\n<!-- Definitely a detached proof in a \"paragraphs\" is bad -->\n<xsl:template match=\"&PROOF-LIKE;\" mode=\"structure-number\">\n    <xsl:apply-templates select=\"parent::*\" mode=\"number\" />\n</xsl:template>\n<!-- Captioned items, arranged in a side-by-side,      -->\n<!-- then inside a captioned figure, earn a serial     -->\n<!-- number that is a letter.  So their structure      -->\n<!-- number comes from the enclosing captioned figure. -->\n<!-- The sidebyside may be a child of the figure,      -->\n<!-- or wrapped in an sbsgroup.                        -->\n<xsl:template match=\"figure/sidebyside/figure | figure/sidebyside/table | figure/sidebyside/listing | figure/sidebyside/list\" mode=\"structure-number\">\n    <xsl:apply-templates select=\"parent::sidebyside/parent::figure\" mode=\"number\" />\n</xsl:template>\n<xsl:template match=\"figure/sbsgroup/sidebyside/figure | figure/sbsgroup/sidebyside/table | figure/sbsgroup/sidebyside/listing | figure/sbsgroup/sidebyside/list\" mode=\"structure-number\">\n    <xsl:apply-templates select=\"parent::sidebyside/parent::sbsgroup/parent::figure\" mode=\"number\" />\n</xsl:template>\n\n<!-- Structure Numbers: Equations -->\n<!-- \"mrow\" may be numbered, and bare \"md\" inherit a number from their  -->\n<!-- manufactured single \"mrow\".  So we need a structure number for the -->\n<!-- numbered versions of these elements.                               -->\n<xsl:template match=\"mrow|md[@pi:authored-one-line]\" mode=\"structure-number\">\n    <xsl:call-template name=\"block-structure-number\">\n        <xsl:with-param name=\"levels\" select=\"$numbering-equations\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- Structure Numbers: Inline Exercises -->\n<!-- Follows the theorem/figure/etc scheme.  The second alternative   -->\n<!-- adds an inline exercise in a division introduction or conclusion -->\n<!-- (its parent is not in the inline filter); divisional-container   -->\n<!-- exercises are handled by the next template instead.              -->\n<xsl:template match=\"exercise[boolean(&INLINE-EXERCISE-FILTER;)]|exercise[(parent::introduction or parent::conclusion) and not(ancestor::exercises or ancestor::worksheet or ancestor::reading-questions)]\" mode=\"structure-number\">\n    <xsl:variable name=\"exercise-levels\">\n        <xsl:choose>\n            <xsl:when test=\"$b-number-exercise-distinct\">\n                <xsl:value-of select=\"$numbering-exercises\" />\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$numbering-blocks\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:call-template name=\"block-structure-number\">\n        <xsl:with-param name=\"levels\" select=\"$exercise-levels\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- Structure Numbers: Divisional and Worksheet Exercises -->\n<!-- Within a \"exercises\" or \"worksheet\", look up to enclosing division -->\n<!-- in order to decide where the structure number comes from           -->\n<xsl:template match=\"exercises//exercise|worksheet//exercise|reading-questions//exercise\" mode=\"structure-number\">\n    <!-- Need to look up through \"exercisegroup\", \"subexercises\", \"sidebyside\", etc -->\n    <!-- Only one of these specialized divisions, just a single node in variable    -->\n    <xsl:variable name=\"container\" select=\"ancestor::*[self::exercises or self::worksheet or self::reading-questions]\"/>\n    <xsl:apply-templates select=\"$container\" mode=\"number\" />\n</xsl:template>\n\n<!-- Structure Numbers: Exercise Groups -->\n<!-- An exercisegroup gets it structure number from the parent exercises -->\n<xsl:template match=\"exercisegroup\" mode=\"structure-number\">\n    <xsl:apply-templates select=\"parent::*\" mode=\"number\" />\n</xsl:template>\n\n<!-- Hints, answers, solutions get structure number from parent       -->\n<!-- exercise's number. Identical for inline and divisional exercises -->\n<xsl:template match=\"&SOLUTION-LIKE;\" mode=\"structure-number\">\n    <xsl:apply-templates select=\"parent::*\" mode=\"number\" />\n</xsl:template>\n\n<!-- Anything within a webwork-reps that needs a structure number    -->\n<!-- gets it from the enclosing exercise.                            -->\n<xsl:template match=\"webwork-reps//*\" mode=\"structure-number\">\n    <xsl:apply-templates select=\"ancestor::exercise\" mode=\"number\" />\n</xsl:template>\n\n<!-- Structure Numbers: Bibliographic Items -->\n<!-- Bibliographic items get their number from the containing     -->\n<!-- \"references\", which may be solo in an unstructured division, -->\n<!-- or one of potentially several in a structured division.      -->\n<!-- Since the global \"references\" (child of \"backmatter\") is not -->\n<!-- numbered, these items will have un-qualified numbers         -->\n<!-- (serial number only). -->\n<xsl:template match=\"biblio\" mode=\"structure-number\">\n    <xsl:apply-templates select=\"parent::*\" mode=\"number\" />\n</xsl:template>\n\n<!-- Notes get structure number from parent biblio's number -->\n<xsl:template match=\"biblio/note\" mode=\"structure-number\">\n    <xsl:apply-templates select=\"parent::*\" mode=\"number\" />\n</xsl:template>\n\n<!-- Structure Numbers: Footnotes -->\n<xsl:template match=\"fn\" mode=\"structure-number\">\n    <xsl:call-template name=\"block-structure-number\">\n        <xsl:with-param name=\"levels\" select=\"$numbering-footnotes\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- Structure Numbers: Lists -->\n<!-- Lists occur in paragraphs (anonymously), in \"list\"      -->\n<!-- blocks (numbered), and within exercises (numbered).     -->\n<!-- Typically we are interested in list items (only),       -->\n<!-- since that is where there is content.  And then we      -->\n<!-- are only interested in the list items within an ordered -->\n<!-- list.  We control for items under unordered lists or    -->\n<!-- description lists elsewhere by providing empty numbers. -->\n<!-- NB: the order of these templates may matter             -->\n<xsl:template match=\"li\" mode=\"structure-number\" />\n\n<xsl:template match=\"list//li\" mode=\"structure-number\">\n    <xsl:apply-templates select=\"ancestor::list\" mode=\"number\" />\n</xsl:template>\n\n<xsl:template match=\"exercise//li\" mode=\"structure-number\">\n    <xsl:apply-templates select=\"ancestor::exercise\" mode=\"number\" />\n</xsl:template>\n\n<!-- Structure Numbers: Tasks (in projects) -->\n<!-- A task gets it structure number from the parent project-like -->\n<xsl:template match=\"task\" mode=\"structure-number\">\n    <!-- ancestors, strip tasks, get number of next enclosure -->\n    <xsl:apply-templates select=\"ancestor::*[not(self::task)][1]\" mode=\"number\" />\n</xsl:template>\n\n<!-- Structure Numbers: GOAL-LIKE -->\n<!-- Objectives are one-per-subdivision, and so   -->\n<!-- get their structure number from their parent -->\n<xsl:template match=\"&GOAL-LIKE;\" mode=\"structure-number\">\n    <xsl:apply-templates select=\"parent::*\" mode=\"structure-number\" />\n</xsl:template>\n\n<!-- Structure Numbers: Objective and Outcome-->\n<!-- A single objective or outcome is a list item -->\n<!-- in an objectives or outcomes environment     -->\n<xsl:template match=\"objectives/ol/li|outcomes/ol/li\" mode=\"structure-number\">\n    <xsl:apply-templates select=\"ancestor::*[&STRUCTURAL-FILTER;][1]\" mode=\"number\" />\n</xsl:template>\n\n<!-- Structure Numbers: Fragment -->\n<!-- We number serially, see below -->\n<xsl:template match=\"fragment\" mode=\"structure-number\"/>\n\n<!-- worksheet pages are unnumbered -->\n<xsl:template match=\"page\" mode=\"structure-number\"/>\n\n<!-- Should not drop in here.  Ever. -->\n<xsl:template match=\"*\" mode=\"structure-number\">\n    <xsl:text>[STRUCT]</xsl:text>\n    <xsl:message>PTX:BUG:   An object (<xsl:value-of select=\"local-name(.)\" />) lacks a structure number, search output for \"[STRUCT]\"</xsl:message>\n    <xsl:apply-templates select=\".\" mode=\"location-report\" />\n</xsl:template>\n\n<!--              -->\n<!-- Full Numbers -->\n<!--              -->\n\n<!-- The \"number\" of a table note (\"tn\") is its letter: a, b, c,     -->\n<!-- assigned per-\"tabular\" in document order of the marks, which is -->\n<!-- reading order (Notes to tables: CMoS 18th ed., 3.77-3.81;       -->\n<!-- specific notes at 3.80).  One computation, consumed by every    -->\n<!-- conversion, and deliberately disjoint from the numbering of     -->\n<!-- true footnotes.                                                 -->\n<xsl:template match=\"tabular//tn\" mode=\"number\">\n    <xsl:number level=\"any\" from=\"tabular\" format=\"a\"/>\n</xsl:template>\n\n<!-- Now trivial, the container structure plus the serial.  -->\n<!-- We condition on empty serial number in order to create -->\n<!-- empty full numbers.  This is where we add separator,   -->\n<!-- normally a period, but for a list item within a named  -->\n<!-- list, we use a colon (a double period?).               -->\n<xsl:template match=\"*\" mode=\"number\">\n    <xsl:variable name=\"serial\">\n        <xsl:apply-templates select=\".\" mode=\"serial-number\" />\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$serial = ''\" />\n        <xsl:otherwise>\n            <xsl:variable name=\"structure\">\n                <xsl:apply-templates select=\".\" mode=\"structure-number\" />\n            </xsl:variable>\n            <xsl:if test=\"not($structure='')\">\n                <xsl:value-of select=\"$structure\" />\n                <xsl:choose>\n                    <xsl:when test=\"self::li and ancestor::list\">\n                        <xsl:text>:</xsl:text>\n                    </xsl:when>\n                    <!-- A figure-like inside a sidebyside (or       -->\n                    <!-- sbsgroup) inside a figure is subnumbered    -->\n                    <!-- with a letter like \"(a)\", so the serial     -->\n                    <!-- number already carries its own delimiter    -->\n                    <!-- and no period separator is needed.          -->\n                    <xsl:when test=\"(&FIGURE-FILTER;) and (parent::sidebyside/parent::figure or parent::sidebyside/parent::sbsgroup/parent::figure)\"/>\n                    <xsl:otherwise>\n                        <xsl:text>.</xsl:text>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:if>\n            <xsl:value-of select=\"$serial\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- ##### Division serial numbers ##### -->\n<!-- ############## -->\n<!-- Serial Numbers -->\n<!-- ############## -->\n\n<!-- Serial Numbers: Divisions -->\n<!-- To respect the maximum level for numbering, we          -->\n<!-- return an empty serial number at an excessive level,    -->\n<!-- otherwise we call for a serial number relative to peers -->\n<xsl:template match=\"part|chapter|appendix|section|subsection|subsubsection|backmatter/solutions\" mode=\"serial-number\">\n    <xsl:variable name=\"relative-level\">\n        <xsl:apply-templates select=\".\" mode=\"new-level\" />\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$relative-level > $numbering-maxlevel\" />\n        <xsl:otherwise>\n            <xsl:value-of select=\"@pi:serial\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Serial Numbers: Specialized Divisions -->\n<xsl:template match=\"exercises|solutions|worksheet|handout|reading-questions|references|glossary\" mode=\"serial-number\">\n    <xsl:variable name=\"is-numbered\">\n        <xsl:apply-templates select=\".\" mode=\"is-specialized-own-number\"/>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$is-numbered = 'true'\">\n            <xsl:variable name=\"relative-level\">\n                <xsl:apply-templates select=\".\" mode=\"new-level\" />\n            </xsl:variable>\n            <xsl:choose>\n                <xsl:when test=\"$relative-level > $numbering-maxlevel\" />\n                <xsl:otherwise>\n                    <xsl:value-of select=\"@pi:serial\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\"parent::*\" mode=\"serial-number\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n</xsl:stylesheet>\n","pretext-revealjs.xsl":"<?xml version='1.0'?>\n\n<!--********************************************************************\nCopyright 2019 Andrew Rechnitzer, Steven Clontz, Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- http://pimpmyxslt.com/articles/entity-tricks-part2/ -->\n<!DOCTYPE xsl:stylesheet [\n    <!ENTITY % entities SYSTEM \"entities.ent\">\n    %entities;\n]>\n\n<!-- \"pi\" necessary to trap \"visual\" URLs automatically being -->\n<!-- added by \"assembly\" for with-content \"url\" elements      -->\n<xsl:stylesheet\n    xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\"\n    xmlns:xml=\"http://www.w3.org/XML/1998/namespace\"\n    xmlns:pi=\"http://pretextbook.org/2020/pretext/internal\"\n    xmlns:svg=\"http://www.w3.org/2000/svg\"\n    xmlns:pf=\"https://prefigure.org\"\n    xmlns:exsl=\"http://exslt.org/common\"\n    xmlns:date=\"http://exslt.org/dates-and-times\"\n    xmlns:str=\"http://exslt.org/strings\"\n    extension-element-prefixes=\"exsl date str\"\n    exclude-result-prefixes=\"svg pf\"\n>\n\n<!-- Necessary to get some HTML constructions,    -->\n<!-- but want to be sure to override the entry    -->\n<!-- template to avoid chunking, etc.             -->\n<!-- The pretext-assembly stylesheet is employed, -->\n<!-- so be sure to use the right trees in the     -->\n<!-- entry template                               -->\n<xsl:import href=\"pretext-html.xsl\" />\n\n<!-- Disable clipboardable -->\n<xsl:template name=\"insert-clipboardable-class\"/>\n\n<!-- Used to identify build target in templates shared with plain  -->\n<!-- HTML conversion (preferably avoid using this).                -->\n<xsl:variable name=\"b-reveal-build\" select=\"true()\" />\n\n<!-- Embedded mathematics: files of per-equation SVG and speech     -->\n<!-- representations, keyed by id, manufactured at build time by    -->\n<!-- the \"mathjax_latex()\" routine and passed in here as string     -->\n<!-- parameters.  Both are empty for online mathematics (the        -->\n<!-- default), and then the derived variables are empty node-sets,  -->\n<!-- never consulted.                                               -->\n<xsl:param name=\"mathfile\" select=\"''\"/>\n<xsl:param name=\"speechfile\" select=\"''\"/>\n<xsl:variable name=\"math-repr\" select=\"document($mathfile)/pi:math-representations\"/>\n<xsl:variable name=\"speech-repr\" select=\"document($speechfile)/pi:math-representations\"/>\n\n<!-- Reveal.js output is one monolithic page, so heading levels are -->\n<!-- threaded, not chunked.  The slideshow title (h1) and subtitle  -->\n<!-- (h2) are fixed.  A \"section\" is always level 2 (sections never -->\n<!-- nest in a slideshow), so a \"slide\" title is level 3 when there -->\n<!-- are sections and level 2 when there are none; slide content    -->\n<!-- begins one level deeper.                                       -->\n<xsl:variable name=\"b-reveal-has-sections\" select=\"boolean($root/slideshow/section)\"/>\n<xsl:variable name=\"reveal-slide-heading-level\">\n    <xsl:choose>\n        <xsl:when test=\"$b-reveal-has-sections\">\n            <xsl:text>3</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>2</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- HTML5 format -->\n<xsl:output method=\"html\" indent=\"yes\" encoding=\"UTF-8\" doctype-system=\"about:legacy-compat\"/>\n\n<!-- Publisher Switches -->\n<!-- Various configuration options are set in the publisher file,  -->\n<!-- which is analyzed by its own stylesheet, which is imported in -->\n<!-- the process of importing the pretext-html.xsl stylesheet.     -->\n\n<!-- ################ -->\n<!-- # Entry Template -->\n<!-- ################ -->\n\n<!-- We override the entry template, so as to avoid the \"chunking\"    -->\n<!-- procedure, since we are going to *always* produce one monolithic -->\n<!-- HTML file as the output/slideshow                                -->\n<xsl:template match=\"/\">\n    <xsl:call-template name=\"reveal-warnings\"/>\n    <xsl:apply-templates select=\"$original\" mode=\"generic-warnings\"/>\n    <xsl:apply-templates select=\"$original\" mode=\"element-deprecation-warnings\"/>\n    <xsl:apply-templates select=\"$original\" mode=\"parameter-deprecation-warnings\"/>\n    <xsl:apply-templates select=\"$root\"/>\n</xsl:template>\n\n<xsl:template match=\"/pretext\">\n  <xsl:apply-templates select=\"slideshow\" />\n</xsl:template>\n\n<!-- Kill creation of the index page from the -html -->\n<!-- conversion (we just build one monolithic page) -->\n<xsl:variable name=\"html-index-page\" select=\"/..\"/>\n\n<!-- Kill knowl-ing of various environments -->\n<xsl:template match=\"&THEOREM-LIKE;|&PROOF-LIKE;|&DEFINITION-LIKE;|&EXAMPLE-LIKE;|&PROJECT-LIKE;|task|&FIGURE-LIKE;|&REMARK-LIKE;|&GOAL-LIKE;|exercise\" mode=\"is-hidden\">\n    <xsl:text>no</xsl:text>\n</xsl:template>\n\n<!-- The HTML conversion computes a global \"universal\" Table of    -->\n<!-- Contents for the sidebar.  Then later, for each page it sees  -->\n<!-- some customization.  So we reset the variable here, and that  -->\n<!-- also means the work done in the \"toc-items\" template never    -->\n<!-- occurs.  (And even better, doing the work was exposing that   -->\n<!-- the \"level\" template wasn't working right for a \"slideshow\".) -->\n<xsl:variable name=\"toc-cache-rtf\" select=\"''\"/>\n\n<!-- Write the infrastructure for a page -->\n<xsl:template match=\"slideshow\">\n    <xsl:call-template name=\"converter-blurb-html\" />\n    <html>\n        <head>\n            <title>\n                <xsl:apply-templates select=\".\" mode=\"title-simple\" />\n            </title>\n\n            <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes\"></meta>\n\n            <xsl:call-template name=\"sagecell-code\" />\n            <xsl:apply-templates select=\".\" mode=\"sagecell\" />\n            <xsl:call-template name=\"syntax-highlight\"/>\n\n            <!-- load reveal.js resources; w/ v 6.x                 -->\n            <!-- paths are relative to the distribution's \"dist\"    -->\n            <!-- directory, whose layout a \"local\" resource host    -->\n            <!-- must reproduce                                     -->\n            <link href=\"{$reveal-root}/reset.css\" rel=\"stylesheet\"></link>\n            <link href=\"{$reveal-root}/reveal.css\" rel=\"stylesheet\"></link>\n            <link href=\"{$reveal-root}/theme/{$reveal-theme}.css\" rel=\"stylesheet\"></link>\n            <script src=\"{$reveal-root}/reveal.js\"></script>\n            <!-- embedded mathematics needs no typesetting, so no math plugin -->\n            <xsl:if test=\"not($b-reveal-embedded-math)\">\n                <script src=\"{$reveal-root}/plugin/math.js\"></script>\n            </xsl:if>\n\n            <link href=\"_static/pretext/css/pretext-reveal.css\" rel=\"stylesheet\"></link>\n          <style>\n            <xsl:if test=\"$b-reveal-embedded-math\">\n                <!-- layout for build-time SVG images of mathematics; the -->\n                <!-- class names are those of the EPUB conversion, which  -->\n                <!-- pioneered this device                                -->\n                <xsl:text>span.mjpage { display: inline; }&#xa;</xsl:text>\n                <xsl:text>span.mjpage__block { display: block; text-align: center; margin: 0.5em 0; }&#xa;</xsl:text>\n            </xsl:if>\n            <!-- Vertical alignment of slides diverging from the      -->\n            <!-- document-wide default.  reveal.js absolutely         -->\n            <!-- positions each slide, and when configured to center  -->\n            <!-- (\"center: true\") it computes an inline \"top\" offset, -->\n            <!-- which only \"!important\" can overrule.  A top-aligned -->\n            <!-- slide just pins that offset to zero.  Middle and     -->\n            <!-- bottom alignment stretch the slide to the full frame -->\n            <!-- and place its content by flexbox; the \"display\" rule -->\n            <!-- is confined to the \"present\" slide so hidden slides  -->\n            <!-- retain \"display: none\".                              -->\n            <xsl:text>.reveal .slides section.valign-top { top: 0 !important; }&#xa;</xsl:text>\n            <xsl:text>.reveal .slides section.valign-middle.present { display: flex !important; flex-direction: column; justify-content: center; top: 0 !important; height: 100% !important; }&#xa;</xsl:text>\n            <xsl:text>.reveal .slides section.valign-bottom.present { display: flex !important; flex-direction: column; justify-content: flex-end; top: 0 !important; height: 100% !important; }&#xa;</xsl:text>\n          </style>\n          <!-- no diagcess machinery with embedded mathematics: an  -->\n          <!-- annotated PreFigure diagram is then a static image   -->\n          <xsl:if test=\"not($b-reveal-embedded-math)\">\n              <xsl:call-template name=\"diagcess-header\"/>\n          </xsl:if>\n\n          <!-- custom-css, if specified, should be last -->\n          <xsl:if test=\"not($reveal-custom-css = '')\">\n              <xsl:variable name=\"csses\" select=\"str:tokenize($reveal-custom-css, ', ')\"/>\n              <xsl:for-each select=\"$csses\">\n                  <link rel=\"stylesheet\" type=\"text/css\">\n                      <xsl:attribute name=\"href\">\n                          <xsl:value-of select=\".\" />\n                      </xsl:attribute>\n                  </link>\n              </xsl:for-each>\n          </xsl:if>\n        </head>\n\n        <body>\n            <div class=\"reveal ptx-content\">\n                <!-- For mathematics/MathJax, must be located  -->\n                <!-- within div.reveal to be effective.  With  -->\n                <!-- embedded mathematics the macros are baked -->\n                <!-- into the SVG images at build time, so the -->\n                <!-- hidden macro division would be inert.     -->\n                <xsl:if test=\"not($b-reveal-embedded-math)\">\n                    <xsl:apply-templates select=\".\" mode=\"latex-macros\"/>\n                </xsl:if>\n                <div class=\"slides\">\n                     <xsl:apply-templates select=\"frontmatter\"/>\n                    <xsl:apply-templates select=\"section|slide\"/>\n                </div>\n            </div>\n            <xsl:if test=\"not($b-reveal-embedded-math)\">\n                <xsl:call-template name=\"diagcess-footer\"/>\n            </xsl:if>\n        </body>\n\n        <script>\n            <xsl:text>&#xa;</xsl:text>\n            <xsl:text>Reveal.initialize({&#xa;</xsl:text>\n            <xsl:text>  controls: </xsl:text>\n                <xsl:choose>\n                    <xsl:when test=\"$b-reveal-control-display\">\n                        <xsl:text>true</xsl:text>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:text>false</xsl:text>\n                    </xsl:otherwise>\n                </xsl:choose>\n            <xsl:text>,&#xa;</xsl:text>\n            <xsl:text>  controlsTutorial: </xsl:text>\n                <xsl:choose>\n                    <xsl:when test=\"$b-reveal-control-tutorial\">\n                        <xsl:text>true</xsl:text>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:text>false</xsl:text>\n                    </xsl:otherwise>\n                </xsl:choose>\n            <xsl:text>,&#xa;</xsl:text>\n            <xsl:text>  controlsLayout: '</xsl:text>\n                <xsl:value-of select=\"$reveal-control-layout\"/>\n            <xsl:text>',&#xa;</xsl:text>\n            <xsl:text>  controlsBackArrows: '</xsl:text>\n                <xsl:value-of select=\"$reveal-control-backarrow\"/>\n            <xsl:text>',&#xa;</xsl:text>\n            <xsl:text>  navigationMode: '</xsl:text>\n                <xsl:value-of select=\"$reveal-navigation-mode\"/>\n            <xsl:text>',&#xa;</xsl:text>\n            <xsl:text>  progress: false,&#xa;</xsl:text>\n            <!-- reveal.js \"center\" vertically centers every slide,  -->\n            <!-- so it realizes a document-wide \"middle\" default;    -->\n            <!-- a \"top\" or \"bottom\" default disables it, and slides -->\n            <!-- diverging from the default get a class instead      -->\n            <xsl:text>  center: </xsl:text>\n                <xsl:choose>\n                    <xsl:when test=\"$slides-valign-default = 'middle'\">\n                        <xsl:text>true</xsl:text>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:text>false</xsl:text>\n                    </xsl:otherwise>\n                </xsl:choose>\n            <xsl:text>,&#xa;</xsl:text>\n            <xsl:text>  hash: true,&#xa;</xsl:text>\n            <xsl:text>  transition: 'fade',&#xa;</xsl:text>\n            <xsl:text>  width: \"100%\",&#xa;</xsl:text>\n            <xsl:text>  height: \"100%\",&#xa;</xsl:text>\n            <!-- \"margin\" must be a JavaScript number.  The PDF export     -->\n            <!-- computes its page size as (slide dimension)*(1 + margin); -->\n            <!-- a quoted value concatenates instead of adding, producing  -->\n            <!-- pages ten times too large, and a print dialog then        -->\n            <!-- shrinks each slide to a small fraction of the paper.      -->\n            <xsl:text>  margin: 0.025,&#xa;</xsl:text>\n            <xsl:choose>\n                <!-- Embedded mathematics is finished SVG images: -->\n                <!-- no math plugin, no typesetting configuration -->\n                <xsl:when test=\"$b-reveal-embedded-math\">\n                    <xsl:text>  plugins: []&#xa;</xsl:text>\n                </xsl:when>\n                <!-- Explicitly enable AMS-style inline \\(...\\),      -->\n                <!-- and explicitly disable TeX-style inline $...$    -->\n                <!-- The main HTML conversion does not do anything    -->\n                <!-- special for display math, so we disable any such -->\n                <!-- markup, since we use environments exclusively.   -->\n                <!-- N.B. default HTML adds a \"zero-width\" space into -->\n                <!-- a \\( authored in a non-math context.             -->\n                <!-- The MathJax version matches the main HTML        -->\n                <!-- conversion; the \"mathjax4\" adapter of the math   -->\n                <!-- plugin loads it from the URL given and passes    -->\n                <!-- the \"tex\" object into the MathJax configuration. -->\n                <!-- Suggested by  https://revealjs.com/math/, 2026-07-22 -->\n                <xsl:otherwise>\n                    <xsl:text>  mathjax4: {&#xa;</xsl:text>\n                    <xsl:text>    mathjax: 'https://cdn.jsdelivr.net/npm/mathjax@4/tex-mml-chtml.js',&#xa;</xsl:text>\n                    <xsl:text>    tex: {&#xa;</xsl:text>\n                    <xsl:text>      inlineMath:  [['\\\\(','\\\\)']],&#xa;</xsl:text>\n                    <xsl:text>      displayMath: [],&#xa;</xsl:text>\n                    <xsl:text>    }&#xa;</xsl:text>\n                    <xsl:text>  },&#xa;</xsl:text>\n                    <xsl:text>  plugins: [ RevealMath.MathJax4 ]&#xa;</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n            <xsl:text>});&#xa;</xsl:text>\n        </script>\n    </html>\n</xsl:template>\n\n<!-- reveal.js natively places content at the middle of a slide -->\n<!-- when centering (a \"middle\" default) and at the top         -->\n<!-- otherwise.  Any other placement gets a class tied to the   -->\n<!-- style rules above.                                         -->\n<xsl:template name=\"valign-class\">\n    <xsl:param name=\"valign\"/>\n    <xsl:variable name=\"native\">\n        <xsl:choose>\n            <xsl:when test=\"$slides-valign-default = 'middle'\">\n                <xsl:text>middle</xsl:text>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>top</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:if test=\"not($valign = $native)\">\n        <xsl:attribute name=\"class\">\n            <xsl:text>valign-</xsl:text>\n            <xsl:value-of select=\"$valign\"/>\n        </xsl:attribute>\n    </xsl:if>\n</xsl:template>\n\n<!-- A \"section\" contains multiple \"slide\", which we process,   -->\n<!-- but first we make a special slide announcing the \"section\" -->\n<!-- With reveal.js navigationMode set to \"default\" or \"grid\"   -->\n<!-- we organize title slides as the \"horizontal\" (or major)    -->\n<!-- slides, with the slides within a section as the \"vertical\" -->\n<!-- (or minor) slides.  But if the navigationMode is \"linear\"  -->\n<!-- we do not even create this two-deep organization at all,   -->\n<!-- in part because we think the linear mode is buggy for      -->\n<!-- the last vertical set.                                     -->\n<xsl:template match=\"section\">\n    <xsl:choose>\n        <xsl:when test=\"($reveal-navigation-mode = 'default') or ($reveal-navigation-mode = 'grid')\">\n            <section>\n                <section>\n                    <xsl:call-template name=\"valign-class\">\n                        <xsl:with-param name=\"valign\" select=\"$slides-valign-default\"/>\n                    </xsl:call-template>\n                    <h2>\n                        <xsl:apply-templates select=\".\" mode=\"title-full\"/>\n                    </h2>\n                </section>\n                <xsl:apply-templates select=\"slide\"/>\n            </section>\n        </xsl:when>\n        <xsl:when test=\"$reveal-navigation-mode = 'linear'\">\n            <section>\n                <xsl:call-template name=\"valign-class\">\n                    <xsl:with-param name=\"valign\" select=\"$slides-valign-default\"/>\n                </xsl:call-template>\n                <h2>\n                    <xsl:apply-templates select=\".\" mode=\"title-full\"/>\n                </h2>\n            </section>\n            <xsl:apply-templates select=\"slide\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:BUG: a reveal.js navigation mode (\"<xsl:value-of select=\"$reveal-navigation-mode\"/>\") is implemented but the section construction is not prepared for that mode</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"frontmatter\">\n    <section>\n      <section>\n        <xsl:call-template name=\"valign-class\">\n            <xsl:with-param name=\"valign\" select=\"$slides-valign-default\"/>\n        </xsl:call-template>\n        <!-- we assume an overall title exists -->\n        <h1>\n            <xsl:apply-templates select=\"$root/slideshow\" mode=\"title-full\" />\n        </h1>\n        <!-- subtitle would be optional, subsidary -->\n        <xsl:if test=\"$root/slideshow/subtitle\">\n            <h2>\n                <xsl:apply-templates select=\"$root/slideshow\" mode=\"subtitle\" />\n            </h2>\n        </xsl:if>\n        <!-- we assume at least one author, these are in a table -->\n        <xsl:apply-templates select=\"titlepage\" mode=\"author-list\"/>\n        <!-- optional \"event\" -->\n        <xsl:if test=\"bibinfo/event\">\n            <h3>\n                <xsl:apply-templates select=\"bibinfo/event\"/>\n            </h3>\n        </xsl:if>\n        <!-- optional \"date\" -->\n        <xsl:if test=\"bibinfo/date\">\n            <h3>\n                <xsl:apply-templates select=\"bibinfo/date\"/>\n            </h3>\n        </xsl:if>\n    </section>\n    <xsl:apply-templates select=\"abstract\"/>\n  </section>\n</xsl:template>\n\n<xsl:template match=\"titlepage\" mode=\"author-list\">\n  <table>\n  <tr>\n  <xsl:for-each select=\"$bibinfo/author\">\n    <th align=\"center\" style=\"border-bottom: 0px;\"><xsl:value-of select=\"personname\"/></th>\n  </xsl:for-each>\n</tr>\n  <tr>\n  <xsl:for-each select=\"$bibinfo/author\">\n    <td align=\"center\" style=\"border-bottom: 0px;\"><xsl:value-of select=\"affiliation|institution\"/></td>\n  </xsl:for-each>\n</tr>\n<tr>\n  <xsl:for-each select=\"$bibinfo/author\">\n    <td align=\"center\"><xsl:apply-templates select=\"logo\" /></td>\n  </xsl:for-each>\n  </tr>\n</table>\n</xsl:template>\n\n<xsl:template match=\"abstract\">\n    <section>\n          <xsl:call-template name=\"valign-class\">\n              <xsl:with-param name=\"valign\" select=\"$slides-valign-default\"/>\n          </xsl:call-template>\n          <h2>Abstract</h2>\n          <div align=\"left\">\n              <xsl:apply-templates select=\"*\"/>\n          </div>\n    </section>\n</xsl:template>\n\n<xsl:template match=\"slide\">\n    <section>\n          <xsl:call-template name=\"valign-class\">\n              <xsl:with-param name=\"valign\">\n                  <xsl:apply-templates select=\".\" mode=\"valign\"/>\n              </xsl:with-param>\n          </xsl:call-template>\n          <xsl:variable name=\"slide-hN\">\n              <xsl:apply-templates select=\".\" mode=\"hN\">\n                  <xsl:with-param name=\"heading-level\" select=\"$reveal-slide-heading-level\"/>\n              </xsl:apply-templates>\n          </xsl:variable>\n          <xsl:element name=\"{$slide-hN}\">\n              <xsl:apply-templates select=\".\" mode=\"title-full\" />\n          </xsl:element>\n          <div align=\"left\">\n              <!-- Single monolithic page: heading levels are threaded, not -->\n              <!-- chunked.  The slide title is one level below a \"section\" -->\n              <!-- (when present); slide content is one level below that.   -->\n              <xsl:apply-templates select=\"*\">\n                  <xsl:with-param name=\"heading-level\" select=\"$reveal-slide-heading-level + 1\"/>\n              </xsl:apply-templates>\n          </div>\n      </section>\n</xsl:template>\n\n<xsl:template match=\"subslide\">\n  <div class=\"fragment\">\n    <xsl:apply-templates select=\"*\"/>\n  </div>\n</xsl:template>\n\n<xsl:template match=\"ul/li|ol/li\">\n  <li>\n    <xsl:if test=\"parent::*/@pause = 'yes'\">\n      <xsl:attribute name=\"class\">\n        <xsl:text>fragment</xsl:text>\n      </xsl:attribute>\n    </xsl:if>\n    <!-- content may be structured, or not -->\n    <xsl:if test=\"title\">\n        <h6 class=\"heading\">\n            <span class=\"title\">\n                <xsl:apply-templates select=\".\" mode=\"title-xref\"/>\n            </span>\n        </h6>\n    </xsl:if>\n    <xsl:apply-templates/>\n  </li>\n</xsl:template>\n\n<!-- We group dt/dd pairs in a div so that fragments work properly -->\n<!-- Yes, this seems to be legitimate HTML structure               -->\n<!-- https://www.stefanjudis.com/today-i-learned/                  -->\n<!-- divs-are-valid-elements-inside-of-a-definition-list/          -->\n<xsl:template match=\"dl/li\">\n  <div>\n    <xsl:if test=\"parent::*/@pause = 'yes'\">\n      <xsl:attribute name=\"class\">\n        <xsl:text>fragment</xsl:text>\n      </xsl:attribute>\n    </xsl:if>\n    <dt>\n      <xsl:apply-templates select=\".\" mode=\"title-full\"/>\n    </dt>\n    <dd>\n      <!-- assumes content part is structured -->\n      <!-- title gets killed on-sight         -->\n      <xsl:apply-templates select=\"*\"/>\n    </dd>\n  </div>\n</xsl:template>\n\n<xsl:template match=\"p\">\n  <p>\n    <xsl:if test=\"@pause = 'yes'\">\n      <xsl:attribute name=\"class\">\n        <xsl:text>fragment</xsl:text>\n      </xsl:attribute>\n    </xsl:if>\n    <xsl:apply-templates/>\n  </p>\n</xsl:template>\n\n<!-- Images get wrapped in a div with @class=\"fragment\" if they are  -->\n<!-- paused                                                          -->\n<xsl:template match=\"image[not(ancestor::sidebyside) and (@pause='yes')]\">\n    <div class=\"fragment\">\n      <xsl:apply-imports/>\n    </div>\n</xsl:template>\n\n<!-- Side-By-Side -->\n<!-- Same container-declared composition as HTML and LaTeX,        -->\n<!-- realized here with CSS table display: margins are declared on -->\n<!-- the wrapper div, and each panel div carries its width and     -->\n<!-- vertical alignment.  Built by implementing the two abstract   -->\n<!-- templates (\"panel-panel\", \"compose-panels\") of the -common    -->\n<!-- machinery.                                                    -->\n\n<!-- Overall wrapper of a sidebyside  -->\n<xsl:template match=\"sidebyside\" mode=\"compose-panels\">\n    <xsl:param name=\"layout\" />\n    <xsl:param name=\"panels\" />\n\n    <xsl:variable name=\"left-margin\"  select=\"$layout/left-margin\" />\n    <xsl:variable name=\"right-margin\" select=\"$layout/right-margin\" />\n\n    <div style=\"display: table;\">\n       <xsl:attribute name=\"class\">\n            <xsl:text>sidebyside</xsl:text>\n       </xsl:attribute>\n       <xsl:attribute name=\"style\">\n            <xsl:text>display:table;</xsl:text>\n            <xsl:text>margin-left:</xsl:text>\n            <xsl:value-of select=\"$left-margin\" />\n            <xsl:text>;</xsl:text>\n            <xsl:text>margin-right:</xsl:text>\n            <xsl:value-of select=\"$right-margin\" />\n            <xsl:text>;</xsl:text>\n        </xsl:attribute>\n        <xsl:copy-of select=\"$panels\" />\n    </div>\n</xsl:template>\n\n<!-- A single panel of the sidebyside -->\n<xsl:template match=\"*\" mode=\"panel-panel\">\n    <xsl:param name=\"width\" />\n    <xsl:param name=\"left-margin\" />\n    <xsl:param name=\"right-margin\" />\n    <xsl:param name=\"valign\" />\n\n    <xsl:element name=\"div\">\n        <xsl:if test=\"parent::sidebyside/@pause = 'yes'\">\n          <xsl:attribute name=\"class\">\n            <xsl:text>fragment</xsl:text>\n          </xsl:attribute>\n        </xsl:if>\n        <xsl:attribute name=\"style\">\n            <xsl:text>display:table-cell;</xsl:text>\n            <xsl:text>width:</xsl:text>\n            <xsl:call-template name=\"relative-width\">\n                <xsl:with-param name=\"width\" select=\"$width\" />\n                <xsl:with-param name=\"left-margin\"  select=\"$left-margin\" />\n                <xsl:with-param name=\"right-margin\" select=\"$right-margin\" />\n            </xsl:call-template>\n            <xsl:text>;</xsl:text>\n            <!-- top, middle, bottom -->\n            <xsl:text>vertical-align:</xsl:text>\n            <xsl:value-of select=\"$valign\"/>\n            <xsl:text>;</xsl:text>\n        </xsl:attribute>\n        <!-- Realize each panel's object -->\n        <xsl:apply-templates select=\".\">\n            <xsl:with-param name=\"width\" select=\"$width\" />\n        </xsl:apply-templates>\n    </xsl:element>\n</xsl:template>\n\n<!-- The content of a cross-reference is computed by the -common  -->\n<!-- machinery; on a slide we do not make it a live link, since   -->\n<!-- the likely target is a nearby slide and knowls do not exist. -->\n<xsl:template match=\"*\" mode=\"xref-link\">\n    <xsl:param name=\"target\"/>\n    <xsl:param name=\"content\"/>\n    <xsl:param name=\"origin\"/>\n    <xsl:copy-of select=\"$content\"/>\n</xsl:template>\n\n<!-- We don't want any permalinks -->\n<xsl:template match=\"*\" mode=\"permalink\"/>\n\n<!-- ######## -->\n<!-- Bad Bank -->\n<!-- ######## -->\n\n<!-- Reveal.js specific, so best to place inside this stylesheet.  -->\n\n<!-- A couple of temporary command-line stringparam will just be    -->\n<!-- ignored as this stylesheet was first released about the time   -->\n<!-- the publisher file came into existence.                        -->\n\n<!-- 2020-02-09: Stopped using a temporary \"theme\" stringparam -->\n<xsl:param name=\"theme\" select=\"''\"/>\n<!-- 2020-02-09: Stopped using a temporary \"local\" stringparam -->\n<xsl:param name=\"local\" select=\"''\"/>\n\n<xsl:template name=\"reveal-warnings\">\n    <xsl:call-template name=\"banner-warning\">\n        <xsl:with-param name=\"warning\">Conversion to reveal.js presentations/slideshows is experimental&#xa;Requests for additional specific constructions welcome&#xa;Additional PreTeXt elements are subject to change</xsl:with-param>\n    </xsl:call-template>\n    <xsl:if test=\"not($theme = '')\">\n        <xsl:message >PTX:DEPRECATE: the temporary \"theme\" stringparam is deprecated and is being ignored by the conversion to a Reveal.js slideshow.  Please switch to using a publisher file to set this option, see documentation in The Guide.  The default theme is \"simple\".</xsl:message>\n        <xsl:text>simple</xsl:text>\n    </xsl:if>\n    <xsl:if test=\"not($local = '')\">\n        <xsl:message >PTX:DEPRECATE: the temporary \"local\" stringparam is deprecated and is being ignored.  Please switch to using a publisher file to set this option, see documentation in The Guide.  The default behavior is to get resources from a CDN.</xsl:message>\n    </xsl:if>\n</xsl:template>\n\n<!-- #################### -->\n<!-- Embedded Mathematics -->\n<!-- #################### -->\n\n<!-- Online mathematics (the default) is authored LaTeX passed      -->\n<!-- through, inherited from the HTML conversion, for the math      -->\n<!-- plugin and MathJax to typeset in the browser.  Embedded        -->\n<!-- mathematics substitutes an SVG image and a speech string,      -->\n<!-- both manufactured at build time, so the slideshow performs no  -->\n<!-- typesetting at all: the same device as the EPUB conversion,    -->\n<!-- whose templates these mirror.  Every \"md\" has \"mrow\" children  -->\n<!-- once the assembly repairs an authored one-line \"md\", so the    -->\n<!-- match covers all mathematics.  Slides never link to an         -->\n<!-- equation (a cross-reference renders as its text), so no HTML   -->\n<!-- id is placed, unlike EPUB.                                     -->\n<xsl:template match=\"m|md[mrow]\">\n    <xsl:choose>\n        <xsl:when test=\"$b-reveal-embedded-math\">\n            <!-- NB: math-representation file writes with \"unique-id\" -->\n            <xsl:variable name=\"id\">\n                <xsl:apply-templates select=\".\" mode=\"unique-id\"/>\n            </xsl:variable>\n            <xsl:variable name=\"math\" select=\"$math-repr/pi:math[@id = $id]\"/>\n            <xsl:variable name=\"speech\" select=\"$speech-repr/pi:math[@id = $id]\"/>\n            <span>\n                <xsl:attribute name=\"class\">\n                    <xsl:choose>\n                        <xsl:when test=\"$math/@context = 'inline'\">\n                            <xsl:text>mjpage</xsl:text>\n                        </xsl:when>\n                        <xsl:when test=\"$math/@context = 'displaymath'\">\n                            <xsl:text>mjpage mjpage__block</xsl:text>\n                        </xsl:when>\n                    </xsl:choose>\n                </xsl:attribute>\n                <xsl:apply-templates select=\"$math/div[@class = 'svg']/svg:svg\" mode=\"svg-edit\">\n                    <xsl:with-param name=\"speech\" select=\"$speech\"/>\n                    <xsl:with-param name=\"base-id\" select=\"$id\"/>\n                </xsl:apply-templates>\n            </span>\n        </xsl:when>\n        <!-- online: the usual LaTeX-within-delimiters construction -->\n        <xsl:otherwise>\n            <xsl:apply-imports/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- An annotated PreFigure diagram is normally embedded for the    -->\n<!-- diagcess library: an interactive, keyboard-driven exploration  -->\n<!-- for a screen reader.  With embedded mathematics the slideshow  -->\n<!-- has already traded such interactivity for fixed alternatives,  -->\n<!-- so the diagram becomes a static image (its plain SVG), and the -->\n<!-- diagcess machinery is omitted entirely.                        -->\n<xsl:template match=\"image[pf:prefigure[pf:diagram/pf:annotations]]\" mode=\"image-inclusion\">\n    <xsl:choose>\n        <xsl:when test=\"$b-reveal-embedded-math\">\n            <xsl:variable name=\"base-pathname\">\n                <xsl:value-of select=\"$generated-directory\"/>\n                <xsl:text>prefigure/</xsl:text>\n                <xsl:apply-templates select=\"pf:prefigure\" mode=\"image-source-basename\"/>\n            </xsl:variable>\n            <xsl:apply-templates select=\".\" mode=\"svg-png-wrapper\">\n                <xsl:with-param name=\"image-filename\" select=\"concat($base-pathname, '.svg')\"/>\n            </xsl:apply-templates>\n            <!-- possibly annotate with archive links -->\n            <xsl:apply-templates select=\".\" mode=\"archive\">\n                <xsl:with-param name=\"base-pathname\" select=\"$base-pathname\"/>\n            </xsl:apply-templates>\n            <!-- possibly give a long description -->\n            <xsl:apply-templates select=\".\" mode=\"description\"/>\n        </xsl:when>\n        <!-- online: the diagcess embedding, inherited -->\n        <xsl:otherwise>\n            <xsl:apply-imports/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- MathJax mints an HTML id from an equation's \\tag for its own  -->\n<!-- \\eqref linking, which PreTeXt never uses; a tag used twice    -->\n<!-- (symbols as tags invite this) would duplicate the id, so they -->\n<!-- are dropped                                                   -->\n<xsl:template match=\"@id[starts-with(., 'mjx-eqn')]\" mode=\"svg-edit\"/>\n\n<!-- Identity for the SVG stream-edit -->\n<xsl:template match=\"node()|@*\" mode=\"svg-edit\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"svg-edit\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- We enrich the main \"svg\" element with a speech string.      -->\n<!--   1.  Since this is the \"entry template\" for this mode,     -->\n<!--       this is the only place we accept the \"speech\" param.  -->\n<!--   2.  MathJax seems to use SVGs inside of SVGs for placing  -->\n<!--       numbers/tags of numbered equations, so we only enrich -->\n<!--       \"top-level\" SVG - that is the point of the filter.    -->\n<!--   3.  The id of the math element will be used as the base   -->\n<!--       of (unique) ids necessary to point to the speech.     -->\n<!--       Pattern 11 at:                                        -->\n<!--       https://www.deque.com/blog/creating-accessible-svgs/  -->\n<!--   4.  Seems                                                 -->\n<!--           \"title\" + @aria-labelledby                        -->\n<!--           \"desc\"  + @aria-describedby                       -->\n<!--       cover all the bases.  It is suggested that the two    -->\n<!--       elements alone would be recognized by screen readers. -->\n<xsl:template match=\"svg:svg[not(ancestor::svg:svg)]\" mode=\"svg-edit\">\n    <xsl:param name=\"speech\"/>\n    <xsl:param name=\"base-id\"/>\n\n    <!-- manufacture id values for consistency, uniqueness -->\n    <xsl:variable name=\"title-id\">\n        <xsl:value-of select=\"$base-id\"/>\n        <xsl:text>-title</xsl:text>\n    </xsl:variable>\n    <xsl:variable name=\"desc-id\">\n        <xsl:value-of select=\"$base-id\"/>\n        <xsl:text>-desc</xsl:text>\n    </xsl:variable>\n\n    <xsl:copy>\n        <!-- attributes first -->\n        <xsl:apply-templates select=\"@*\" mode=\"svg-edit\"/>\n        <xsl:attribute name=\"role\">\n            <xsl:text>img</xsl:text>\n        </xsl:attribute>\n        <xsl:attribute name=\"aria-labelledby\">\n            <xsl:value-of select=\"$title-id\"/>\n        </xsl:attribute>\n        <xsl:attribute name=\"aria-describedby\">\n            <xsl:value-of select=\"$desc-id\"/>\n        </xsl:attribute>\n        <!-- now additional metadata, of sorts -->\n        <xsl:element name=\"title\" namespace=\"http://www.w3.org/2000/svg\">\n            <xsl:attribute name=\"id\">\n                <xsl:value-of select=\"$title-id\"/>\n            </xsl:attribute>\n            <xsl:text>Math Expression</xsl:text>\n        </xsl:element>\n        <xsl:element name=\"desc\" namespace=\"http://www.w3.org/2000/svg\">\n            <xsl:attribute name=\"id\">\n                <xsl:value-of select=\"$desc-id\"/>\n            </xsl:attribute>\n            <xsl:value-of select=\"$speech\"/>\n        </xsl:element>\n        <!-- and all the rest of the nodes -->\n        <xsl:apply-templates select=\"node()\" mode=\"svg-edit\"/>\n    </xsl:copy>\n</xsl:template>\n\n</xsl:stylesheet>\n","pretext-runestone-fitb.xsl":"<?xml version='1.0'?> <!-- As XML file -->\n\n<!--********************************************************************\nCopyright (C) 2023-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*****************************************************************-->\n<!DOCTYPE xsl:stylesheet>\n\n<xsl:stylesheet\n    xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\"\n    xmlns:xml=\"http://www.w3.org/XML/1998/namespace\"\n    xmlns:pi=\"http://pretextbook.org/2020/pretext/internal\"\n    xmlns:exsl=\"http://exslt.org/common\"\n    xmlns:date=\"http://exslt.org/dates-and-times\"\n    xmlns:str=\"http://exslt.org/strings\"\n    extension-element-prefixes=\"pi exsl date str\"\n>\n\n<xsl:variable name=\"b-include-postContent\" select=\"true()\"/>\n\n<!-- ==================================================== -->\n<!-- Actual rules for substution when generating HTML     -->\n<!-- ==================================================== -->\n\n<!-- Convert fillin tag to an input element on the page -->\n<xsl:template match=\"exercise[@pi:exercise-interactive='fillin']//fillin\n                     | project[@pi:exercise-interactive='fillin']//fillin\n                     | activity[@pi:exercise-interactive='fillin']//fillin\n                     | exploration[@pi:exercise-interactive='fillin']//fillin\n                     | investigation[@pi:exercise-interactive='fillin']//fillin\n                     | task[@pi:exercise-interactive='fillin']//fillin\">\n    <xsl:param name=\"b-human-readable\" />\n    <xsl:variable name=\"parent-id\">\n        <xsl:apply-templates select=\"ancestor::exercise\" mode=\"html-id\" />\n    </xsl:variable>\n    <xsl:element name=\"input\">\n        <xsl:attribute name=\"type\">\n            <xsl:choose>\n                <xsl:when test=\"@mode = 'number'\">\n                    <xsl:text>number</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:text>text</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:attribute>\n        <xsl:attribute name=\"id\">\n            <xsl:value-of select=\"$parent-id\"/>\n            <xsl:text>-</xsl:text>\n            <xsl:apply-templates select=\".\" mode=\"blank-name\"/>\n        </xsl:attribute>\n        <xsl:if test=\"@name\">\n            <xsl:attribute name=\"name\"><xsl:value-of select=\"@name\"/></xsl:attribute>\n        </xsl:if>\n        <xsl:if test=\"@width\">\n            <xsl:attribute name=\"size\">\n                <xsl:value-of select=\"@width\"/>\n            </xsl:attribute>\n        </xsl:if>\n    </xsl:element>\n</xsl:template>\n\n<!-- ========================================================= -->\n<!-- The Runestone element is based on JSON scripts describing -->\n<!-- the exercise, how to set it up, and how to evaluate it.   -->\n<!-- The HTML will contain this JSON and Runestone extracts it -->\n<!-- and inserts it into the HTML page via JS.                 -->\n<!-- ========================================================= -->\n<xsl:template match=\"exercise[@pi:exercise-interactive='fillin']\n                     | project[@pi:exercise-interactive='fillin']\n                     | activity[@pi:exercise-interactive='fillin']\n                     | exploration[@pi:exercise-interactive='fillin']\n                     | investigation[@pi:exercise-interactive='fillin']\n                     | task[@pi:exercise-interactive='fillin']\" mode=\"runestone-to-interactive\">\n    <xsl:variable name=\"b-is-dynamic\" select=\"boolean(./setup)\"/>\n    <div class=\"ptx-runestone-container\">\n        <div class=\"runestone\">\n            <div data-component=\"fillintheblank\" class=\"fillintheblank\" style=\"visibility: hidden;\">\n                <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n                <script type=\"application/json\">\n                    <xsl:text>{&#xa;</xsl:text>\n                    <!-- A seed is provided to generate consistent static content -->\n                    <xsl:if test=\"setup and $b-dynamics-static-seed\">\n                        <xsl:text>\"static_seed\": \"</xsl:text>\n                        <xsl:choose>\n                            <xsl:when test=\"setup/@seed\">\n                                <xsl:value-of select=\"setup/@seed\"/>\n                            </xsl:when>\n                            <xsl:otherwise>\n                                <!-- Report if a seed is not provided-->\n                                <xsl:message>PTX:FALLBACK:   Dynamic exercise \"<xsl:apply-templates select=\".\" mode=\"unique-id\" />\" is missing setup @seed for static content generation.</xsl:message>\n                                <xsl:text>1234</xsl:text>\n                            </xsl:otherwise>\n                        </xsl:choose>\n                        <xsl:text>\",&#xa;</xsl:text>\n                    </xsl:if>\n                    <!-- The formatted HTML presentation of the problem, -->\n                    <!-- with escape codes for dynamic content, all of   -->\n                    <!-- which is serialized and escaped to a string.    -->\n                    <xsl:text>\"problemHtml\": </xsl:text>\n                    <xsl:call-template name=\"escape-quote-xml\">\n                        <xsl:with-param name=\"xml_content\">\n                            <xsl:apply-templates select=\"statement/*\" />\n                            <xsl:if test=\"$b-dynamics-static-seed\">\n                                <div>\n                                    <xsl:attribute name=\"id\">\n                                        <xsl:apply-templates select=\".\" mode=\"html-id\"/>\n                                        <xsl:text>-substitutions</xsl:text>\n                                    </xsl:attribute>\n                                    <xsl:apply-templates select=\"(statement|solution)//eval[@obj]|evaluation//feedback//eval[@obj]|statement//fillin[@ansobj]\" mode=\"track-evaluation\" />\n                                </div>\n                            </xsl:if>\n                        </xsl:with-param>\n                    </xsl:call-template>\n                    <!-- The formatted HTML presentation of the solution, -->\n                    <!-- similar to statement but no fillins              -->\n                    <xsl:text>,&#xa;\"solutionHtml\": </xsl:text>\n                    <xsl:call-template name=\"escape-quote-xml\">\n                        <xsl:with-param name=\"xml_content\">\n                            <xsl:apply-templates select=\"solution/*\" />\n                        </xsl:with-param>\n                    </xsl:call-template>\n                    <!-- Add packages that need to be loaded as javascript -->\n                    <xsl:if test=\"$b-is-dynamic\">\n                        <xsl:text>,&#xa;\"dyn_imports\": [</xsl:text>\n                        <xsl:text>\"BTM\"</xsl:text>\n                        <!-- Future: add additional packages here -->\n                        <xsl:if test=\"setup/jsimports\">\n                          <xsl:apply-templates select=\"setup/jsimports/jslibrary\" mode=\"js-import\"/>\n                        </xsl:if>\n                        <xsl:text>]</xsl:text>\n                    </xsl:if>\n                    <!-- Names assigned to the blanks.      -->\n                    <!-- Empty if none named.               -->\n                    <xsl:text>,&#xa;\"blankNames\": {</xsl:text>\n                    <xsl:for-each select=\"statement//fillin\">\n                        <xsl:if test=\"position() > 1\">\n                            <xsl:text>, </xsl:text>\n                        </xsl:if>\n                        <xsl:apply-templates select=\".\" mode=\"declare-blank\"/>\n                    </xsl:for-each>\n                    <xsl:text>}</xsl:text>\n                    <xsl:if test=\"$b-is-dynamic\">\n                        <!-- The actual setup code is javascript enclosed in quotes. -->\n                        <!-- The declaration creates the objects that are needed.    -->\n                        <!-- The script is included as an escaped string             -->\n                        <xsl:text>,&#xa;\"dyn_vars\": </xsl:text>\n                        <xsl:call-template name=\"dynamic-setup\" />\n                    </xsl:if>\n                    <!-- An array of tests and feedback for answer evaluation    -->\n                    <!-- Each blank has a corresponding array of test/feedback   -->\n                    <!-- response. The test is Javascript (stringified) that     -->\n                    <!-- returns a boolean response. The first test is for       -->\n                    <!-- correctness. The last response is default.              -->\n                    <xsl:text>,&#xa;\"feedbackArray\": [</xsl:text>\n                    <!-- In case all answers are based on one test               -->\n                    <xsl:variable name=\"multiAns\">\n                        <xsl:apply-templates select=\"evaluation\" mode=\"get-multianswer-check\"/>\n                    </xsl:variable>\n                    <!-- Verify match between fillin and evaluate -->\n                    <xsl:if test=\"count(evaluation/evaluate[not(@all='yes')]) != count(statement//fillin)\">\n                        <xsl:message>PTX:ERROR:   \"<xsl:apply-templates select=\".\" mode=\"unique-id\"/>\" has <xsl:value-of\n                            select=\"count(statement//fillin)\"/> blanks but <xsl:value-of\n                            select=\"count(evaluation/evaluate[not(@all='yes')])\"/> \"evaluate\" elements; they must correspond one-to-one.</xsl:message>\n                    </xsl:if>\n                    <!-- Generate test/feedback pair for each fillin             -->\n                    <xsl:for-each select=\"statement//fillin\">\n                        <xsl:if test=\"position() > 1\">\n                            <xsl:text>, </xsl:text>\n                        </xsl:if>\n                        <xsl:apply-templates select=\".\" mode=\"dynamic-feedback\">\n                            <xsl:with-param name=\"multiAns\" select=\"$multiAns\" />\n                        </xsl:apply-templates>\n                    </xsl:for-each>\n                    <xsl:text>]</xsl:text>\n                    <xsl:text>&#xa;}</xsl:text>\n                </script>\n            </div>\n            <xsl:text>&#xa;</xsl:text>\n        </div>\n    </div>\n</xsl:template>\n\n<!-- Find the sequential position of the fillin relative to its ancestor statement -->\n<xsl:template match=\"fillin\" mode=\"blank-number\">\n    <xsl:variable name=\"the-fillin\" select=\".\"/>\n    <xsl:for-each select=\"ancestor::statement[1]//fillin\">\n        <xsl:if test=\"generate-id() = generate-id($the-fillin)\">\n            <xsl:value-of select=\"position()\"/>\n        </xsl:if>\n    </xsl:for-each>\n</xsl:template>\n\n<!-- Fillins can be provided a name or use a default rule -->\n<xsl:template match=\"fillin\" mode=\"blank-name\">\n    <xsl:choose>\n        <xsl:when test=\"@name\">\n            <xsl:value-of select=\"@name\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>blank</xsl:text>\n            <xsl:apply-templates select=\".\" mode=\"blank-number\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Creating a list of blank names. -->\n<xsl:template match=\"fillin\" mode=\"declare-blank\">\n    <xsl:if test=\"not(@mode)\">\n        <xsl:message>PTX:FALLBACK:   a \"fillin\" of interactive exercise \"<xsl:apply-templates\n            select=\"ancestor::statement[1]/parent::*\" mode=\"unique-id\"/>\" has no @mode, so \"string\" will be used.  A response is then compared as plain text, and an @ansobj answer is rendered with its \"toString\" and not as mathematics.  Set @mode to \"math\", \"number\", or \"string\" to say which is wanted.</xsl:message>\n    </xsl:if>\n    <xsl:variable name=\"blankNum\">\n        <xsl:apply-templates select=\".\" mode=\"blank-number\" />\n    </xsl:variable>\n    <xsl:call-template name=\"quote-string\">\n        <xsl:with-param name=\"text\">\n            <xsl:apply-templates select=\".\" mode=\"blank-name\"/>\n        </xsl:with-param>\n    </xsl:call-template>\n    <xsl:text>: </xsl:text>\n    <xsl:value-of select=\"number($blankNum) - 1\"/>\n</xsl:template>\n\n<!-- Identify external javascript libraries, either as asset or by url -->\n<xsl:template match=\"jslibrary\" mode=\"js-import-path\">\n    <xsl:choose>\n        <xsl:when test=\"@source\">\n            <xsl:value-of select=\"$external-directory\"/>\n            <xsl:value-of select=\"@source\"/>\n        </xsl:when>\n        <xsl:when test=\"@url\">\n            <xsl:value-of select=\"@url\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message>PTX:WARNING: a \"jslibrary\" element needs either a @source (project-local) or a @url (remote) attribute, and this one has neither, so it will be ignored.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- A \"jslibrary\" as an entry of the HTML \"dyn_imports\" array.  The -->\n<!-- array always leads with \"BTM\", so every entry here is preceded  -->\n<!-- by a comma.                                                     -->\n<xsl:template match=\"jslibrary\" mode=\"js-import\">\n    <xsl:variable name=\"import-path\">\n        <xsl:apply-templates select=\".\" mode=\"js-import-path\"/>\n    </xsl:variable>\n    <xsl:if test=\"string-length($import-path) > 0\">\n        <xsl:text>, </xsl:text>\n        <xsl:call-template name=\"escape-quote-string\">\n            <xsl:with-param name=\"text\" select=\"$import-path\"/>\n        </xsl:call-template>\n    </xsl:if>\n</xsl:template>\n\n<!-- #eval in a dynamic exercise (has setup) is to evaluate -->\n<!-- an expression that has been previously generated. If   -->\n<!-- in math-mode, we want to see if it is an object that   -->\n<!-- knows how to formulate a LaTeX representation          -->\n<!-- The `toTeX` javascript function is defined in BTM.js   -->\n<!-- which is loaded by Runestone.                          -->\n<xsl:template match=\"eval[@obj]\">\n    <xsl:text>[%= </xsl:text>\n    <xsl:choose>\n        <xsl:when test=\"ancestor::m|ancestor::md|ancestor::mrow\">\n            <xsl:text>toTeX(</xsl:text>\n            <xsl:value-of select=\"@obj\"/>\n            <xsl:text>)</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"@obj\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n    <xsl:text> %]</xsl:text>\n</xsl:template>\n\n<!-- Part of static output content extraction process,   -->\n<!-- this creates elements that will be pulled from the  -->\n<!-- stand-alone page into a generated XML document that -->\n<!-- gives the actual substitution in static mode.       -->\n<xsl:template match=\"eval[@obj]\" mode=\"track-evaluation\">\n    <eval-subst>\n        <xsl:attribute name=\"obj\">\n            <xsl:value-of select=\"@obj\"/>\n        </xsl:attribute>\n        <xsl:apply-templates select=\".\"/>\n    </eval-subst>\n</xsl:template>\n\n<xsl:template match=\"fillin[@ansobj]\" mode=\"track-evaluation\">\n    <eval-subst>\n        <xsl:attribute name=\"obj\">\n            <xsl:value-of select=\"@ansobj\"/>\n        </xsl:attribute>\n        <xsl:variable name=\"temp-eval\">\n            <xsl:choose>\n                <xsl:when test=\"@mode='math' or @mode='number'\">\n                    <m><eval>\n                        <xsl:attribute name=\"obj\">\n                            <xsl:value-of select=\"@ansobj\"/>\n                        </xsl:attribute>\n                    </eval></m>\n                </xsl:when>\n                <xsl:otherwise>\n                    <eval>\n                        <xsl:attribute name=\"obj\">\n                            <xsl:value-of select=\"@ansobj\"/>\n                        </xsl:attribute>\n                    </eval>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:variable>\n        <xsl:apply-templates select=\"exsl:node-set($temp-eval)//eval\"/>\n    </eval-subst>\n</xsl:template>\n\n\n<!-- Create the dynamic aspect of the problem.           -->\n<!-- Define all of the mathematical elements as well as  -->\n<!-- objects (e.g. graphs) that might depend on them     -->\n<!-- A script in setup/setupScript is executed after     -->\n<!-- object-based setup concludes.                       -->\n<!-- A script in setup/postRenderScript is executed      -->\n<!-- after the dynamic creation is complete.             -->\n<xsl:template name=\"dynamic-setup\">\n    <xsl:variable name=\"js_code\">\n        <!-- Initialize the evaluation environment -->\n        <xsl:call-template name=\"setup-evaluation-environment\"/>\n        <!-- Any direct JS for environment setup   -->\n        <xsl:if test=\"setup/setupScript\">\n            <xsl:value-of select=\"setup/setupScript\"/>\n        </xsl:if>\n        <!-- Prepare evaluation and feedback       -->\n        <xsl:call-template name=\"setup-fillin-parsers\"/>\n        <!-- Create the call-back for post-render tasks -->\n        <xsl:if test=\"$b-include-postContent\">\n            <xsl:call-template name=\"setup-postContent\"/>\n        </xsl:if>\n    </xsl:variable>\n    <xsl:call-template name=\"escape-quote-string\">\n        <xsl:with-param name=\"text\" select=\"$js_code\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- Parse any settings for the math environment for the problem -->\n<xsl:template name=\"setup-evaluation-environment\">\n    <xsl:text>v._mobjs = new BTM({</xsl:text>\n        <!-- Setup seeded random number generator  -->\n        <xsl:text>'rand': rand</xsl:text>\n        <!-- FUTURE: Pull additional settings from an environment element -->\n        <xsl:apply-templates select=\"de-environment\" mode=\"runestone-setup\"/>\n    <xsl:text>});&#xa;</xsl:text>\n    <xsl:text>var RNG = v._mobjs.menv.rng;&#xa;</xsl:text>\n    <!-- Option to define v._config for any data purposes -->\n    <xsl:if test=\"setup/config-json\">\n        <xsl:text>const _config = v._config = JSON.parse(\"</xsl:text>\n        <xsl:call-template name=\"escape-json-string\">\n            <xsl:with-param name=\"text\">\n                <xsl:value-of select=\"setup/config-json\"/>\n            </xsl:with-param>\n        </xsl:call-template>\n        <xsl:text>\");&#xa;</xsl:text>\n    </xsl:if>\n    <!-- Generate all of the XML-declared math objects -->\n    <xsl:apply-templates select=\"setup/de-object\" mode=\"runestone-setup\"/>\n</xsl:template>\n\n<!-- Environment Setup: Define the mathematical objects -->\n<xsl:template match=\"de-object\" mode=\"runestone-setup\">\n    <xsl:text>v.</xsl:text><xsl:value-of select=\"@name\"/>\n    <xsl:text> = v._mobjs.addMathObject(</xsl:text>\n    <xsl:call-template name=\"quote-string\">\n        <xsl:with-param name=\"text\" select=\"@name\"/>\n    </xsl:call-template>\n    <xsl:text>, </xsl:text>\n    <!-- Get the context of the object here -->\n    <xsl:call-template name=\"quote-string\">\n        <xsl:with-param name=\"text\">\n            <xsl:choose>\n                <!-- Usually use value of @context but in case strings change. -->\n                <xsl:when test=\"@context='interval' or @context='set'\">\n                    <xsl:text>set</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:value-of select=\"@context\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:with-param>\n    </xsl:call-template>\n    <xsl:text>, </xsl:text>\n    <xsl:apply-templates select=\"*\" mode=\"evaluate\">\n        <xsl:with-param name=\"setupMode\"><xsl:text>1</xsl:text></xsl:with-param>\n    </xsl:apply-templates>\n    <xsl:text>);&#xa;</xsl:text>\n</xsl:template>\n\n<!-- Runestone requires declaring an array of answer-types for  -->\n<!-- validating and parsing what the user enters as a response. -->\n<xsl:template name=\"setup-fillin-parsers\">\n    <xsl:text>v.types = [</xsl:text>\n    <xsl:for-each select=\"statement//fillin\">\n        <xsl:if test=\"position() > 1\">\n            <xsl:text>, </xsl:text>\n        </xsl:if>\n        <xsl:apply-templates select=\".\" mode=\"setup-parsers\"/>\n    </xsl:for-each>\n    <xsl:text>];&#xa;</xsl:text>\n</xsl:template>\n\n<!-- Each fillin defines a blank. Establish the list of parsers. -->\n<!-- During setup and called while creating dyn_vars.            -->\n<xsl:template match=\"fillin\" mode=\"setup-parsers\">\n     <xsl:choose>\n        <xsl:when test=\"@parser\">\n          <xsl:value-of select=\"@parser\"/>\n        </xsl:when>\n        <xsl:when test=\"@mode='math'\">\n            <xsl:text>v._mobjs.getParser()</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"@mode='number'\">\n            <xsl:text>Number</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>function(val){ return val; }</xsl:text>\n        </xsl:otherwise>\n     </xsl:choose>\n</xsl:template>\n\n<!-- Create a call-back for what occurs post-rendering.  -->\n<!-- This includes automated tasks as well as any script -->\n<!-- commands in setup/postRenderScript                  -->\n<xsl:template name=\"setup-postContent\">\n    <xsl:text>v.afterContentRender = function() {&#xa;</xsl:text>\n        <xsl:if test=\"setup/postRenderScript\">\n            <xsl:value-of select=\"setup/postRenderScript\"/>\n        </xsl:if>\n    <xsl:text>};&#xa;</xsl:text>\n</xsl:template>\n\n\n<!-- ========================================================== -->\n<!-- Evaluation and Feedback                                    -->\n<!-- ========================================================== -->\n\n<!-- Default localized feedback strings. -->\n<xsl:template match=\"*\" mode=\"get-default-feedback\">\n    <xsl:param name=\"b-correct\" select=\"'no'\"/>\n    <xsl:choose>\n        <xsl:when test=\"$b-correct='yes'\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'correct'\"/>\n            </xsl:apply-templates>\n            <xsl:text>!</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'incorrect'\"/>\n            </xsl:apply-templates>\n            <xsl:text>.</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Deal with possibility of global checker for all blanks -->\n<xsl:template match=\"evaluation\" mode=\"get-multianswer-check\">\n    <xsl:variable name=\"responseTree\" select=\"../statement//fillin\" />\n    <xsl:if test=\"count($responseTree) > 1 and evaluate[@all='yes']/test\">\n        <xsl:apply-templates select=\"evaluate[@all='yes']/test\" mode=\"create-test-feedback\">\n            <xsl:with-param name=\"b-correct\" select=\"'yes'\"/>\n            <xsl:with-param name=\"fillin\" select=\"$responseTree\"/>\n        </xsl:apply-templates>\n    </xsl:if>\n</xsl:template>\n\n<!-- Build feedback based on the #evaluate element. -->\n<xsl:template match=\"evaluate\" mode=\"dynamic-feedback\">\n    <xsl:param name=\"multiAns\"/>\n    <xsl:param name=\"match-fillin\"/>\n\n    <!-- Catching name mismatch is detected by the caller. See \"fillin\"/\"dynamic-feedback\".                                  -->\n\n    <!-- First check is for correctness. -->\n    <xsl:text>[</xsl:text>\n    <xsl:choose>\n        <xsl:when test=\"string-length($multiAns) > 0\">\n            <xsl:value-of select=\"$multiAns\"/>\n        </xsl:when>\n        <xsl:when test=\"test[@correct='yes']\">\n            <xsl:apply-templates select=\"test[@correct='yes']\" mode=\"create-test-feedback\">\n                <xsl:with-param name=\"fillin\" select=\"$match-fillin\" />\n                <xsl:with-param name=\"b-correct\" select=\"'yes'\" />\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- If no explicit test is provided, use given answer. -->\n        <!-- NB: The @answer cases (mode='number' and mode='string') are now   -->\n        <!-- handled upstream in pretext-assembly.xsl (exercise pass), which   -->\n        <!-- injects a synthesized <test correct=\"yes\"> element.               -->\n        <!-- The remaining cases are for fillins that use @ansobj that         -->\n        <!-- reference an object that was dynamically created (random).        -->\n        <xsl:otherwise>\n            <xsl:text>{</xsl:text>\n            <xsl:choose>\n                <xsl:when test=\"$match-fillin/@ansobj\">\n                    <xsl:choose>\n                        <!-- Number objects — assume match with very tight tolerance -->\n                        <xsl:when test=\"$match-fillin/@mode='number'\">\n                            <xsl:text>function() {&#xa;</xsl:text>\n                            <xsl:text>    return (Math.abs(</xsl:text>\n                            <xsl:value-of select=\"$match-fillin/@ansobj\"/>\n                            <xsl:text>- ans) &lt; 1e-10);&#xa;}</xsl:text>\n                        </xsl:when>\n                        <!-- String objects — assume require exact string match -->\n                        <!-- otherwise the author should specify the test -->\n                        <xsl:when test=\"$match-fillin/@mode='string'\">\n                            <xsl:text>function() {&#xa;</xsl:text>\n                            <xsl:text>    return (</xsl:text>\n                            <xsl:value-of select=\"$match-fillin/@ansobj\"/>\n                            <xsl:text>== ans);&#xa;}</xsl:text>\n                        </xsl:when>\n                        <!-- Dynamic math objects: compare expressions -->\n                        <xsl:when test=\"$match-fillin/@mode='math'\">\n                            <xsl:text>function() {&#xa;</xsl:text>\n                            <xsl:text>    return _mobjs.compareExpressions(</xsl:text>\n                            <xsl:value-of select=\"$match-fillin/@ansobj\"/>\n                            <xsl:text>, ans</xsl:text>\n                            <xsl:text>);&#xa;}</xsl:text>\n                        </xsl:when>\n                        <xsl:otherwise>\n                            <xsl:message>PTX:ERROR: fillin has an @ansobj with invalid or missing mode (valid: number|string|math) in \"<xsl:apply-templates select=\".\" mode=\"unique-id\" />\".</xsl:message>\n                        </xsl:otherwise>\n                    </xsl:choose>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:ERROR: No method provided to identify a correct answer for #fillin in \"<xsl:apply-templates select=\".\" mode=\"unique-id\" />\".</xsl:message>\n                </xsl:otherwise>\n            </xsl:choose>\n            <xsl:text>, \"feedback\": \"</xsl:text>\n            <xsl:apply-templates select=\".\" mode=\"get-default-feedback\">\n                <xsl:with-param name=\"b-correct\" select=\"'yes'\"/>\n            </xsl:apply-templates>\n            <xsl:text>\"}</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n\n    <!-- Now add additional checks for feedback. -->\n    <xsl:for-each select=\"test[not(@correct='yes')]\">\n        <xsl:text>, </xsl:text>\n        <xsl:apply-templates select=\".\" mode=\"create-test-feedback\">\n            <xsl:with-param name=\"fillin\" select=\"$match-fillin\"/>\n        </xsl:apply-templates>\n    </xsl:for-each>\n    <!-- Default feedback for the blank. Always evaluates true.   -->\n    <xsl:text>, {\"feedback\": \"</xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"get-default-feedback\">\n        <xsl:with-param name=\"b-correct\" select=\"'no'\"/>\n    </xsl:apply-templates>\n    <xsl:text>\"}]</xsl:text>\n</xsl:template>\n\n<!-- Template for answer checking. Actual work done by specialized templates. -->\n<xsl:template match=\"fillin\" mode=\"dynamic-feedback\">\n    <xsl:param name=\"multiAns\"/>\n\n    <xsl:variable name=\"fillinName\">\n        <xsl:apply-templates select=\".\" mode=\"blank-name\"/>\n    </xsl:variable>\n    <xsl:variable name=\"blankNum\">\n        <xsl:apply-templates select=\".\" mode=\"blank-number\"/>\n    </xsl:variable>\n\n    <!-- The multi-answer checker applies to the exercise as a whole, so   -->\n    <!-- it is excluded from the numbering.  Every other \"evaluate\" holds  -->\n    <!-- a slot, named or not: the pairing with blanks is one-to-one.      -->\n    <xsl:variable name=\"the-evaluation\" select=\"ancestor::statement[1]/../evaluation\"/>\n    <xsl:variable name=\"ordered-evaluates\" select=\"$the-evaluation/evaluate[not(@all='yes')]\"/>\n\n    <!-- Pair by name when possible, else by position. -->\n    <xsl:variable name=\"named-match\" select=\"$the-evaluation/evaluate[@name = $fillinName]\"/>\n    <xsl:variable name=\"ordered-match\"\n                  select=\"$ordered-evaluates[position() = number($blankNum)]\"/>\n    <xsl:variable name=\"the-evaluate\"\n                  select=\"$named-match | $ordered-match[count($named-match) = 0]\"/>\n\n    <!-- The two error branches below still emit a well-formed array, so   -->\n    <!-- that one authoring mistake costs the exercise its feedback and    -->\n    <!-- not its JSON.  The caller has already written the separator that  -->\n    <!-- precedes this blank; emitting nothing here would leave \", ,\" and  -->\n    <!-- the whole script would fail to parse.                             -->\n    <xsl:choose>\n        <!-- Author reused one @name on several \"evaluate\" elements. -->\n        <xsl:when test=\"count($the-evaluate) > 1\">\n            <xsl:message>PTX:ERROR:   several \"evaluate\" share the name \"<xsl:value-of\n                select=\"$fillinName\"/>\" in \"<xsl:apply-templates select=\".\" mode=\"unique-id\"/>\".</xsl:message>\n            <xsl:text>[{\"feedback\": \"[Error: Several evaluate elements share this blank's name]\"}]</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$the-evaluate\">\n            <!-- Only reachable on the positional path: a name match makes   -->\n            <!-- @name and $fillinName equal by construction.                -->\n            <!--                                                             -->\n            <!-- @name on an \"evaluate\" exists to pair it with a \"fillin\" of -->\n            <!-- the same name, so a positional match whose names disagree   -->\n            <!-- is reported here.                                           -->\n            <xsl:if test=\"$the-evaluate/@name and not($the-evaluate/@name = $fillinName)\">\n                <xsl:choose>\n                    <!-- Names don't agree    -->\n                    <xsl:when test=\"@name\">\n                        <xsl:message>PTX:ERROR:   blank named \"<xsl:value-of select=\"@name\"/>\" of \"<xsl:apply-templates\n                            select=\".\" mode=\"unique-id\"/>\" was matched by position to an \"evaluate\" named \"<xsl:value-of\n                            select=\"$the-evaluate/@name\"/>\".  The names must agree, or the blank must be left unnamed.</xsl:message>\n                    </xsl:when>\n                    <!-- Name present for evaluate but not fillin -->\n                    <xsl:otherwise>\n                        <xsl:message>PTX:WARNING: the \"evaluate\" named \"<xsl:value-of select=\"$the-evaluate/@name\"/>\" in \"<xsl:apply-templates\n                            select=\".\" mode=\"unique-id\"/>\" was matched to blank <xsl:value-of select=\"$blankNum\"/> by position,\n                            because that blank has no @name.  A name on an \"evaluate\" is only used to pair it with a \"fillin\"\n                            carrying the same name; give the blank @name=\"<xsl:value-of select=\"$the-evaluate/@name\"/>\" to make\n                            the pairing explicit, or drop the name from the \"evaluate\".</xsl:message>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:if>\n            <xsl:apply-templates select=\"$the-evaluate\" mode=\"dynamic-feedback\">\n                <xsl:with-param name=\"multiAns\" select=\"$multiAns\"/>\n                <xsl:with-param name=\"match-fillin\" select=\".\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message>PTX:ERROR: No matching #evaluate for #fillin in \"<xsl:apply-templates\n                select=\".\" mode=\"unique-id\"/>\".</xsl:message>\n            <xsl:text>[{\"feedback\": \"[Error: No evaluate to match this blank]\"}]</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"test\" mode=\"create-test-feedback\">\n    <xsl:param name=\"fillin\"/>\n    <xsl:param name=\"b-correct\" select=\"'no'\"/>\n    <xsl:variable name=\"feedback-rtf\">\n        <xsl:apply-templates select=\"feedback\"/>\n    </xsl:variable>\n    <xsl:text>{</xsl:text>\n    <xsl:apply-templates select=\".\" mode=\"create-test\">\n        <xsl:with-param name=\"fillin\" select=\"$fillin\" />\n    </xsl:apply-templates>\n    <xsl:text>, \"feedback\": \"</xsl:text>\n    <xsl:choose>\n        <xsl:when test=\"feedback\">\n            <!-- serialize HTML as text, then escape as JSON -->\n            <xsl:call-template name=\"escape-json-string\">\n                <xsl:with-param name=\"text\">\n                    <xsl:apply-templates select=\"exsl:node-set($feedback-rtf)\" mode=\"xml-to-string\"/>\n                </xsl:with-param>\n            </xsl:call-template>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\".\" mode=\"get-default-feedback\">\n                <xsl:with-param name=\"b-correct\" select=\"$b-correct\"/>\n            </xsl:apply-templates>\n        </xsl:otherwise>\n    </xsl:choose>\n<xsl:text>\"}</xsl:text>\n</xsl:template>\n\n<!-- Template for simple answer checkers: no interaction between different fillins. -->\n<!-- Add a post-filter to deal with additional feedback, similar to AnswerHints but allowing more complex logic. -->\n<!-- JSON dictionary for numerical condition -->\n<xsl:template match=\"test[numcmp]\" mode=\"create-test\">\n    <xsl:param name=\"fillin\"/>\n    <xsl:choose>\n        <xsl:when test=\"(numcmp/@use-answer='yes' and $fillin/@ansobj) or numcmp/@object\">\n            <xsl:apply-templates select=\".\" mode=\"create-test-ansobj\">\n                <xsl:with-param name=\"fillin\" select=\"$fillin\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:variable name=\"answer\">\n                <xsl:choose>\n                    <xsl:when test=\"numcmp/@use-answer='yes' and $fillin/@answer\">\n                        <xsl:value-of select=\"$fillin/@answer\"/>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:value-of select=\"numcmp/@value\"/>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:variable>\n            <xsl:variable name=\"tolerance\">\n                <xsl:choose>\n                    <xsl:when test=\"numcmp/@use-answer='yes' and $fillin/@tolerance\">\n                        <xsl:value-of select=\"$fillin/@tolerance\"/>\n                    </xsl:when>\n                    <xsl:when test=\"numcmp/@tolerance\">\n                        <xsl:value-of select=\"numcmp/@tolerance\"/>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:text>0</xsl:text>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:variable>\n            <xsl:variable name=\"min-val\">\n              <xsl:choose>\n                <xsl:when test=\"numcmp/@min\">\n                  <xsl:value-of select=\"numcmp/@min\"/>\n                </xsl:when>\n                <xsl:otherwise>\n                  <xsl:value-of select=\"$answer - $tolerance\"/>\n                </xsl:otherwise>\n              </xsl:choose>\n            </xsl:variable>\n            <xsl:variable name=\"max-val\">\n              <xsl:choose>\n                <xsl:when test=\"numcmp/@max\">\n                  <xsl:value-of select=\"numcmp/@max\"/>\n                </xsl:when>\n                <xsl:otherwise>\n                  <xsl:value-of select=\"$answer + $tolerance\"/>\n                </xsl:otherwise>\n              </xsl:choose>\n            </xsl:variable>\n            <xsl:text>\"number\": [</xsl:text>\n            <xsl:value-of select=\"$min-val\"/>\n            <xsl:text>,</xsl:text>\n            <xsl:value-of select=\"$max-val\"/>\n            <xsl:text>]</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- When the comparison is with an object, we rely on function comparisons. -->\n<xsl:template match=\"test[numcmp]\" mode=\"create-test-ansobj\">\n    <xsl:param name=\"fillin\"/>\n    <xsl:variable name=\"ansObject\">\n        <xsl:choose>\n            <xsl:when test=\"numcmp/@use-answer='yes' and $fillin/@ansobj\">\n                <xsl:value-of select=\"$fillin/@ansobj\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"numcmp/@object\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"tolerance\">\n        <xsl:choose>\n            <xsl:when test=\"numcmp/@use-answer='yes' and $fillin/@tolerance\">\n                <xsl:value-of select=\"$fillin/@tolerance\"/>\n            </xsl:when>\n            <xsl:when test=\"numcmp/@tolerance\">\n                <xsl:value-of select=\"numcmp/@tolerance\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>0</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"min-val\">\n        <xsl:choose>\n            <xsl:when test=\"numcmp/@min\">\n                <xsl:value-of select=\"numcmp/@min\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$ansObject\"/>\n                <xsl:text> - </xsl:text>\n                <xsl:value-of select=\"$tolerance\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"max-val\">\n        <xsl:choose>\n            <xsl:when test=\"numcmp/@max\">\n                <xsl:value-of select=\"numcmp/@max\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$ansObject\"/>\n                <xsl:text> + </xsl:text>\n                <xsl:value-of select=\"$tolerance\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:text>\"solution_code\": </xsl:text>\n    <xsl:variable name=\"js_code\">\n        <xsl:text>function() { </xsl:text>\n        <xsl:text>return (ans &gt;= </xsl:text>\n        <xsl:value-of select=\"$min-val\"/>\n        <xsl:text>) &amp;&amp; (ans &lt;= </xsl:text>\n        <xsl:value-of select=\"$max-val\"/>\n        <xsl:text>); }()</xsl:text>\n    </xsl:variable>\n    <xsl:call-template name=\"escape-quote-string\">\n        <xsl:with-param name=\"text\" select=\"$js_code\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- JSON dictionary for string condition -->\n<xsl:template match=\"test[strcmp]\" mode=\"create-test\">\n    <xsl:param name=\"fillin\"/>\n    <xsl:choose>\n        <xsl:when test=\"strcmp/@use-answer='yes' and $fillin/@ansobj or strcmp//eval\">\n            <xsl:apply-templates mode=\"create-test-ansobj\">\n                <xsl:with-param name=\"fillin\" select=\"$fillin\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:variable name=\"answer\">\n                <xsl:choose>\n                    <!-- If comparing with actual answer, implicitly a literal check -->\n                    <xsl:when test=\"strcmp/@use-answer='yes'\">\n                        <xsl:call-template name=\"escape-regexp-literal\">\n                            <xsl:with-param name=\"text\" select=\"$fillin/@answer\"/>\n                        </xsl:call-template>\n                    </xsl:when>\n                    <xsl:when test=\"strcmp/@literal='yes'\">\n                        <xsl:call-template name=\"escape-regexp-literal\">\n                            <xsl:with-param name=\"text\" select=\"strcmp\"/>\n                        </xsl:call-template>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:value-of select=\"strcmp\"/>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:variable>\n            <xsl:variable name=\"regexFlags\">\n                <xsl:choose>\n                    <xsl:when test=\"strcmp/@use-answer='yes' and $fillin/@case = 'insensitive'\">\n                        <xsl:text>i</xsl:text>\n                    </xsl:when>\n                    <xsl:when test=\"strcmp/@case = 'insensitive'\">\n                        <xsl:text>i</xsl:text>\n                    </xsl:when>\n                    <!-- Otherwise nothing -->\n                </xsl:choose>\n            </xsl:variable>\n            <!-- regex string match, drop    -->\n            <!-- leading/trailing whitespace -->\n            <xsl:text>\"regex\": \"</xsl:text>\n            <!-- JSON escapes necessary for regular expression -->\n            <xsl:call-template name=\"escape-json-string\">\n                <xsl:with-param name=\"text\">\n                    <xsl:choose>\n                        <xsl:when test=\"strcmp/@strip = 'no'\">\n                            <xsl:value-of select=\"$answer\"/>\n                        </xsl:when>\n                        <xsl:otherwise>\n                            <xsl:text>^\\s*</xsl:text>\n                            <xsl:value-of select=\"$answer\"/>\n                            <xsl:text>\\s*$</xsl:text>\n                        </xsl:otherwise>\n                    </xsl:choose>\n                </xsl:with-param>\n            </xsl:call-template>\n            <xsl:text>\"</xsl:text>\n            <!-- flag for case-sensitive match -->\n            <!-- default:  'sensitive'         -->\n            <xsl:text>, \"regexFlags\": \"</xsl:text>\n            <xsl:value-of select=\"$regexFlags\"/>\n            <xsl:text>\"</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- When the comparison is with an object, we rely on function comparisons. -->\n<xsl:template match=\"test[strcmp]\" mode=\"create-test-ansobj\">\n    <xsl:variable name=\"regex\">\n        <xsl:choose>\n            <xsl:when test=\"strcmp/@use-answer='yes' and $fillin/@ansobj\">\n                <xsl:text>`${</xsl:text>\n                <xsl:value-of select=\"$fillin/@ansobj\"/>\n                <xsl:text>}`</xsl:text>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>`</xsl:text>\n                <xsl:apply-templates select=\"strcmp/*\" mode=\"strcmp-object-substitution\"/>\n                <xsl:text>`</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"regexFlags\">\n        <xsl:choose>\n            <xsl:when test=\"strcmp/@use-answer='yes' and $fillin/@case = 'insensitive'\">\n                <xsl:text>i</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"strcmp/@case = 'insensitive'\">\n                <xsl:text>i</xsl:text>\n            </xsl:when>\n            <!-- Otherwise Nothing -->\n        </xsl:choose>\n    </xsl:variable>\n    <!-- create a function to do the regex -->\n    <xsl:text>\"solution_code\": </xsl:text>\n    <xsl:variable name=\"js_code\">\n        <xsl:text>function(){&#xa;</xsl:text>\n            <xsl:text>  const re_str = </xsl:text><xsl:value-of select=\"$regex\"/><xsl:text>;&#xa;</xsl:text>\n            <xsl:text>  const re = new RegExp(re_str, \"</xsl:text>\n            <xsl:value-of select=\"$regexFlags\"/>\n            <xsl:text>\");&#xa;</xsl:text>\n            <xsl:text>  return re.test(ans);&#xa;</xsl:text>\n            <xsl:text>}()&#xa;</xsl:text>\n            </xsl:variable>\n    <xsl:call-template name=\"escape-quote-string\">\n        <xsl:with-param name=\"text\" select=\"$js_code\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<xsl:template match=\"eval\" mode=\"strcmp-object-substitution\">\n    <xsl:text>${</xsl:text>\n    <xsl:value-of select=\".\"/>\n    <xsl:text>}</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"strcmp-object-substitution\">\n    <xsl:copy-of select=\".\"/>\n</xsl:template>\n\n<!-- Otherwise create a function that deals with the test. -->\n<xsl:template match=\"test\" mode=\"create-test\">\n    <xsl:param name=\"fillin\" />\n    <xsl:variable name=\"conditions\" select=\"*[not(self::feedback)]\"/>\n    <xsl:text>\"solution_code\": </xsl:text>\n    <xsl:variable name=\"js_code\">\n        <xsl:text>function() {&#xa;</xsl:text>\n        <!-- Create a checker function. Initialize a stack of flag variables to track results. -->\n        <xsl:text>    var testResults = new Array();&#xa;</xsl:text>\n        <xsl:choose>\n            <xsl:when test=\"count($conditions) = 1\">\n                <xsl:call-template name=\"checker-simple\">\n                    <xsl:with-param name=\"fillin\" select=\"$fillin\" />\n                    <xsl:with-param name=\"curTest\" select=\"$conditions\" />\n                    <xsl:with-param name=\"level\" select=\"0\" />\n                </xsl:call-template>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:call-template name=\"checker-layer\">\n                    <xsl:with-param name=\"fillin\" select=\"$fillin\" />\n                    <xsl:with-param name=\"tests\" select=\"$conditions\" />\n                    <xsl:with-param name=\"level\" select=\"0\" />\n                    <xsl:with-param name=\"logic\" select=\"'and'\" /> <!-- All tests at first layer must be true -->\n                </xsl:call-template>\n            </xsl:otherwise>\n        </xsl:choose>\n        <xsl:text>    return (testResults[0]);&#xa;</xsl:text>\n        <xsl:text>}()</xsl:text>\n    </xsl:variable>\n    <xsl:call-template name=\"escape-quote-string\">\n        <xsl:with-param name=\"text\" select=\"$js_code\"/>\n    </xsl:call-template>\n</xsl:template>\n\n\n<!-- This template is called for a simple test (no compound logic). -->\n<xsl:template name=\"checker-simple\">\n    <xsl:param name=\"curTest\" />\n    <xsl:param name=\"fillin\" />\n    <xsl:param name=\"level\" select=\"0\" />\n    <xsl:choose>\n        <!-- Test might be coded directly in javascript -->\n        <xsl:when test=\"name($curTest) = 'jscmp'\">\n            <xsl:text>    testResults[</xsl:text>\n            <xsl:value-of select=\"$level\" />\n            <xsl:text>] = </xsl:text>\n            <xsl:value-of select=\"$curTest\"/>\n        </xsl:when>\n        <!-- Test might require logic -->\n        <xsl:when test=\"name($curTest)='logic'\">\n            <xsl:call-template name=\"checker-layer\">\n                <xsl:with-param name=\"fillin\" select=\"$fillin\" />\n                <xsl:with-param name=\"tests\" select=\"$curTest/*\" />\n                <xsl:with-param name=\"level\" select=\"$level + 1\" />\n                <xsl:with-param name=\"logic\" select=\"$curTest/@op\" /> <!-- Default: All tests at first layer must be true -->\n            </xsl:call-template>\n            <xsl:text>    testResults[</xsl:text>\n            <xsl:value-of select=\"$level\" />\n            <xsl:text>] = testResults[</xsl:text>\n            <xsl:value-of select=\"$level + 1\" />\n            <xsl:text>];&#xa;</xsl:text>\n        </xsl:when>\n        <!-- Otherwise simple test -->\n        <xsl:otherwise>\n            <!-- A test can have an implied equal or an explicit equal -->\n            <!-- At root level, the test might also have a feedback. Skip that. -->\n            <xsl:text>    testResults[</xsl:text>\n            <xsl:value-of select=\"$level\" />\n            <xsl:text>] = </xsl:text>\n            <xsl:text>_mobjs.compareExpressions(</xsl:text>\n            <xsl:choose>\n                <!-- An equal element must have two expression children. -->\n                <xsl:when test=\"name($curTest)='mathcmp' and $curTest/@use-answer='yes'\">\n                    <xsl:choose>\n                        <xsl:when test=\"not($fillin/@ansobj)\">\n                            <xsl:message>PTX:ERROR:   Feedback for \"<xsl:apply-templates select=\".\" mode=\"unique-id\" />\" says to use given math answer, but @ansobj not defined. </xsl:message>\n                            <xsl:text>UNDEFINED</xsl:text>\n                        </xsl:when>\n                        <xsl:otherwise>\n                            <xsl:value-of select=\"$fillin/@ansobj\"/>\n                        </xsl:otherwise>\n                    </xsl:choose>\n                    <xsl:text>, ans</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"name($curTest)='mathcmp' and $curTest/@obj\">\n                    <xsl:value-of select=\"$curTest/@obj\"/>\n                    <xsl:text>, ans</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"name($curTest)='mathcmp' and count($curTest/*)=1\">\n                    <xsl:apply-templates select=\"$curTest/*[1]\" mode=\"evaluate\"/>\n                    <xsl:text>, ans</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"name($curTest)='mathcmp' and count($curTest/*)=2\">\n                    <xsl:apply-templates select=\"$curTest/*[1]\" mode=\"evaluate\"/>\n                    <xsl:text>, </xsl:text>\n                    <xsl:apply-templates select=\"$curTest/*[2]\" mode=\"evaluate\"/>\n                </xsl:when>\n                <!-- An implied equal compares the submitted answer to the given expression. -->\n                <xsl:otherwise>   <!-- Must be expression: #eval or #de-expression -->\n                    <xsl:apply-templates select=\"$curTest\" mode=\"evaluate\"/>\n                    <xsl:text>, ans</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n            <xsl:text>)</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n    <xsl:text>;&#xa;</xsl:text>\n</xsl:template>\n\n<!-- A test can also be composite involving a combination of logical tests -->\n<!-- This template works through one layer, recursively dealing with deeper layers as needed -->\n<xsl:template name=\"checker-layer\" >\n    <xsl:param name=\"fillin\" />\n    <xsl:param name=\"tests\" />                   <!-- The layer of tests (subtree) -->\n    <xsl:param name=\"level\" select=\"0\" />        <!-- Level (or depth) of the layer -->\n    <xsl:param name=\"logic\" select=\"'and'\" />    <!-- and = all must be true, or = at least one, not = negation -->\n    <xsl:choose>\n        <xsl:when test=\"$logic = 'and'\">         <!-- Treat logic like multipication. A single false (0) makes product zero -->\n            <xsl:text>    testResults[</xsl:text><xsl:value-of select=\"$level\" /><xsl:text>] = 1;&#xa;</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$logic = 'or'\">         <!-- Treat logic like addition. A single true makes sum positive -->\n            <xsl:text>testResults[</xsl:text><xsl:value-of select=\"$level\" /><xsl:text>] = 0;&#xa;</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$logic = 'not'\"/>         <!-- Negation has no preparation -->\n        <xsl:otherwise>\n            <xsl:message>PTX:ERROR:    Invalid logic operator in dynamic fillin for \"<xsl:apply-templates select=\".\" mode=\"unique-id\" />\"</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n    <xsl:for-each select=\"$tests\">    <!-- Work through the layer of tests one at a time. -->\n        <xsl:choose>\n            <xsl:when test=\"name()='and'\">\n                <xsl:text>    testResults[</xsl:text>\n                <xsl:value-of select=\"$level+1\" />\n                <xsl:text>] = 1;&#xa;</xsl:text>\n                <xsl:call-template name=\"checker-layer\">\n                    <xsl:with-param name=\"fillin\" select=\"$fillin\" />\n                    <xsl:with-param name=\"tests\" select=\"./*\" />\n                    <xsl:with-param name=\"level\" select=\"$level+1\" />\n                    <xsl:with-param name=\"logic\" select=\"'and'\" /> <!-- Default: All tests at first layer must be true -->\n                </xsl:call-template>\n            </xsl:when>\n            <xsl:when test=\"name()='or'\">\n                <xsl:text>    testResults[</xsl:text>\n                <xsl:value-of select=\"$level+1\" />\n                <xsl:text>] = 0;&#xa;</xsl:text>\n                <xsl:call-template name=\"checker-layer\">\n                    <xsl:with-param name=\"fillin\" select=\"$fillin\" />\n                    <xsl:with-param name=\"tests\" select=\"./*\" />\n                    <xsl:with-param name=\"level\" select=\"$level+1\" />\n                    <xsl:with-param name=\"logic\" select=\"'or'\" />\n                </xsl:call-template>\n            </xsl:when>\n            <xsl:when test=\"name()='not'\">\n                <xsl:call-template name=\"checker-layer\">\n                    <xsl:with-param name=\"fillin\" select=\"$fillin\" />\n                    <xsl:with-param name=\"tests\" select=\"./*\" />\n                    <xsl:with-param name=\"level\" select=\"$level+1\" />\n                    <xsl:with-param name=\"logic\" select=\"'not'\" />\n                </xsl:call-template>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:call-template name=\"checker-simple\">\n                    <xsl:with-param name=\"fillin\" select=\"$fillin\" />\n                    <xsl:with-param name=\"curTest\" select=\".\" />\n                    <xsl:with-param name=\"level\" select=\"$level+1\" />\n                </xsl:call-template>\n            </xsl:otherwise>\n        </xsl:choose>\n        <xsl:choose> <!-- Deal with the results of that recursive call to a deeper layer. -->\n            <xsl:when test=\"$logic = 'and'\">\n                <xsl:text>    testResults[</xsl:text><xsl:value-of select=\"$level\" />\n                <xsl:text>] &amp;= testResults[</xsl:text><xsl:value-of select=\"$level+1\" /><xsl:text>];&#xa;</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"$logic = 'or'\">\n                <xsl:text>    testResults[</xsl:text><xsl:value-of select=\"$level\" />\n                <xsl:text>] |= testResults[</xsl:text><xsl:value-of select=\"$level+1\" /><xsl:text>];&#xa;</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"$logic = 'not'\">\n                <xsl:text>    testResults[</xsl:text><xsl:value-of select=\"$level\" />\n                <xsl:text>] = !(testResults[</xsl:text><xsl:value-of select=\"$level+1\" /><xsl:text>]);&#xa;</xsl:text>\n            </xsl:when>\n            <!-- Otherwise: invalid logic call was signaled as Error earlier. -->\n        </xsl:choose>\n    </xsl:for-each>\n</xsl:template>\n\n\n<!-- ================================================ -->\n<!-- Templates for working with evaluation objects    -->\n<!-- ================================================ -->\n\n<!-- Wrappers for calling appropriate javascript commands that  -->\n<!-- will parse the expression for a number appropriately,     -->\n<!-- which could be written as an expression involving symbols -->\n<!-- or a random number                                        -->\n<xsl:template match=\"de-number\" mode=\"evaluate\">\n    <xsl:param name=\"setupMode\" />\n    <xsl:variable name=\"prefix\">\n        <xsl:if test=\"$setupMode\">\n            <xsl:text>v.</xsl:text>\n        </xsl:if>\n    </xsl:variable>\n    <xsl:variable name=\"de_env\">\n        <xsl:value-of select=\"$prefix\"/>\n        <xsl:text>_mobjs</xsl:text>\n    </xsl:variable>\n    <xsl:value-of select=\"$de_env\"/>\n    <xsl:text>.parseExpression(</xsl:text>\n    <xsl:call-template name=\"quote-strip-string\">\n        <xsl:with-param name=\"text\" select=\".\"/>\n    </xsl:call-template>\n    <xsl:text>, \"number\")</xsl:text>\n    <xsl:text>.reduce().simplifyConstants()</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"de-evaluate\" mode=\"evaluate\">\n    <xsl:param name=\"setupMode\" />\n    <xsl:variable name=\"prefix\">\n        <xsl:if test=\"$setupMode\">\n            <xsl:text>v.</xsl:text>\n        </xsl:if>\n    </xsl:variable>\n    <xsl:variable name=\"de_env\">\n        <xsl:value-of select=\"$prefix\"/>\n        <xsl:text>_mobjs</xsl:text>\n    </xsl:variable>\n    <xsl:value-of select=\"$de_env\"/>\n    <xsl:text>.evaluateExpression(</xsl:text>\n        <xsl:apply-templates select=\"formula/*\" mode=\"evaluate\">\n            <xsl:with-param name=\"setupMode\" select=\"$setupMode\"/>\n        </xsl:apply-templates>\n        <xsl:text>, \"number\", {</xsl:text>\n        <xsl:for-each select=\"variable\">\n            <xsl:if test=\"position() > 1\">\n                <xsl:text>, </xsl:text>\n            </xsl:if>\n            <xsl:apply-templates select=\".\" mode=\"evaluation-binding\" >\n                <xsl:with-param name=\"setupMode\" select=\"$setupMode\" />\n            </xsl:apply-templates>\n        </xsl:for-each>\n    <xsl:text>})</xsl:text>\n    <xsl:if test=\"@reduce='yes'\">\n        <xsl:text>.reduce().simplifyConstants()</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<xsl:template match=\"de-random[@distribution='discrete']\" mode=\"evaluate\">\n    <xsl:text>v._mobjs.generateRandom(\"discrete\", { min:</xsl:text>\n    <xsl:choose>\n        <xsl:when test=\"@min\">\n            <xsl:value-of select=\"@min\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>0</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n    <xsl:text>, max:</xsl:text>\n    <xsl:choose>\n        <xsl:when test=\"@max\">\n            <xsl:value-of select=\"@max\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>1</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n    <xsl:text>, by:</xsl:text>\n    <xsl:choose>\n        <xsl:when test=\"@by\">\n            <xsl:value-of select=\"@by\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>1</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n    <xsl:text>, nonzero:</xsl:text>\n    <xsl:choose>\n        <xsl:when test=\"@nonzero = 'yes'\">\n            <xsl:text>true</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>false</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n    <xsl:text>})</xsl:text>\n</xsl:template>\n\n<!-- Objects defined as formulas. Several possible modes: -->\n<!-- formula (literal), substitution (composition),       -->\n<!-- derivative and evaluate                              -->\n<xsl:template match=\"de-expression[not(@mode) or @mode='formula']\" mode=\"evaluate\">\n    <xsl:param name=\"setupMode\" />\n    <xsl:variable name=\"prefix\">\n        <xsl:if test=\"$setupMode\">\n            <xsl:text>v.</xsl:text>\n        </xsl:if>\n    </xsl:variable>\n    <xsl:variable name=\"de_env\">\n        <xsl:value-of select=\"$prefix\"/>\n        <xsl:text>_mobjs</xsl:text>\n    </xsl:variable>\n    <xsl:value-of select=\"$de_env\"/>\n    <xsl:text>.parseExpression(</xsl:text>\n    <xsl:call-template name=\"quote-strip-string\">\n        <xsl:with-param name=\"text\" select=\".\"/>\n    </xsl:call-template>\n    <xsl:text>, \"formula\")</xsl:text>\n    <xsl:if test=\"@reduce='yes'\">\n        <xsl:text>.reduce().simplifyConstants()</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<xsl:template match=\"de-expression[@mode='substitution']\" mode=\"evaluate\">\n    <xsl:param name=\"setupMode\" />\n    <xsl:variable name=\"prefix\">\n        <xsl:if test=\"$setupMode\">\n            <xsl:text>v.</xsl:text>\n        </xsl:if>\n    </xsl:variable>\n    <xsl:variable name=\"de_env\">\n        <xsl:value-of select=\"$prefix\"/>\n        <xsl:text>_mobjs</xsl:text>\n    </xsl:variable>\n    <xsl:value-of select=\"$de_env\"/>\n    <xsl:text>.composeExpression(</xsl:text>\n    <xsl:apply-templates select=\"formula/*\" mode=\"evaluate\">\n        <xsl:with-param name=\"setupMode\" select=\"$setupMode\"/>\n    </xsl:apply-templates>\n    <xsl:text>, {</xsl:text>\n    <xsl:for-each select=\"variable\">\n        <xsl:if test=\"position() > 1\">\n            <xsl:text>, </xsl:text>\n        </xsl:if>\n        <xsl:apply-templates select=\".\" mode=\"evaluation-binding\" >\n            <xsl:with-param name=\"setupMode\" select=\"$setupMode\" />\n        </xsl:apply-templates>\n    </xsl:for-each>\n    <xsl:text>})</xsl:text>\n    <xsl:if test=\"@reduce='yes'\">\n        <xsl:text>.reduce().simplifyConstants()</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<xsl:template match=\"de-expression[@mode='derivative']\" mode=\"evaluate\">\n    <xsl:param name=\"setupMode\" />\n    <xsl:variable name=\"prefix\">\n        <xsl:if test=\"$setupMode\">\n            <xsl:text>v.</xsl:text>\n        </xsl:if>\n    </xsl:variable>\n    <xsl:variable name=\"de_env\">\n        <xsl:value-of select=\"$prefix\"/>\n        <xsl:text>_mobjs</xsl:text>\n    </xsl:variable>\n    <xsl:apply-templates select=\"formula/*\" mode=\"evaluate\">\n        <xsl:with-param name=\"setupMode\" select=\"$setupMode\" />\n    </xsl:apply-templates>\n    <xsl:text>.derivative(</xsl:text>\n    <xsl:call-template name=\"quote-string\">\n        <xsl:with-param name=\"text\" select=\"variable/@name\"/>\n    </xsl:call-template>\n    <xsl:text>)</xsl:text>\n    <xsl:if test=\"@reduce='yes'\">\n        <xsl:text>.reduce().simplifyConstants()</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- Used during composition or evaluation of a variable-->\n<xsl:template match=\"variable\" mode=\"evaluation-binding\">\n    <xsl:param name=\"setupMode\" />\n    <xsl:variable name=\"prefix\">\n        <xsl:if test=\"$setupMode\">\n            <xsl:text>v.</xsl:text>\n        </xsl:if>\n    </xsl:variable>\n    <xsl:call-template name=\"quote-string\">\n        <xsl:with-param name=\"text\" select=\"@name\" />\n    </xsl:call-template>\n    <xsl:text>: </xsl:text>\n    <xsl:choose>\n        <xsl:when test=\"eval or de-number or de-expression\">\n            <xsl:apply-templates select=\"eval|de-number|de-expression\" mode=\"evaluate\">\n                <xsl:with-param name=\"setupMode\" select=\"$setupMode\" />\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\".\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- var elements in expressions (evaluate) are replaced by their name -->\n<!-- During setup, we need to use the context of the `v` object        -->\n<xsl:template match=\"eval\" mode=\"evaluate\">\n    <xsl:param name=\"setupMode\" />\n    <xsl:variable name=\"prefix\">\n        <xsl:if test=\"$setupMode\">\n            <xsl:text>v.</xsl:text>\n        </xsl:if>\n    </xsl:variable>\n    <xsl:value-of select=\"$prefix\"/>\n    <xsl:value-of select=\"@obj\"/>\n</xsl:template>\n\n<!-- Nothing else is defined for evaluation during setup  -->\n<xsl:template match=\"/\" mode=\"evaluate\"/>\n\n<xsl:template match=\"feedback\" mode=\"serialize-feedback\">\n    <xsl:variable name=\"feedback-rtf\">\n        <xsl:apply-templates select=\"*\" />\n    </xsl:variable>\n    <!-- serialize HTML as text, then escape as JSON -->\n    <xsl:call-template name=\"escape-json-string\">\n        <xsl:with-param name=\"text\">\n            <xsl:apply-templates select=\"exsl:node-set($feedback-rtf)\" mode=\"xml-to-string\"/>\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n</xsl:stylesheet>\n","pretext-runestone-static.xsl":"<?xml version='1.0'?> <!-- As XML file -->\n\n<!--********************************************************************\nCopyright (C) 2022-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- http://pimpmyxslt.com/articles/entity-tricks-part2/ -->\n<!DOCTYPE xsl:stylesheet [\n    <!ENTITY % entities SYSTEM \"entities.ent\">\n    %entities;\n]>\n\n<xsl:stylesheet\n    xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\"\n    xmlns:xml=\"http://www.w3.org/XML/1998/namespace\"\n    xmlns:pi=\"http://pretextbook.org/2020/pretext/internal\"\n    xmlns:exsl=\"http://exslt.org/common\"\n    xmlns:str=\"http://exslt.org/strings\"\n    extension-element-prefixes=\"pi exsl str\"\n>\n\n<!-- Conversion of author source for Runestone/interactive exercises  -->\n<!-- to \"standard\" PreTeXt exercises, which can be used as-is in      -->\n<!-- *every* conversion, except the HTML conversion, where a more     -->\n<!-- capable version is designed to be powered by Runestone Services. -->\n\n<!-- We include text utilities so we can manipulate indentation -->\n<!-- in blocks of code as part of Parsons problems              -->\n<xsl:include href = \"./pretext-text-utilities.xsl\"/>\n\n<!-- The enclosing \"exercise\" and its attributes are preserved -->\n<!-- before these templates are applied, so these should just  -->\n<!-- produce the \"body\" of the exercise.                       -->\n\n<!-- The application of the \"runestone-to-static\" template is        -->\n<!-- controlled by a surrounding \"match\" that limits elements        -->\n<!-- to \"exercise\", PROJECT-LIKE, and soon \"task\".  So the           -->\n<!-- matches here are fine with a *[@pi:exercise-interactive='foo'], -->\n<!-- as a convenience.                                               -->\n\n<!-- These get-programming-language templates duplicate logic from pretext-common  -->\n<!-- as the contents of that file are not available yet.                           -->\n<!-- NB: these run during assembly, before the repair pass has produced the tree  -->\n<!-- behind $docinfo, so they read the version tree and must recognize both the   -->\n<!-- \"docinfo/defaults\" home (preferred) and the deprecated top-level placement.  -->\n<xsl:template match=\"program\" mode=\"get-programming-language\">\n    <xsl:choose>\n        <xsl:when test=\"@language\">\n            <xsl:value-of select=\"@language\" />\n        </xsl:when>\n        <xsl:when test=\"$version-docinfo/defaults/programs/@language\">\n            <xsl:value-of select=\"$version-docinfo/defaults/programs/@language\" />\n        </xsl:when>\n        <xsl:when test=\"$version-docinfo/programs/@language\">\n            <xsl:value-of select=\"$version-docinfo/programs/@language\" />\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"*[@pi:exercise-interactive = 'parson' or @pi:exercise-interactive = 'parson-horizontal']\" mode=\"get-programming-language\">\n    <xsl:choose>\n        <xsl:when test=\"@language\">\n            <xsl:value-of select=\"@language\" />\n        </xsl:when>\n        <xsl:when test=\"$version-docinfo/defaults/parsons/@language\">\n            <xsl:value-of select=\"$version-docinfo/defaults/parsons/@language\" />\n        </xsl:when>\n        <xsl:when test=\"$version-docinfo/parsons/@language\">\n            <xsl:value-of select=\"$version-docinfo/parsons/@language\" />\n        </xsl:when>\n        <xsl:when test=\"$version-docinfo/defaults/programs/@language\">\n            <xsl:value-of select=\"$version-docinfo/defaults/programs/@language\" />\n        </xsl:when>\n        <xsl:when test=\"$version-docinfo/programs/@language\">\n            <xsl:value-of select=\"$version-docinfo/programs/@language\" />\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- True/False -->\n\n<xsl:template match=\"*[@pi:exercise-interactive = 'truefalse']\" mode=\"runestone-to-static\">\n    <!-- metadata (idx, title) -->\n    <xsl:copy-of select=\"statement/preceding-sibling::*\"/>\n    <!-- prompt, followed by ordered list of choices -->\n    <statement>\n        <xsl:copy-of select=\"statement/node()\"/>\n    </statement>\n    <!-- Hints are authored, not derived from problem formulation -->\n    <xsl:copy-of select=\"hint\"/>\n    <!-- Any authored answers, not derived from problem formulation.  -->\n    <!-- *Before* automatic ones, so numbering matches interactive    -->\n    <!-- versions on authored ones.                                   -->\n    <xsl:copy-of select=\"answer\"/>\n    <!-- the answer, simply \"True\" or \"False\" -->\n    <answer>\n        <xsl:choose>\n            <xsl:when test=\"statement/@correct = 'yes'\">\n                <p>\n                    <xsl:element name=\"pi:localize\">\n                        <xsl:attribute name=\"string-id\">true</xsl:attribute>\n                    </xsl:element>\n                    <xsl:text>.</xsl:text>\n                </p>\n            </xsl:when>\n            <xsl:when test=\"statement/@correct = 'no'\">\n                <p>\n                    <xsl:element name=\"pi:localize\">\n                        <xsl:attribute name=\"string-id\">false</xsl:attribute>\n                    </xsl:element>\n                    <xsl:text>.</xsl:text>\n                </p>\n            </xsl:when>\n            <xsl:otherwise/>\n        </xsl:choose>\n    </answer>\n    <!-- Any authored solutions, not derived from problem formulation. -->\n    <!-- *Before* automatic ones, so numbering matches interactive     -->\n    <!-- versions on authored ones.                                    -->\n    <xsl:copy-of select=\"solution\"/>\n    <!-- Answer, as above, plus explication with feedback -->\n    <!-- TODO: experiment with a one-item \"dl\" for a slightly more       -->\n    <!--       appealing presentation, rather than a one-word paragraph. -->\n    <solution>\n        <xsl:choose>\n            <xsl:when test=\"statement/@correct = 'yes'\">\n                <p>\n                    <xsl:element name=\"pi:localize\">\n                        <xsl:attribute name=\"string-id\">true</xsl:attribute>\n                    </xsl:element>\n                    <xsl:text>.</xsl:text>\n                </p>\n            </xsl:when>\n            <xsl:when test=\"statement/@correct = 'no'\">\n                <p>\n                    <xsl:element name=\"pi:localize\">\n                        <xsl:attribute name=\"string-id\">false</xsl:attribute>\n                    </xsl:element>\n                    <xsl:text>.</xsl:text>\n                </p>\n            </xsl:when>\n            <xsl:otherwise/>\n        </xsl:choose>\n        <xsl:copy-of select=\"feedback/node()\"/>\n    </solution>\n</xsl:template>\n\n<xsl:template match=\"*[@pi:exercise-interactive = 'multiplechoice']\" mode=\"runestone-to-static\">\n    <!-- metadata (idx, title) -->\n    <xsl:copy-of select=\"statement/preceding-sibling::*\"/>\n    <!-- prompt, followed by ordered list of choices -->\n    <statement>\n        <xsl:copy-of select=\"statement/node()\"/>\n        <p><ol marker=\"A.\"> <!-- conforms to RS markers -->\n            <!-- duplicate an optional @cols -->\n            <xsl:copy-of select=\"choices/@cols\"/>\n            <xsl:for-each select=\"choices/choice\">\n                <li>\n                    <xsl:copy-of select=\"statement/node()\"/>\n                </li>\n            </xsl:for-each>\n        </ol></p>\n    </statement>\n    <!-- Hints are authored, not derived from problem formulation -->\n    <xsl:copy-of select=\"hint\"/>\n    <!-- Any authored answers, not derived from problem formulation. -->\n    <!-- *Before* automatic ones, so numbering matches interactive   -->\n    <!-- versions on authored ones.                                  -->\n    <xsl:copy-of select=\"answer\"/>\n    <!-- the correct choices, as letters, in a sentence as a list -->\n    <answer>\n        <p>\n            <xsl:for-each select=\"choices/choice\">\n                <xsl:if test=\"@correct = 'yes'\">\n                    <xsl:number format=\"A\"/>\n                    <xsl:if test=\"following-sibling::choice[@correct = 'yes']\">\n                        <xsl:text>, </xsl:text>\n                    </xsl:if>\n                </xsl:if>\n            </xsl:for-each>\n            <xsl:text>.</xsl:text>\n        </p>\n    </answer>\n    <!-- Any authored solutions, not derived from problem formulation. -->\n    <!-- *Before* automatic ones, so numbering matches interactive     -->\n    <!-- versions on authored ones.                                    -->\n    <xsl:copy-of select=\"solution\"/>\n    <!-- feedback for each choice, in a list -->\n    <solution>\n        <p><ol marker=\"A.\"> <!-- conforms to RS markers -->\n            <xsl:for-each select=\"choices/choice\">\n                <li>\n                    <title>\n                        <xsl:choose>\n                            <xsl:when test=\"@correct = 'yes'\">\n                                <xsl:element name=\"pi:localize\">\n                                    <xsl:attribute name=\"string-id\">correct</xsl:attribute>\n                                </xsl:element>\n                            </xsl:when>\n                            <xsl:otherwise>\n                                <xsl:element name=\"pi:localize\">\n                                    <xsl:attribute name=\"string-id\">incorrect</xsl:attribute>\n                                </xsl:element>\n                            </xsl:otherwise>\n                        </xsl:choose>\n                    </title>\n                    <xsl:copy-of select=\"feedback/node()\"/>\n                </li>\n            </xsl:for-each>\n        </ol></p>\n    </solution>\n</xsl:template>\n\n<xsl:template match=\"*[@pi:exercise-interactive = 'parson']\" mode=\"runestone-to-static\">\n    <!-- determine these options before context switches -->\n    <xsl:variable name=\"language\">\n        <!-- we just need the \"raw\" programming language, not active-language translation -->\n        <xsl:apply-templates select=\".\" mode=\"get-programming-language\"/>\n    </xsl:variable>\n    <xsl:variable name=\"b-natural\" select=\"($language = '') or ($language = 'natural')\"/>\n    <xsl:attribute name=\"language\">\n        <xsl:value-of select=\"$language\"/>\n    </xsl:attribute>\n    <!-- default for @indentation is \"show\", regards presentation -->\n    <xsl:variable name=\"b-indent\" select=\"@indentation = 'hide'\"/>\n    <!-- we use numbers in static versions, if requested, but ignore left/right distinction -->\n    <!-- default for @numbered is \"no\" -->\n    <!-- do not confuse this attribute with the  @pi:numbered  attribute for numbered equations -->\n    <xsl:variable name=\"b-numbered\" select=\"(blocks/@numbered = 'left') or (blocks/@numbered = 'right')\"/>\n    <!-- metadata (idx, title) -->\n    <xsl:copy-of select=\"statement/preceding-sibling::*\"/>\n    <!-- Statement -->\n    <statement>\n        <xsl:copy-of select=\"statement/node()\"/>\n        <xsl:variable name=\"list-type\">\n            <xsl:choose>\n                <xsl:when test=\"$b-numbered\">\n                    <xsl:text>ol</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:text>ul</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:variable>\n        <!-- blocks, in author-defined order, via @order attribute -->\n        <p>\n            <xsl:element name=\"{$list-type}\">\n                <xsl:if test=\"$list-type = 'ol'\">\n                    <xsl:attribute name=\"marker\">\n                        <xsl:text>1.</xsl:text>\n                    </xsl:attribute>\n                </xsl:if>\n                <xsl:for-each select=\"blocks/block\">\n                    <xsl:sort select=\"@order\"/>\n                    <li>\n                        <xsl:choose>\n                            <xsl:when test=\"choice\">\n                                <!-- a paired distractor in the block        -->\n                                <!-- separate alternatives with \"Either/Or\"  -->\n                                <!-- Order is as authored                    -->\n                                <xsl:element name=\"{$list-type}\">\n                                    <xsl:attribute name=\"marker\">\n                                        <xsl:choose>\n                                            <xsl:when test=\"$list-type = 'ol'\">\n                                                <!-- sub-number as a, b, c -->\n                                                <xsl:text>(a)</xsl:text>\n                                            </xsl:when>\n                                            <xsl:when test=\"$list-type = 'ul'\">\n                                                <!-- no markers on \"bulleted\" sublists -->\n                                                <xsl:text/>\n                                            </xsl:when>\n                                        </xsl:choose>\n                                    </xsl:attribute>\n                                    <xsl:for-each select=\"choice\">\n                                        <li>\n                                            <xsl:if test=\"$list-type = 'ul'\">\n                                                <xsl:choose>\n                                                    <xsl:when test=\"not(preceding-sibling::choice)\">\n                                                        <p>\n                                                            <xsl:element name=\"pi:localize\">\n                                                                <xsl:attribute name=\"string-id\">either</xsl:attribute>\n                                                            </xsl:element>\n                                                            <xsl:text>:</xsl:text>\n                                                        </p>\n                                                    </xsl:when>\n                                                    <xsl:otherwise>\n                                                        <p>\n                                                            <xsl:element name=\"pi:localize\">\n                                                                <xsl:attribute name=\"string-id\">or</xsl:attribute>\n                                                            </xsl:element>\n                                                            <xsl:text>:</xsl:text>\n                                                        </p>\n                                                    </xsl:otherwise>\n                                                </xsl:choose>\n                                            </xsl:if>\n                                            <xsl:choose>\n                                                <xsl:when test=\"$b-natural\">\n                                                    <!-- replicate source of choice -->\n                                                    <xsl:copy-of select=\"node()\"/>\n                                                </xsl:when>\n                                                <xsl:otherwise>\n                                                    <!-- computer code, make a code display           -->\n                                                    <!-- A \"p\" gets indentation relative to Either/Or -->\n                                                    <!-- Otherwsie, we could make a sublist?          -->\n                                                    <p>\n                                                        <cd>\n                                                            <xsl:choose>\n                                                                <xsl:when test=\"$b-indent\">\n                                                                    <xsl:apply-templates select=\".\" mode=\"strip-cline-indentation\"/>\n                                                                </xsl:when>\n                                                                <xsl:otherwise>\n                                                                    <xsl:copy-of select=\"node()\"/>\n                                                                </xsl:otherwise>\n                                                            </xsl:choose>\n                                                        </cd>\n                                                    </p>\n                                                </xsl:otherwise>\n                                            </xsl:choose>\n                                        </li>\n                                    </xsl:for-each>\n                                </xsl:element>\n                            </xsl:when>\n                            <xsl:otherwise>\n                                <!-- not a paired distractor -->\n                                <xsl:choose>\n                                    <xsl:when test=\"$b-natural\">\n                                        <!-- replicate source of block -->\n                                        <xsl:copy-of select=\"node()\"/>\n                                    </xsl:when>\n                                    <xsl:otherwise>\n                                        <!-- computer code, make a code display -->\n                                        <cd>\n                                            <xsl:choose>\n                                                <xsl:when test=\"$b-indent\">\n                                                    <!-- a hard problem, reader supplies indentation -->\n                                                    <xsl:apply-templates select=\".\" mode=\"strip-cline-indentation\"/>\n                                                </xsl:when>\n                                                <xsl:otherwise>\n                                                    <!-- a little help, indentation preserved and visible -->\n                                                    <xsl:attribute name=\"showspaces\">\n                                                        <xsl:text>all</xsl:text>\n                                                    </xsl:attribute>\n                                                    <xsl:text>&#xa;</xsl:text>\n                                                    <xsl:copy-of select=\"node()\"/>\n                                                </xsl:otherwise>\n                                            </xsl:choose>\n                                        </cd>\n                                    </xsl:otherwise>\n                                </xsl:choose>\n                            </xsl:otherwise>\n                        </xsl:choose>\n                    </li>\n                </xsl:for-each>\n            </xsl:element>\n        </p>\n    </statement>\n    <!-- Any authored answers, not derived from problem formulation. -->\n    <!-- *Before* automatic ones, so numbering matches interactive   -->\n    <!-- versions on authored ones.                                  -->\n    <xsl:copy-of select=\"answer\"/>\n    <!-- Answer (potentially) -->\n    <xsl:if test=\"$b-numbered\">\n        <!-- can make an economical answer with numbers of the -->\n        <!-- (correct) blocks in the order of the solution     -->\n        <answer>\n            <p>\n                <xsl:for-each select=\"blocks/block\">\n                    <!-- default on \"block\" is  correct=\"yes\" -->\n                    <xsl:if test=\"not(@correct = 'no')\">\n                        <xsl:value-of select=\"@order\"/>\n                        <xsl:if test=\"choice\">\n                            <xsl:for-each select=\"choice\">\n                                <!-- default on \"choice\" is  correct=\"no\" -->\n                                <xsl:if test=\"@correct = 'yes'\">\n                                    <xsl:number format=\"a\"/>\n                                </xsl:if>\n                            </xsl:for-each>\n                        </xsl:if>\n                        <xsl:if test=\"following-sibling::block\">\n                            <xsl:text>, </xsl:text>\n                        </xsl:if>\n                    </xsl:if>\n                </xsl:for-each>\n            </p>\n        </answer>\n    </xsl:if>\n    <!-- Any authored solutions, not derived from problem formulation. -->\n    <!-- *Before* automatic ones, so numbering matches interactive     -->\n    <!-- versions on authored ones.                                   -->\n    <xsl:copy-of select=\"solution\"/>\n    <!-- Solution -->\n    <solution>\n        <xsl:choose>\n            <xsl:when test=\"$b-natural\">\n                <!-- not a programming exercise, use unordered     -->\n                <!-- or description list and copy \"natural\" markup -->\n                <xsl:variable name=\"list-type\">\n                    <xsl:choose>\n                        <xsl:when test=\"$b-numbered\">\n                            <xsl:text>dl</xsl:text>\n                        </xsl:when>\n                        <xsl:otherwise>\n                            <xsl:text>ul</xsl:text>\n                        </xsl:otherwise>\n                    </xsl:choose>\n                </xsl:variable>\n                <p>\n                    <xsl:element name=\"{$list-type}\">\n                        <xsl:if test=\"$list-type = 'dl'\">\n                            <xsl:attribute name=\"width\">\n                                <xsl:text>narrow</xsl:text>\n                            </xsl:attribute>\n                        </xsl:if>\n                        <xsl:for-each select=\"blocks/block\">\n                            <!-- default on \"block\" is  correct=\"yes\" -->\n                            <xsl:if test=\"not(@correct = 'no')\">\n                                <li>\n                                    <xsl:if test=\"$list-type = 'dl'\">\n                                        <title>\n                                            <xsl:value-of select=\"@order\"/>\n                                            <xsl:if test=\"choice\">\n                                                <xsl:for-each select=\"choice\">\n                                                    <!-- default on \"choice\" is  correct=\"no\" -->\n                                                    <xsl:if test=\"@correct = 'yes'\">\n                                                        <xsl:number format=\"a\"/>\n                                                    </xsl:if>\n                                                </xsl:for-each>\n                                            </xsl:if>\n                                        </title>\n                                    </xsl:if>\n                                    <xsl:choose>\n                                        <xsl:when test=\"choice\">\n                                            <!-- just the correct one -->\n                                            <xsl:for-each select=\"choice\">\n                                                <xsl:if test=\"@correct = 'yes'\">\n                                                    <xsl:copy-of select=\"node()\"/>\n                                                </xsl:if>\n                                            </xsl:for-each>\n                                        </xsl:when>\n                                        <xsl:otherwise>\n                                            <xsl:copy-of select=\"node()\"/>\n                                        </xsl:otherwise>\n                                    </xsl:choose>\n                                </li>\n                            </xsl:if>\n                        </xsl:for-each>\n                    </xsl:element>\n                </p>\n            </xsl:when>\n            <xsl:otherwise>\n                <!-- programming language specified, assume \"cline\" -->\n                <!-- structure, reconstruct as a program/input      -->\n                <program>\n                    <xsl:attribute name=\"language\">\n                        <xsl:value-of select=\"$language\"/>\n                    </xsl:attribute>\n                    <input>\n                        <xsl:for-each select=\"blocks/block\">\n                            <xsl:if test=\"not(@correct = 'no')\">\n                                <xsl:choose>\n                                    <xsl:when test=\"choice\">\n                                        <!-- just the correct choice              -->\n                                        <!-- default on \"choice\" is  correct=\"no\" -->\n                                        <xsl:for-each select=\"choice\">\n                                            <xsl:if test=\"@correct = 'yes'\">\n                                                <xsl:for-each select=\"cline\">\n                                                    <xsl:value-of select=\".\"/>\n                                                    <xsl:text>&#xa;</xsl:text>\n                                                </xsl:for-each>\n                                            </xsl:if>\n                                        </xsl:for-each>\n                                    </xsl:when>\n                                    <xsl:otherwise>\n                                        <xsl:for-each select=\"cline\">\n                                            <xsl:value-of select=\".\"/>\n                                            <xsl:text>&#xa;</xsl:text>\n                                        </xsl:for-each>\n                                    </xsl:otherwise>\n                                </xsl:choose>\n                            </xsl:if>\n                        </xsl:for-each>\n                    </input>\n                </program>\n            </xsl:otherwise>\n        </xsl:choose>\n    </solution>\n</xsl:template>\n\n<!-- If a sequence of \"cline\" are in a problem where a student does      -->\n<!-- not get indentation help, then we need to strip it out for          -->\n<!-- presentation in a static form.  This template forms the text block, -->\n<!-- strips leading/gross indentation with a utility template, then uses -->\n<!-- a recursive template to wrap back into \"cline\".                     -->\n\n<xsl:template match=\"block|choice\" mode=\"strip-cline-indentation\">\n    <xsl:variable name=\"text-block\">\n        <xsl:for-each select=\"cline\">\n            <xsl:value-of select=\".\"/>\n            <xsl:text>&#xa;</xsl:text>\n        </xsl:for-each>\n    </xsl:variable>\n    <xsl:call-template name=\"restore-cline\">\n        <xsl:with-param name=\"text\">\n            <xsl:call-template name=\"sanitize-text\">\n                <xsl:with-param name=\"text\">\n                    <xsl:value-of select=\"$text-block\"/>\n                </xsl:with-param>\n            </xsl:call-template>\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n<xsl:template name=\"restore-cline\">\n    <xsl:param name=\"text\"/>\n\n    <xsl:choose>\n        <xsl:when test=\"$text = ''\"/>\n        <xsl:otherwise>\n            <cline>\n                <xsl:value-of select=\"substring-before($text, '&#xa;')\"/>\n            </cline>\n            <xsl:call-template name=\"restore-cline\">\n                <xsl:with-param name=\"text\" select=\"substring-after($text, '&#xa;')\"/>\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Parson (Horizontal) -->\n\n<xsl:template match=\"*[@pi:exercise-interactive = 'parson-horizontal']\" mode=\"runestone-to-static\">\n    <!-- Natural-language blocks (mathematics included) must stay in  -->\n    <!-- the normal flow, where markup is processed; only genuine     -->\n    <!-- program code belongs in a verbatim code display.  This       -->\n    <!-- mirrors the vertical Parsons template above.                 -->\n    <xsl:variable name=\"language\">\n        <xsl:apply-templates select=\".\" mode=\"get-programming-language\"/>\n    </xsl:variable>\n    <xsl:variable name=\"b-natural\" select=\"($language = '') or ($language = 'natural')\"/>\n    <xsl:attribute name=\"language\">\n        <xsl:apply-templates select=\".\" mode=\"active-language\"/>\n    </xsl:attribute>\n    <xsl:copy-of select=\"statement/preceding-sibling::*\"/>\n    <!-- Statement -->\n    <statement>\n        <xsl:copy-of select=\"statement/node()\"/>\n        <p>\n            <!-- hard to tell which is last once sorted, -->\n            <!-- so we just mark front *and* end         -->\n            <xsl:choose>\n                <xsl:when test=\"$b-natural\">\n                    <xsl:text> | </xsl:text>\n                    <xsl:for-each select=\"blocks/block[@order]\">\n                        <xsl:sort select=\"@order\"/>\n                        <xsl:apply-templates select=\".\" mode=\"static-horizontal-block-flow\"/>\n                        <xsl:text> | </xsl:text>\n                    </xsl:for-each>\n                </xsl:when>\n                <xsl:otherwise>\n                    <cd>\n                        <cline>\n                            <xsl:text> | </xsl:text>\n                            <xsl:for-each select=\"blocks/block[@order]\">\n                                <xsl:sort select=\"@order\"/>\n                                <xsl:apply-templates select=\".\" mode=\"static-horizontal-block\"/>\n                                <xsl:text> | </xsl:text>\n                            </xsl:for-each>\n                        </cline>\n                    </cd>\n                </xsl:otherwise>\n            </xsl:choose>\n        </p>\n    </statement>\n    <!-- We provide a complete solution below, -->\n    <!-- so no automatic hint or answer        -->\n    <xsl:copy-of select=\"hint\"/>\n    <xsl:copy-of select=\"answer\"/>\n    <!-- Any authored solutions, not derived from problem formulation. -->\n    <!-- *Before* automatic ones, so numbering matches interactive     -->\n    <!-- versions on authored ones.                                   -->\n    <xsl:copy-of select=\"solution\"/>\n    <solution>\n        <!-- filter out distractors for the solution -->\n        <xsl:variable name=\"the-blocks\" select=\"blocks/block[not(@correct = 'no')]\"/>\n        <p>\n            <xsl:choose>\n                <xsl:when test=\"$b-natural\">\n                    <!-- authored in order, but need to follow @ref -->\n                    <xsl:for-each select=\"$the-blocks\">\n                        <xsl:apply-templates select=\".\" mode=\"static-horizontal-block-flow\"/>\n                        <xsl:if test=\"following-sibling::block\">\n                            <xsl:text> </xsl:text>\n                        </xsl:if>\n                    </xsl:for-each>\n                </xsl:when>\n                <xsl:otherwise>\n                    <cd>\n                        <cline>\n                            <!-- authored in order, but need to follow @ref -->\n                            <xsl:for-each select=\"$the-blocks\">\n                                <xsl:apply-templates select=\".\" mode=\"static-horizontal-block\"/>\n                                <!-- context shift should handle distractors at the end -->\n                                <xsl:if test=\"following-sibling::block\">\n                                    <xsl:text> </xsl:text>\n                                </xsl:if>\n                            </xsl:for-each>\n                        </cline>\n                    </cd>\n                </xsl:otherwise>\n            </xsl:choose>\n        </p>\n    </solution>\n</xsl:template>\n\n<xsl:template match=\"blocks/block\" mode=\"static-horizontal-block\">\n    <xsl:choose>\n        <!-- follow @ref, copy children -->\n        <xsl:when test=\"@ref\">\n            <xsl:copy-of select=\"id(@ref)/node()\"/>\n        </xsl:when>\n        <!-- otherwisr duplicate children -->\n        <xsl:otherwise>\n            <xsl:copy-of select=\"node()\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- The flow variant serves natural-language blocks: the children  -->\n<!-- of a block are \"p\", whose contents join the running line, so   -->\n<!-- mathematics and other markup process normally.                 -->\n<!-- A natural-language block may wrap its content in a \"p\", or -->\n<!-- carry short inline content directly; the flow copy handles -->\n<!-- both shapes, following @ref to a reused source block first -->\n<xsl:template match=\"blocks/block\" mode=\"static-horizontal-block-flow\">\n    <xsl:variable name=\"the-block\" select=\"id(@ref)|self::*[not(@ref)]\"/>\n    <xsl:choose>\n        <xsl:when test=\"$the-block/p\">\n            <xsl:copy-of select=\"$the-block/p/node()\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:copy-of select=\"$the-block/node()\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Cardsort and Matching Problems -->\n\n<!-- Cardsort problems are (roughly) functions, while a (general)   -->\n<!-- matching would be a relation.  Both match \"premise\" with       -->\n<!-- \"response\".  An implementation might have a colum of \"premise\" -->\n<!-- to the left and a column of \"response\" to the right, with an   -->\n<!-- interface allowing the reader to make associations.            -->\n<!-- The markup for each is similar and different.  Some templates  -->\n<!-- here do double-duty, some are specific (solutions).            -->\n\n<!-- Note how this template accomodates both types of problems  -->\n<!-- by using match/select and modal template names effectively. -->\n<xsl:template match=\"*[@pi:exercise-interactive = 'cardsort']|*[@pi:exercise-interactive = 'matching']\" mode=\"runestone-to-static\">\n    <!-- metadata (idx, title) -->\n    <xsl:copy-of select=\"statement/preceding-sibling::*\"/>\n    <!-- Statement -->\n    <statement>\n        <xsl:copy-of select=\"statement/node()\"/>\n        <xsl:apply-templates select=\"cardsort|matching\" mode=\"cardsort-matching-statement\"/>\n    </statement>\n    <!-- Any authored hint, answers, solutions not derived from   -->\n    <!-- problem formulation. *Before* automatic solution, so     -->\n    <!-- numbering matches interactive versions on authored ones. -->\n    <xsl:copy-of select=\"hint\"/>\n    <xsl:copy-of select=\"answer\"/>\n    <xsl:copy-of select=\"solution\"/>\n    <!-- Automatically generated solution -->\n    <solution>\n        <xsl:apply-templates select=\"cardsort|matching\" mode=\"cardsort-matching-solution\"/>\n    </solution>\n</xsl:template>\n\n<!-- Exercise statement as a tabular -->\n\n<!-- For a problem statement, we use a response list re-ordered    -->\n<!-- according to response/@order attribute values given by author -->\n<xsl:template match=\"cardsort|matching\" mode=\"cardsort-matching-statement\">\n\n    <!-- We allow for sorting the premise and response lists,  -->\n    <!-- independently of each other, so that a static version -->\n    <!-- may have a given permutation, decided by the author.  -->\n    <!-- As a practical matter, a \"cardsort\" should have an    -->\n    <!-- ordering, and premise might be easiest.  A \"matching\" -->\n    <!-- can be authored in a desired fashion and ordering is  -->\n    <!-- not needed.                                           -->\n\n    <!-- Reorder and collect premises -->\n    <xsl:variable name=\"sorted-premises-rtf\">\n        <xsl:for-each select=\"match/premise|premise\">\n            <xsl:sort select=\"@order\"/>\n            <xsl:copy-of select=\".\"/>\n        </xsl:for-each>\n    </xsl:variable>\n    <xsl:variable name=\"sorted-premises\" select=\"exsl:node-set($sorted-premises-rtf)\"/>\n\n    <!-- Reorder and collect responses -->\n    <xsl:variable name=\"sorted-responses-rtf\">\n        <xsl:for-each select=\"match/response|response\">\n            <xsl:sort select=\"@order\"/>\n            <xsl:copy-of select=\".\"/>\n        </xsl:for-each>\n    </xsl:variable>\n    <xsl:variable name=\"sorted-responses\" select=\"exsl:node-set($sorted-responses-rtf)\"/>\n\n    <tabular>\n        <xsl:call-template name=\"matching-row\">\n            <!-- $sorted-premises gets a root element, collecting the \"premise\" -->\n            <xsl:with-param name=\"premises\" select=\"$sorted-premises/premise\"/>\n            <!-- $sorted-responses gets a root element, collecting the \"response\" -->\n            <xsl:with-param name=\"responses\" select=\"$sorted-responses/response\"/>\n        </xsl:call-template>\n    </tabular>\n</xsl:template>\n\n<!-- Make one row of a tabular, recursively.  We do not know which list  -->\n<!-- is longer (or they are the same length).  So we \"zip\" them together -->\n<!-- by making a row and then effectively discarding the contents of the -->\n<!-- row in the recursive call.  (We could pass/increment a row number   -->\n<!-- and not keep updating the node-set.)                                -->\n<xsl:template name=\"matching-row\">\n    <xsl:param name=\"premises\"/>\n    <xsl:param name=\"responses\"/>\n\n    <xsl:choose>\n        <xsl:when test=\"not($premises) and not($responses)\"/>\n        <xsl:otherwise>\n            <row>\n                <cell>\n                    <xsl:if test=\"count($premises) > 1\">\n                        <xsl:attribute name=\"bottom\">\n                            <xsl:text>minor</xsl:text>\n                        </xsl:attribute>\n                    </xsl:if>\n                    <xsl:copy-of select=\"$premises[1]/node()\"/>\n                </cell>\n                <!-- An empty (two-character wide) column is a bit of a hack to get -->\n                <!-- a visual separation.  Could we do better with paragraph cells? -->\n                <cell bottom=\"none\"><nbsp/><nbsp/></cell>\n                <cell>\n                    <xsl:if test=\"count($responses) > 1\">\n                        <xsl:attribute name=\"bottom\">\n                            <xsl:text>minor</xsl:text>\n                        </xsl:attribute>\n                    </xsl:if>\n                    <xsl:copy-of select=\"$responses[1]/node()\"/>\n                </cell>\n            </row>\n            <xsl:call-template name=\"matching-row\">\n                <xsl:with-param name=\"premises\" select=\"$premises[position() > 1]\"/>\n                <xsl:with-param name=\"responses\" select=\"$responses[position() > 1]\"/>\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Solutions are lists of lists, but seem to      -->\n<!-- require two different, but similar, templates. -->\n\n<!-- For a solution, we make an unordered list of the responses     -->\n<!-- (the \"buckets\" in true cardsort terminology) and for each      -->\n<!-- we make a sub-list wioth the premises that match (the \"cards\"  -->\n<!-- in true cardsort terminology.  Note that potential distractors -->\n<!-- are a premise with no response (empty sub-list) and a response -->\n<!-- with no premise (a premise that is null-ish).                  -->\n<xsl:template match=\"cardsort\" mode=\"cardsort-matching-solution\">\n    <p><ul>\n        <xsl:for-each select=\"match\">\n            <li>\n                <p>\n                    <xsl:choose>\n                        <xsl:when test=\"response\">\n                            <xsl:copy-of select=\"response\"/>\n                        </xsl:when>\n                        <xsl:otherwise>\n                            <xsl:text>(</xsl:text>\n                            <xsl:element name=\"pi:localize\">\n                                <xsl:attribute name=\"string-id\">uncategorized</xsl:attribute>\n                            </xsl:element>\n                            <xsl:text>)</xsl:text>\n                        </xsl:otherwise>\n                    </xsl:choose>\n                    <xsl:if test=\"premise\">\n                        <ul>\n                            <xsl:for-each select=\"premise\">\n                                <li>\n                                    <xsl:copy-of select=\".\"/>\n                                </li>\n                            </xsl:for-each>\n                        </ul>\n                    </xsl:if>\n                </p>\n            </li>\n        </xsl:for-each>\n    </ul></p>\n</xsl:template>\n\n<!-- For a solution, we make an unordered list of the    -->\n<!-- responses (mirroring the cardsort organization) and -->\n<!-- for each we make a sub-list with the premises that. -->\n<!-- are matched.  Distractors are a premise with no     -->\n<!-- response (empty sub-list) and a response with no    -->\n<!-- premise (a premise that is null-ish).               S-->\n<xsl:template match=\"matching\" mode=\"cardsort-matching-solution\">\n    <p><ul>\n        <xsl:for-each select=\"response\">\n            <xsl:variable name=\"response-xmlid-fenced\" select=\"concat('|', @xml:id, '|')\"/>\n            <li>\n                <p>\n                    <xsl:copy-of select=\".\"/>\n                    <!-- form list items of matching premise -->\n                    <!-- this could be empty, so we not open -->\n                    <!-- a sub-list prematurely              -->\n                    <xsl:variable name=\"matched-premises-rtf\">\n                        <!-- context is a \"response\" step up to get \"permise\" -->\n                        <xsl:for-each select=\"parent::matching/premise\">\n                            <xsl:variable name=\"the-ref-fenced\" select=\"concat('|', translate(@ref, ' ', '|'), '|')\"/>\n                            <!-- the test for adjacency -->\n                            <xsl:if test=\"contains($the-ref-fenced, $response-xmlid-fenced)\">\n                                <li>\n                                    <xsl:copy-of select=\".\"/>\n                                </li>\n                            </xsl:if>\n                        </xsl:for-each>\n                    </xsl:variable>\n                    <xsl:variable name=\"matched-premises\" select=\"exsl:node-set($matched-premises-rtf)\"/>\n                    <!-- create a non-empty sublist of matched premise -->\n                    <xsl:if test=\"$matched-premises/li\">\n                        <ul>\n                            <xsl:copy-of select=\"$matched-premises\"/>\n                        </ul>\n                    </xsl:if>\n                </p>\n            </li>\n        </xsl:for-each>\n        <!-- And we need to catch premises that do not get   -->\n        <!-- matched to any response (through null-ish @ref) -->\n        <!-- NB: context is now the \"matching\"               -->\n        <xsl:variable name=\"unmatched-premises-rtf\">\n            <xsl:for-each select=\"premise\">\n                <xsl:if test=\"not(@ref) or (normalize-space(@ref) = '')\">\n                    <li>\n                        <xsl:copy-of select=\".\"/>\n                    </li>\n                </xsl:if>\n            </xsl:for-each>\n        </xsl:variable>\n        <xsl:variable name=\"unmatched-premises\" select=\"exsl:node-set($unmatched-premises-rtf)\"/>\n        <!-- Make a top-level list item \"uncategorized\" response,-->\n        <!-- and populate it with a sub-list of all the premise  -->\n        <!-- that do not get matched with anything               -->\n        <xsl:if test=\"$unmatched-premises/li\">\n            <li><p>\n                <xsl:text>(</xsl:text>\n                <xsl:element name=\"pi:localize\">\n                    <xsl:attribute name=\"string-id\">uncategorized</xsl:attribute>\n                </xsl:element>\n                <xsl:text>)</xsl:text>\n                <ul>\n                    <xsl:copy-of select=\"$unmatched-premises/li\"/>\n                </ul>\n            </p></li>\n        </xsl:if>\n    </ul></p>\n</xsl:template>\n\n\n<!-- Clickable Area -->\n\n<xsl:template match=\"*[@pi:exercise-interactive = 'clickablearea']\" mode=\"runestone-to-static\">\n    <!-- metadata (idx, title) -->\n    <xsl:copy-of select=\"statement/preceding-sibling::*\"/>\n    <!-- Statement -->\n    <statement>\n        <xsl:copy-of select=\"statement/node()\"/>\n        <xsl:apply-templates select=\"areas\" mode=\"static-areas\"/>\n    </statement>\n    <xsl:copy-of select=\"hint\"/>\n    <!-- Any authored answers, not derived from problem formulation. -->\n    <!-- *Before* automatic ones, so numbering matches interactive   -->\n    <!-- versions on authored ones.                                  -->\n    <xsl:copy-of select=\"answer\"/>\n    <answer>\n        <p>\n            <xsl:element name=\"pi:localize\">\n                <xsl:attribute name=\"string-id\">correct</xsl:attribute>\n            </xsl:element>\n            <xsl:text>: </xsl:text>\n            <xsl:for-each select=\"areas//area[not(@correct = 'no')]\">\n                <xsl:apply-templates select=\".\" mode=\"answer-areas\"/>\n                <xsl:if test=\"not(position() = last())\">\n                    <xsl:text>; </xsl:text>\n                </xsl:if>\n            </xsl:for-each>\n            <xsl:text>.</xsl:text>\n            <xsl:text> </xsl:text>\n            <xsl:element name=\"pi:localize\">\n                <xsl:attribute name=\"string-id\">incorrect</xsl:attribute>\n            </xsl:element>\n            <xsl:text>: </xsl:text>\n            <xsl:for-each select=\"areas//area[@correct = 'no']\">\n                <xsl:apply-templates select=\".\" mode=\"answer-areas\"/>\n                <xsl:if test=\"not(position() = last())\">\n                    <xsl:text>; </xsl:text>\n                </xsl:if>\n            </xsl:for-each>\n            <xsl:text>.</xsl:text>\n        </p>\n        <xsl:copy-of select=\"feedback/node()\"/>\n    </answer>\n    <!-- Any authored solutions, not derived from problem formulation. -->\n    <!-- *Before* automatic ones, so numbering matches interactive     -->\n    <!-- versions on authored ones.                                    -->\n    <xsl:copy-of select=\"solution\"/>\n    <!-- A text version can get markup of correct and incorrect areas    -->\n    <!-- (italics, strikethrough) but no good way to markup code easily. -->\n    <!-- So no \"solution\" for code versions.                             -->\n    <xsl:if test=\"not(areas/cline)\">\n        <solution>\n            <xsl:apply-templates select=\"areas/node()\" mode=\"solution-areas\"/>\n        </solution>\n    </xsl:if>\n</xsl:template>\n\n<!-- We do a xerox'ing pass to construct the problem. -->\n<!--   (1) \"area\" gets dropped (invisible in static)  -->\n<!--       [could italicize correct and incorrect?]   -->\n<!--   (2) \"cline\" get reconstructed as a \"program\"   -->\n\n<xsl:template match=\"node()|@*\" mode=\"static-areas\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"static-areas\"/>\n    </xsl:copy>\n</xsl:template>\n\n<xsl:template match=\"areas\" mode=\"static-areas\">\n    <xsl:choose>\n        <xsl:when test=\"cline\">\n            <!-- code, so make a \"program\" structure -->\n            <program>\n                <xsl:attribute name=\"language\">\n                    <xsl:apply-templates select=\".\" mode=\"get-programming-language\"/>\n                </xsl:attribute>\n                <input>\n                    <xsl:apply-templates select=\"cline\" mode=\"static-areas\"/>\n                </input>\n            </program>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- regular text, this will match a default template later -->\n            <xsl:apply-templates select=\"*\" mode=\"static-areas\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template match=\"areas/cline\" mode=\"static-areas\">\n    <xsl:apply-templates select=\"text()|area\" mode=\"static-areas\"/>\n    <xsl:text>&#xa;</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"cline/text()\" mode=\"static-areas\">\n    <xsl:value-of select=\".\"/>\n</xsl:template>\n\n<!-- NB: don't apply to attributes of an \"area\" (just @correct) -->\n<xsl:template match=\"area\" mode=\"static-areas\">\n    <xsl:apply-templates select=\"node()\" mode=\"static-areas\"/>\n</xsl:template>\n\n<!-- Modal templates reproduce answers, which could have some  -->\n<!-- markup in them?  We enter here at each \"area\" to form the -->\n<!-- lists of correct and incorrect areas.                     -->\n\n<xsl:template match=\"node()|@*\" mode=\"answer-areas\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"answer-areas\"/>\n    </xsl:copy>\n</xsl:template>\n\n<xsl:template match=\"area[parent::cline]\" mode=\"answer-areas\">\n    <c>\n        <!-- NB: don't xerox attributes of an \"area\" (just @correct) -->\n        <xsl:apply-templates select=\"node()\" mode=\"answer-areas\"/>\n    </c>\n</xsl:template>\n\n<xsl:template match=\"area[not(parent::cline) and not(@correct = 'no')]\" mode=\"answer-areas\">\n    <em>\n        <!-- NB: don't xerox attributes of an \"area\" (just @correct) -->\n        <xsl:apply-templates select=\"node()\" mode=\"answer-areas\"/>\n    </em>\n</xsl:template>\n\n<xsl:template match=\"area[not(parent::cline) and (@correct = 'no')]\" mode=\"answer-areas\">\n    <delete>\n        <!-- NB: don't xerox attributes of an \"area\" (just @correct) -->\n        <xsl:apply-templates select=\"node()\" mode=\"answer-areas\"/>\n    </delete>\n</xsl:template>\n\n<!-- protect from low-level routines in -common -->\n<xsl:template match=\"cline/area/text()\" mode=\"answer-areas\">\n    <xsl:value-of select=\".\"/>\n</xsl:template>\n\n<!-- For a text version (only, not a code version) we xerox -->\n<!-- the contents of \"areas\" and slide-in some highlighting -->\n<!-- of the correct and incorrect \"area\".                   -->\n\n<xsl:template match=\"node()|@*\" mode=\"solution-areas\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"solution-areas\"/>\n    </xsl:copy>\n</xsl:template>\n\n<xsl:template match=\"area[not(@correct = 'no')]\" mode=\"solution-areas\">\n    <em>\n        <!-- NB: don't xerox attributes of an \"area\" (just @correct) -->\n        <xsl:apply-templates select=\"node()\" mode=\"solution-areas\"/>\n    </em>\n</xsl:template>\n\n<xsl:template match=\"area[@correct = 'no']\" mode=\"solution-areas\">\n    <delete>\n        <!-- NB: don't xerox attributes of an \"area\" (just @correct) -->\n        <xsl:apply-templates select=\"node()\" mode=\"solution-areas\"/>\n    </delete>\n</xsl:template>\n\n\n<!-- Select -->\n\n<xsl:template match=\"*[@pi:exercise-interactive = 'select']\" mode=\"runestone-to-static\">\n    <!-- metadata (idx, title) -->\n    <xsl:copy-of select=\"select/preceding-sibling::*\"/>\n\n    <!-- identify the type of \"select\"                    -->\n    <!-- duplicated in \"pretext-runestone.xsl\"            -->\n    <!-- No good place to put this, since static versions -->\n    <!-- are forned in assembly phase and we do not want  -->\n    <!-- to introduce too many templates there.           -->\n    <!-- Save off which type, since context is lost looping over refs -->\n    <xsl:variable name=\"select-variant\">\n        <xsl:choose>\n            <!-- Runestone JS picks a random problem from many-->\n            <xsl:when test=\"select/@grade='random'\">\n                <xsl:text>random</xsl:text>\n            </xsl:when>\n            <!-- Two questions, split across roster into A, B groups. -->\n            <xsl:when test=\"select/@grade='ab-experiment'\">\n                <xsl:text>ab-experiment</xsl:text>\n            </xsl:when>\n            <!-- Two questions (usually), the first will always be graded,  -->\n            <!-- while any others may be worked and may be helpful.         -->\n            <!-- Colloquially known as a \"toggle lock\" question.            -->\n            <xsl:when test=\"select/@grade='first'\">\n                <xsl:text>first</xsl:text>\n            </xsl:when>\n            <!-- Two questions (usually), any one may be     -->\n            <!-- chosen by the reader to be graded.          -->\n            <!-- Colloquially known as a \"toggle \" question. -->\n            <xsl:when test=\"select/@grade='any'\">\n                <xsl:text>any</xsl:text>\n            </xsl:when>\n            <!-- default to \"random\" selection -->\n            <xsl:otherwise>\n                <xsl:text>random</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- One simple sentence in a \"p\", typically presented -->\n    <!-- just after a lead-in title from \"exercise\"        -->\n    <p>\n        <!-- some lead-in explanation -->\n        <xsl:text>Runestone-only: </xsl:text>\n        <xsl:choose>\n            <xsl:when test=\"$select-variant = 'random'\">\n                <xsl:text>exercise to grade will be automatically chosen by Runestone from </xsl:text>\n            </xsl:when>\n            <xsl:when test=\"$select-variant = 'ab-experiment'\">\n                <xsl:text>an A/B experiment (named </xsl:text>\n                    <c>\n                        <xsl:value-of select=\"select/@experiment-name\"/>\n                    </c>\n                <xsl:text>) with </xsl:text>\n            </xsl:when>\n            <xsl:when test=\"$select-variant = 'first'\">\n                <xsl:text>a toggle question where the question graded is </xsl:text>\n                <em>always</em>\n                <xsl:text> the first of </xsl:text>\n            </xsl:when>\n            <xsl:when test=\"$select-variant = 'any'\">\n                <xsl:text>a toggle question where the question graded is </xsl:text>\n                <em>any</em>\n                <xsl:text> question chosen by the reader from </xsl:text>\n            </xsl:when>\n        </xsl:choose>\n        <!-- list \"xref\" to questions -->\n        <xsl:for-each select=\"str:tokenize(select/@questions, ' ,')\">\n            <!-- cross-reference, will be in default document style -->\n            <xref>\n                <xsl:attribute name=\"ref\">\n                    <xsl:value-of select=\".\"/>\n                </xsl:attribute>\n            </xref>\n            <!-- punctuation -->\n            <xsl:choose>\n                <xsl:when test=\"not($select-variant = 'ab-experiment')\">\n                    <xsl:choose>\n                        <!-- penultimate; trailing comma, plus \"or\" -->\n                        <xsl:when test=\"count(following-sibling::token) = 1\">\n                            <xsl:text>, or </xsl:text>\n                        </xsl:when>\n                        <!-- more, more coming; trailing comma -->\n                        <xsl:when test=\"following-sibling::token\">\n                            <xsl:text>, </xsl:text>\n                        </xsl:when>\n                        <!-- done; need final period -->\n                        <xsl:otherwise>\n                            <xsl:text>.</xsl:text>\n                        </xsl:otherwise>\n                    </xsl:choose>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:choose>\n                        <!-- finish \"A\", and separate from \"B\" -->\n                        <xsl:when test=\"following-sibling::token\">\n                            <xsl:text> as (A)</xsl:text>\n                            <xsl:text> and </xsl:text>\n                        </xsl:when>\n                        <!-- final period -->\n                        <xsl:otherwise>\n                            <xsl:text> as (B).</xsl:text>\n                        </xsl:otherwise>\n                    </xsl:choose>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:for-each>\n    </p>\n</xsl:template>\n\n\n<!-- Fill-In the Blanks (Basic) -->\n\n<xsl:template match=\"*[@pi:exercise-interactive = 'fillin-basic']\" mode=\"runestone-to-static\">\n    <!-- metadata (idx, title) -->\n    <xsl:copy-of select=\"statement/preceding-sibling::*\"/>\n    <!-- reproduce statement identically, but replace var w/ fillin -->\n    <xsl:apply-templates select=\"statement\" mode=\"fillin-statement\"/>\n    <!-- Any authored hints, answers, solutions, not derived from   -->\n    <!-- problem formulation. *Before* automatic ones, so numbering -->\n    <!-- matches interactive versions on authored ones.             -->\n    <xsl:copy-of select=\"hint\"/>\n    <xsl:copy-of select=\"answer\"/>\n    <xsl:copy-of select=\"solution\"/>\n    <xsl:apply-templates select=\"statement\" mode=\"fillin-solution\"/>\n</xsl:template>\n\n<!-- Fillin Statement -->\n<xsl:template match=\"node()|@*\" mode=\"fillin-statement\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"fillin-statement\"/>\n    </xsl:copy>\n</xsl:template>\n\n<xsl:template match=\"var\" mode=\"fillin-statement\">\n    <fillin>\n        <xsl:attribute name=\"characters\">\n            <xsl:choose>\n                <xsl:when test=\"@width\">\n                    <xsl:value-of select=\"@width\"/>\n                </xsl:when>\n                <xsl:otherwise>\n                    <!-- arbitrary default width -->\n                    <xsl:text>5</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:attribute>\n    </fillin>\n</xsl:template>\n\n<!-- Fillin complete solution -->\n\n<xsl:template match=\"node()|@*\" mode=\"fillin-solution\">\n    <xsl:copy>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"fillin-solution\"/>\n    </xsl:copy>\n</xsl:template>\n\n<!-- Don't duplicate xml:id. Nobody should point into the solution. -->\n<!-- Note that any internal link references will point to the original not the copy -->\n<xsl:template match=\"@xml:id\" mode=\"fillin-solution\"/>\n\n<!-- Append to a label -->\n<xsl:template match=\"@label\" mode=\"fillin-solution\">\n    <xsl:attribute name=\"label\">\n        <xsl:value-of select=\".\"/>\n        <xsl:text>-fitb-solution</xsl:text>\n    </xsl:attribute>\n</xsl:template>\n\n<xsl:template match=\"statement\" mode=\"fillin-solution\">\n    <xsl:variable name=\"exercise\" select=\"..\"/>\n    <xsl:variable name=\"ordered-evaluates\" select=\"$exercise/evaluation/evaluate[not(@all = 'yes')]\"/>\n    <solution>\n        <xsl:apply-templates select=\"node()|@*\" mode=\"fillin-solution\"/>\n        <!-- xerox feedback for correct response on each var -->\n        <xsl:for-each select=\"../setup/var/condition[1]/feedback\">\n            <xsl:apply-templates select=\"node()\" mode=\"fillin-solution\"/>\n        </xsl:for-each>\n        <xsl:for-each select=\".//fillin\">\n            <xsl:variable name=\"fillin-name\" select=\"@name\"/>\n            <xsl:variable name=\"fillin-pos\" select=\"position()\"/>\n            <xsl:variable name=\"named-evaluate\" select=\"$exercise/evaluation/evaluate[@name = $fillin-name]\"/>\n            <xsl:variable name=\"ordered-evaluate\" select=\"$ordered-evaluates[position() = $fillin-pos]\"/>\n            <xsl:choose>\n                <!-- If #evaluate matches by name, find feedback on a correct result -->\n                <xsl:when test=\"$named-evaluate/test[@correct = 'yes']\">\n                    <xsl:apply-templates select=\"$named-evaluate/test[@correct = 'yes']/feedback/node()\" mode=\"fillin-solution\"/>\n                </xsl:when>\n                <!-- Otherwise #evaluate matches by order, find feedback on a correct result -->\n                <xsl:when test=\"$ordered-evaluate/test[@correct = 'yes']\">\n                    <xsl:apply-templates select=\"$ordered-evaluate/test[@correct = 'yes']/feedback/node()\" mode=\"fillin-solution\"/>\n                </xsl:when>\n            </xsl:choose>\n        </xsl:for-each>\n        <xsl:if test=\"../evaluation[@answers-coupled='yes']\">\n            <xsl:apply-templates select=\"$exercise/evaluation/evaluate[@all='yes']/test[@correct='yes']/feedback/node()\" mode=\"fillin-solution\"/>\n        </xsl:if>\n    </solution>\n</xsl:template>\n\n<xsl:template match=\"var\" mode=\"fillin-solution\">\n    <!-- NB: this code is used in formulating HTML representations -->\n    <!-- count location of (context) \"var\" in problem statement    -->\n    <xsl:variable name=\"location\">\n        <xsl:number from=\"statement\"/>\n    </xsl:variable>\n    <!-- locate corresponding \"var\" in \"setup\" -->\n    <xsl:variable name=\"setup-var\" select=\"ancestor::exercise/setup/var[position() = $location]\"/>\n\n    <!-- Know can tell what the correct answer is, from first \"condition\"-->\n    <fillin characters=\"1\"/>\n    <xsl:choose>\n        <xsl:when test=\"$setup-var/condition[1]/@number\">\n            <m>\n                <xsl:value-of select=\"$setup-var/condition[1]/@number\"/>\n            </m>\n        </xsl:when>\n        <xsl:when test=\"$setup-var/condition[1]/@string\">\n            <xsl:value-of select=\"$setup-var/condition[1]/@string\"/>\n        </xsl:when>\n    </xsl:choose>\n    <fillin characters=\"1\"/>\n</xsl:template>\n\n<!-- Fill-In the Blanks (Complete) -->\n\n<xsl:template match=\"*[@pi:exercise-interactive = 'fillin']\" mode=\"runestone-to-static\">\n    <!-- metadata (idx, title) -->\n    <xsl:copy-of select=\"statement/preceding-sibling::*\"/>\n    <!-- reproduce statement identically, but replace var w/ fillin -->\n    <xsl:apply-templates select=\"statement\" mode=\"fillin-statement\"/>\n    <!-- Any authored hints, answers, solutions, not derived from   -->\n    <!-- problem formulation. *Before* automatic ones, so numbering -->\n    <!-- matches interactive versions on authored ones.             -->\n    <xsl:copy-of select=\"hint\"/>\n    <xsl:copy-of select=\"answer\"/>\n    <xsl:choose>\n        <xsl:when test=\"solution[@include-automatic='no']\">\n            <xsl:copy-of select=\"solution\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\"statement\" mode=\"fillin-solution\"/>\n            <xsl:copy-of select=\"solution\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Fillin Statement -->\n<xsl:template match=\"fillin\" mode=\"fillin-statement\">\n    <fillin>\n        <xsl:attribute name=\"characters\">\n            <xsl:choose>\n                <xsl:when test=\"@width\">\n                    <xsl:value-of select=\"@width\"/>\n                </xsl:when>\n                <xsl:otherwise>\n                    <!-- arbitrary default width -->\n                    <xsl:text>5</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:attribute>\n    </fillin>\n</xsl:template>\n\n<!-- Fillin complete solution -->\n<xsl:template match=\"fillin\" mode=\"fillin-solution\">\n    <!-- Correct answer is in @answer. -->\n    <fillin characters=\"1\"/>\n    <xsl:choose>\n        <xsl:when test=\"@mode='math' or @mode='number'\">\n            <m><xsl:value-of select=\"@answer\"/></m>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"@answer\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n    <fillin characters=\"1\"/>\n</xsl:template>\n\n<!-- Short Answer -->\n\n<!-- Authored with a \"response\" element, we effectively drop it here -->\n<xsl:template match=\"*[@pi:exercise-interactive = 'shortanswer']\" mode=\"runestone-to-static\">\n    <!-- metadata (idx, title) -->\n    <xsl:copy-of select=\"statement/preceding-sibling::*\"/>\n    <!-- reproduce usual components -->\n    <xsl:copy-of select=\"statement\"/>\n    <!-- skip over response until it carries something relevant -->\n    <xsl:copy-of select=\"hint\"/>\n    <xsl:copy-of select=\"answer\"/>\n    <xsl:copy-of select=\"solution\"/>\n</xsl:template>\n\n<!-- Queries -->\n\n<xsl:template match=\"query\" mode=\"runestone-to-static\">\n    <paragraphs>\n        <!-- no period, it is supplied by conversions -->\n        <title>\n            <xsl:element name=\"pi:localize\">\n                <xsl:attribute name=\"string-id\">query</xsl:attribute>\n            </xsl:element>\n        </title>\n        <!-- reproduce structured statement's pieces -->\n        <xsl:copy-of select=\"statement/*\"/>\n        <xsl:choose>\n            <xsl:when test=\"choices\">\n                <p><ol format=\"1.\">\n                    <xsl:for-each select=\"choices/choice\">\n                        <li>\n                            <xsl:copy-of select=\".\"/>\n                        </li>\n                    </xsl:for-each>\n                </ol></p>\n            </xsl:when>\n            <xsl:when test=\"@scale\">\n                <!-- A pre-formatted \"display\" of the integer choices, -->\n                <!-- which could be printed and circled by the reader. -->\n                <pre>\n                    <xsl:apply-templates select=\".\" mode=\"scale-choices\"/>\n                </pre>\n            </xsl:when>\n            <xsl:otherwise/>\n        </xsl:choose>\n    </paragraphs>\n</xsl:template>\n\n<!-- Recursively count-up and layout choices with rows of -->\n<!-- 10 choices each, with blank lines between the rows.  -->\n<xsl:template match=\"query\" mode=\"scale-choices\">\n    <xsl:param name=\"the-choice\" select=\"'1'\"/>\n\n    <xsl:choose>\n        <!-- Done.  Emit and that's it -->\n        <xsl:when test=\"$the-choice = ./@scale\">\n            <xsl:value-of select=\"$the-choice\"/>\n        </xsl:when>\n        <!-- Done with a row, but not done.  Newline, and blankline. -->\n        <xsl:when test=\"$the-choice mod 10 = 0\">\n            <xsl:value-of select=\"$the-choice\"/>\n            <xsl:text>&#xa;&#xa;</xsl:text>\n            <xsl:apply-templates select=\".\" mode=\"scale-choices\">\n                <xsl:with-param name=\"the-choice\" select=\"$the-choice + 1\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <!-- Mid-row, use two spaces to separate. -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$the-choice\"/>\n            <xsl:text>&#x20;&#x20;</xsl:text>\n            <xsl:apply-templates select=\".\" mode=\"scale-choices\">\n                <xsl:with-param name=\"the-choice\" select=\"$the-choice + 1\"/>\n            </xsl:apply-templates>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- Active Code -->\n\n<xsl:template match=\"*[@pi:exercise-interactive = 'coding']\" mode=\"runestone-to-static\">\n    <!-- metadata (idx, title) -->\n    <xsl:copy-of select=\"statement/preceding-sibling::*\"/>\n    <statement>\n        <!-- duplicate the authored prompt/statement -->\n        <xsl:copy-of select=\"statement/node()\"/>\n        <!-- Bring up the program as part of the problem statement and -->\n        <!-- also neuter any @interactive indication.  This was not    -->\n        <!-- tagged as a coding exercise without a \"program\" outside   -->\n        <!-- the \"statement\", but we are careful about not making an   -->\n        <!-- empty \"program\" where there is none.                      -->\n        <xsl:if test=\"program\">\n            <xsl:element name=\"program\">\n                <xsl:copy-of select=\"program/@*[not(name() = 'interactive')]\"/>\n                <xsl:copy-of select=\"program/node()\"/>\n            </xsl:element>\n        </xsl:if>\n    </statement>\n    <xsl:copy-of select=\"hint\"/>\n    <xsl:copy-of select=\"answer\"/>\n    <xsl:copy-of select=\"solution\"/>\n</xsl:template>\n\n\n<xsl:template match=\"datafile\" mode=\"runestone-to-static\">\n    <!-- Some templates and variables are defined in -common for consistency -->\n\n    <!-- Mostly the data file is a \"pre\", or an \"image\", but we -->\n    <!-- want to have a title of sorts indicating the filename. -->\n    <!-- To accomplish an overall element that won't disrupt    -->\n    <!-- subsequent automatic ids, we do a bit of a hack: a     -->\n    <!-- \"sidebyside\" as the overall element with a \"stack\".    -->\n    <sidebyside>\n        <stack>\n            <!-- faux title -->\n            <p>\n                <xsl:element name=\"pi:localize\">\n                    <xsl:attribute name=\"string-id\">data</xsl:attribute>\n                </xsl:element>\n                <xsl:text>: </xsl:text>\n                <c>\n                    <xsl:value-of select=\"@filename\"/>\n                </c>\n            </p>\n            <!-- image or code, one panel -->\n            <xsl:choose>\n                <xsl:when test=\"image\">\n                    <xsl:copy-of select=\"image\"/>\n                </xsl:when>\n                <xsl:when test=\"pre\">\n                    <!-- provide default rows and cols, sync with dynamic version -->\n                    <xsl:variable name=\"desired-rows\">\n                        <xsl:choose>\n                            <xsl:when test=\"@rows\">\n                                <xsl:value-of select=\"@rows\"/>\n                            </xsl:when>\n                            <xsl:otherwise>\n                                <xsl:value-of select=\"$datafile-default-rows\"/>\n                            </xsl:otherwise>\n                        </xsl:choose>\n                    </xsl:variable>\n                    <xsl:variable name=\"desired-cols\">\n                        <xsl:choose>\n                            <xsl:when test=\"@cols\">\n                                <xsl:value-of select=\"@cols\"/>\n                            </xsl:when>\n                            <xsl:otherwise>\n                                <xsl:value-of select=\"$datafile-default-cols\"/>\n                            </xsl:otherwise>\n                        </xsl:choose>\n                    </xsl:variable>\n                    <pre>\n                        <!-- form an \"upper-left-corner\" view -->\n                        <xsl:call-template name=\"text-viewport\">\n                            <xsl:with-param name=\"nrows\" select=\"$desired-rows\"/>\n                            <xsl:with-param name=\"ncols\" select=\"$desired-cols\"/>\n                            <xsl:with-param name=\"text\">\n                                <!-- defined in -common -->\n                                <xsl:apply-templates select=\".\" mode=\"datafile-text-contents\"/>\n                            </xsl:with-param>\n                        </xsl:call-template>\n                    </pre>\n                </xsl:when>\n                <!-- no other source/PTX element is supported , bail out-->\n                <xsl:otherwise/>\n            </xsl:choose>\n        </stack>\n    </sidebyside>\n</xsl:template>\n\n</xsl:stylesheet>\n","pretext-runestone.xsl":"<?xml version='1.0'?> <!-- As XML file -->\n\n<!--********************************************************************\nCopyright (C) 2022-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- http://pimpmyxslt.com/articles/entity-tricks-part2/ -->\n<!DOCTYPE xsl:stylesheet [\n    <!ENTITY % entities SYSTEM \"entities.ent\">\n    %entities;\n]>\n\n<!-- exsl: necessary to write out Runestone manifest -->\n<!-- str: necessary to tokenize alternate Runestone Services -->\n\n<xsl:stylesheet\n    xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\"\n    xmlns:xml=\"http://www.w3.org/XML/1998/namespace\"\n    xmlns:pi=\"http://pretextbook.org/2020/pretext/internal\"\n    xmlns:exsl=\"http://exslt.org/common\"\n    xmlns:str=\"http://exslt.org/strings\"\n    extension-element-prefixes=\"exsl str pi\"\n>\n\n<!-- ######################## -->\n<!-- Runestone Infrastructure -->\n<!-- ######################## -->\n\n<!-- Runestone Services -->\n<!-- Runestone provides universally-applicable Javascript, and since Brad Miller -->\n<!-- is \"such a nice guy\" he provides an XML version of the necessary files.     -->\n<!-- These are obtained/created/analyzed in the Python script. The structure     -->\n<!-- of this file is pretty simple, and should be apparent to the cognescenti.   -->\n\n<!-- The content of the services file  is provided via                 -->\n<!-- string parameters passed into this stylesheet. The purpose is to  -->\n<!-- allow the core Python routines to query the Runestone server for  -->\n<!-- the *very latest* services file available online. This is meant   -->\n<!-- to be a totally automated operation, so parameter names are not   -->\n<!-- always human-friendly.  Sometimes these parameters are provided   -->\n<!-- from alternate sources due to some debugging mode being employed. -->\n<!-- See the Python script for more detail.                            -->\n<xsl:param name=\"rs-js\" select=\"''\"/>\n<xsl:param name=\"rs-css\" select=\"''\"/>\n<xsl:param name=\"rs-version\" select=\"''\"/>\n\n<xsl:param name=\"godot.shell\" select=\"'https://runestone.academy/cdn/runestone/godot-shell-'\"/>\n\n<!-- The Runestone Services version actually in use is -->\n<!-- needed several places, so we compute it once now. -->\n<!-- Manifest, two \"ebookConfig\".                      -->\n<xsl:variable name=\"runestone-version\">\n    <xsl:value-of select=\"$rs-version\"/>\n</xsl:variable>\n\n<!-- The Runestone platform option requires output that can be used  -->\n<!-- on the server with a templating language/tool.  For books       -->\n<!-- originating from PreTeXt we use a non-default pair of strings.  -->\n<!-- This is because the default is {{, }} and these behave poorly   -->\n<!-- in  a/@href  output, since the outer pair looks like an XSL AVT -->\n<!-- and then the inner pair gets escaped as a reserved character in -->\n<!-- a URI.  (We can turn off URI-escaping with XSLT 2.0, but the    -->\n<!-- AVT confusion may still be a problem.)                          -->\n\n<!-- These are used two places, so defined globally, not  -->\n<!-- conditionally.  Due to their ubiquity in these two   -->\n<!-- concentrated locations, the variable names are       -->\n<!-- intentionally cryptic, contrary to usual practice.   -->\n<!-- rs = Runestone, o = open, c = close.                 -->\n\n<xsl:variable name=\"rso\" select=\"'~._'\"/>\n<xsl:variable name=\"rsc\" select=\"'_.~'\"/>\n\n<!-- Determines the base url of a book served on Runestone  -->\n<!-- If there is an authored base url, use it as the author -->\n<!-- may be targetting a non-public server. Otherwise,      -->\n<!-- assume book is hosted on Runestone Academy             -->\n<xsl:template name=\"runestone-server-baseurl\">\n    <xsl:choose>\n        <xsl:when test=\"$b-has-baseurl\">\n            <xsl:value-of select=\"$baseurl\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>https://runestone.academy/ns/books/published/</xsl:text>\n            <xsl:value-of select=\"$document-id\"/>\n            <xsl:text>/</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Runestone Services (Javascript)  -->\n<!-- OR, Hosting at Runestone Academy -->\n<xsl:template name=\"runestone-header\">\n    <!-- Runestone templating for customizing hosted books   -->\n    <!-- no Sphinx {% %} templating for build system at all, -->\n    <!-- conditional on $b-host-runestone                    -->\n    <!-- 'true'  - hosted on a Runestone server,             -->\n    <!--           {{ }} templating replaced by $rso, $rsc   -->\n    <!-- 'false' - local viewing, no server,                 -->\n    <!--           just Runestone Services, so dummy values  -->\n    <xsl:choose>\n        <!-- Runestone Server build -->\n        <xsl:when test=\"$b-host-runestone\">\n            <script type=\"text/javascript\">\n                <xsl:text>&#xa;</xsl:text>\n                <xsl:text>eBookConfig = {};&#xa;</xsl:text>\n                <xsl:text>eBookConfig.useRunestoneServices = true;&#xa;</xsl:text>\n                <xsl:text>eBookConfig.host = '';&#xa;</xsl:text>\n                <xsl:text>eBookConfig.app = eBookConfig.host + '/runestone';&#xa;</xsl:text>\n                <xsl:text>eBookConfig.course = '</xsl:text><xsl:value-of select=\"$rso\"/><xsl:text> course_name </xsl:text><xsl:value-of select=\"$rsc\"/><xsl:text>';&#xa;</xsl:text>\n                <xsl:text>eBookConfig.termStartDate = '</xsl:text><xsl:value-of select=\"$rso\"/><xsl:text> term_start_date </xsl:text><xsl:value-of select=\"$rsc\"/><xsl:text>';&#xa;</xsl:text>\n                <xsl:text>eBookConfig.basecourse = '</xsl:text><xsl:value-of select=\"$rso\"/><xsl:text> base_course </xsl:text><xsl:value-of select=\"$rsc\"/><xsl:text>';&#xa;</xsl:text>\n                <xsl:text>eBookConfig.isLoggedIn = </xsl:text><xsl:value-of select=\"$rso\"/><xsl:text> is_logged_in|default('false') </xsl:text><xsl:value-of select=\"$rsc\"/><xsl:text>;&#xa;</xsl:text>\n                <xsl:text>eBookConfig.email = '</xsl:text><xsl:value-of select=\"$rso\"/><xsl:text> user_email </xsl:text><xsl:value-of select=\"$rsc\"/><xsl:text>';&#xa;</xsl:text>\n                <xsl:text>eBookConfig.isInstructor = </xsl:text><xsl:value-of select=\"$rso\"/><xsl:text> is_instructor|default('false') </xsl:text><xsl:value-of select=\"$rsc\"/><xsl:text>;&#xa;</xsl:text>\n                <xsl:text>eBookConfig.logLevel = 10;&#xa;</xsl:text>\n                <xsl:text>eBookConfig.ajaxURL = eBookConfig.app + \"/ajax/\";&#xa;</xsl:text>\n                <!-- no .loglevel -->\n                <xsl:text>eBookConfig.username = '</xsl:text><xsl:value-of select=\"$rso\"/><xsl:text> user_id </xsl:text><xsl:value-of select=\"$rsc\"/><xsl:text>';&#xa;</xsl:text>\n                <xsl:text>eBookConfig.readings = </xsl:text><xsl:value-of select=\"$rso\"/><xsl:text> readings|default([])|safe </xsl:text><xsl:value-of select=\"$rsc\"/><xsl:text>;&#xa;</xsl:text>\n                <xsl:text>eBookConfig.activities = </xsl:text><xsl:value-of select=\"$rso\"/><xsl:text> activity_info|default({})|safe </xsl:text><xsl:value-of select=\"$rsc\"/><xsl:text>;&#xa;</xsl:text>\n                <xsl:text>eBookConfig.downloadsEnabled = </xsl:text><xsl:value-of select=\"$rso\"/><xsl:text> downloads_enabled|default('false') </xsl:text><xsl:value-of select=\"$rsc\"/><xsl:text>;&#xa;</xsl:text>\n                <xsl:text>eBookConfig.allow_pairs = </xsl:text><xsl:value-of select=\"$rso\"/><xsl:text> allow_pairs|default('false') </xsl:text><xsl:value-of select=\"$rsc\"/><xsl:text>;&#xa;</xsl:text>\n                <xsl:text>eBookConfig.course_attrs = </xsl:text><xsl:value-of select=\"$rso\"/><xsl:text> course_attrs|default({})|tojson|safe </xsl:text><xsl:value-of select=\"$rsc\"/><xsl:text>;&#xa;</xsl:text>\n                <!-- Scratch ActiveCode windows are a publisher option -->\n                <xsl:text>eBookConfig.enableScratchAC = </xsl:text>\n                <xsl:choose>\n                    <xsl:when test=\"$b-has-scratch-activecode\">\n                        <xsl:text>true</xsl:text>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:text>false</xsl:text>\n                    </xsl:otherwise>\n                </xsl:choose>\n                <xsl:text>;&#xa;</xsl:text>\n                <!-- And set the language when scratch ActiveCode is enabled -->\n                <xsl:if test=\"$b-has-scratch-activecode\">\n                    <xsl:text>eBookConfig.acDefaultLanguage = '</xsl:text>\n                    <xsl:value-of select=\"$html-scratch-activecode-language\"/>\n                    <xsl:text>';&#xa;</xsl:text>\n                </xsl:if>\n                <!-- end Scratch ActiveCode windows -->\n                <xsl:text>eBookConfig.new_server_prefix = \"/ns\";&#xa;</xsl:text>\n                <xsl:text>eBookConfig.runestone_version = '</xsl:text>\n                <xsl:value-of select=\"$runestone-version\"/>\n                <xsl:text>';&#xa;</xsl:text>\n                <!-- no .build_info -->\n                <!-- no .python3 -->\n                <!-- no .jobehost -->\n                <!-- no .proxyuri_runs -->\n                <!-- no .proxyuri_files -->\n                <!-- no .enable_chatcodes -->\n            </script>\n            <xsl:text>&#xa;</xsl:text>\n\n            <!-- Ethical Ads: only on Runestone server, only visible in -->\n            <!-- *non-login* versions of books hosted at Runestone      -->\n            <script src=\"https://media.ethicalads.io/media/client/ethicalads.min.js\"/>\n\n        </xsl:when>\n        <!-- Runestone for All build -->\n        <!-- Hosted without a Runestone Server, just using Javascript -->\n        <xsl:when test=\"not($b-host-runestone)\">\n            <xsl:comment>** eBookCongig is necessary to configure interactive       **</xsl:comment><xsl:text>&#xa;</xsl:text>\n            <xsl:comment>** Runestone components to run locally in reader's browser **</xsl:comment><xsl:text>&#xa;</xsl:text>\n            <xsl:comment>** No external communication:                              **</xsl:comment><xsl:text>&#xa;</xsl:text>\n            <xsl:comment>**     log level is 0, Runestone Services are disabled     **</xsl:comment><xsl:text>&#xa;</xsl:text>\n            <script type=\"text/javascript\">\n                <xsl:text>&#xa;</xsl:text>\n                <xsl:text>eBookConfig = {};&#xa;</xsl:text>\n                <xsl:text>eBookConfig.useRunestoneServices = false;&#xa;</xsl:text>\n                <xsl:text>eBookConfig.host = 'http://127.0.0.1:8000';&#xa;</xsl:text>\n                <!-- no .app -->\n                <!-- scratch Active Code fails if these faux strings have spaces or colons -->\n                <xsl:text>eBookConfig.course = 'PTX_Course_Title_Here';&#xa;</xsl:text>\n                <xsl:text>eBookConfig.basecourse = 'PTX_Base_Course';&#xa;</xsl:text>\n                <xsl:text>eBookConfig.isLoggedIn = false;&#xa;</xsl:text>\n                <xsl:text>eBookConfig.email = '';&#xa;</xsl:text>\n                <xsl:text>eBookConfig.isInstructor = false;&#xa;</xsl:text>\n                <!-- no .ajaxURL since no .app -->\n                <xsl:text>eBookConfig.logLevel = 0;&#xa;</xsl:text>\n                <xsl:text>eBookConfig.username = '';&#xa;</xsl:text>\n                <xsl:text>eBookConfig.readings = null;&#xa;</xsl:text>\n                <xsl:text>eBookConfig.activities = null;&#xa;</xsl:text>\n                <xsl:text>eBookConfig.downloadsEnabled = false;&#xa;</xsl:text>\n                <xsl:text>eBookConfig.allow_pairs = false;&#xa;</xsl:text>\n                <!-- Scratch ActiveCode windows are a publisher option -->\n                <xsl:text>eBookConfig.enableScratchAC = </xsl:text>\n                <xsl:choose>\n                    <xsl:when test=\"$b-has-scratch-activecode\">\n                        <xsl:text>true</xsl:text>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:text>false</xsl:text>\n                    </xsl:otherwise>\n                </xsl:choose>\n                <xsl:text>;&#xa;</xsl:text>\n                <!-- And set the language when scratch ActiveCode is enabled -->\n                <xsl:if test=\"$b-has-scratch-activecode\">\n                    <xsl:text>eBookConfig.acDefaultLanguage = '</xsl:text>\n                    <xsl:value-of select=\"$html-scratch-activecode-language\"/>\n                    <xsl:text>';&#xa;</xsl:text>\n                </xsl:if>\n                <!-- end Scratch ActiveCode windows -->\n                <xsl:text>eBookConfig.build_info = \"\";&#xa;</xsl:text>\n                <xsl:text>eBookConfig.python3 = null;&#xa;</xsl:text>\n                <xsl:text>eBookConfig.runestone_version = '</xsl:text>\n                <xsl:value-of select=\"$runestone-version\"/>\n                <xsl:text>';&#xa;</xsl:text>\n                <xsl:text>eBookConfig.jobehost = '';&#xa;</xsl:text>\n                <xsl:text>eBookConfig.proxyuri_runs = '';&#xa;</xsl:text>\n                <xsl:text>eBookConfig.proxyuri_files = '';&#xa;</xsl:text>\n                <xsl:text>eBookConfig.enable_chatcodes =  false;&#xa;</xsl:text>\n            </script>\n            <xsl:text>&#xa;</xsl:text>\n        </xsl:when>\n    </xsl:choose>\n\n    <!-- The Runestone Services file typically contains multiple filenames    -->\n    <!-- for Javascript and CSS (like two or three).                          -->\n    <!-- We expect the two string parameters to be lists delimited by a colon -->\n    <!-- (':'), so this character should not ever appear in the filenames.    -->\n    <!-- Note: these variables will be vacuous when the string parameters are -->\n    <!-- empty strings, and then will not ever be employed                    -->\n    <xsl:variable name=\"rs-js-tokens\" select=\"str:tokenize($rs-js, ':')\"/>\n    <xsl:variable name=\"rs-css-tokens\" select=\"str:tokenize($rs-css, ':')\"/>\n\n    <!-- Javascript and CSS \"master\" links/pointers into _static -->\n    <xsl:comment>*** Runestone Services ***</xsl:comment>\n    <xsl:text>&#xa;</xsl:text>\n    <xsl:for-each select=\"$rs-js-tokens\">\n        <script>\n            <xsl:attribute name=\"src\">\n                <xsl:value-of select=\"$cdn-prefix\"/>\n                <xsl:text>_static/</xsl:text>\n                <xsl:value-of select=\".\"/>\n            </xsl:attribute>\n        </script>\n    </xsl:for-each>\n    <xsl:for-each select=\"$rs-css-tokens\">\n        <link rel=\"stylesheet\" type=\"text/css\">\n            <xsl:attribute name=\"href\">\n                <xsl:value-of select=\"$cdn-prefix\"/>\n                <xsl:text>_static/</xsl:text>\n                <xsl:value-of select=\".\"/>\n            </xsl:attribute>\n        </link>\n    </xsl:for-each>\n</xsl:template>\n\n<!-- User Menu (aka Bust Menu)                    -->\n<!-- Conditional on a build for Runestone hosting -->\n<!-- \"template\" elements are not visible, ever,   -->\n<!-- but rather serve as a model for Javascript   -->\n\n<xsl:template name=\"runestone-bust-menu\">\n    <!-- \"Bust w/ Silhoutte\" is U+1F464, used as menu icon -->\n    <xsl:if test=\"$b-host-runestone\">\n        <xsl:variable name=\"profile-localization\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'profile'\"/>\n            </xsl:apply-templates>\n        </xsl:variable>\n        <!-- note: as of 6/20/2026, anchor positioning is not widely supported -->\n        <!-- when it becomes supported, would make sense to use popover API    -->\n        <button type=\"button\" id=\"ptx-user-dropdown-button\" class=\"runestone-profile button ptx-dropdown-button\" aria-haspopup=\"menu\" aria-controls=\"ptx-user-dropdown-content\" aria-expanded=\"false\" title=\"{$profile-localization}\">\n            <xsl:call-template name=\"insert-symbol\">\n                <xsl:with-param name=\"name\" select=\"'person'\"/>\n            </xsl:call-template>\n            <span class=\"name\">\n                <xsl:value-of select=\"$profile-localization\"/>\n            </span>\n        </button>\n        <div id=\"ptx-user-dropdown-content\" class=\"ptx-dropdown-content\" aria-labelledby=\"ptx-user-dropdown-button\" role=\"menu\">\n            <ul id=\"ptx-user-dropdown_rs-content\" role=\"group\" aria-label=\"Runestone\"></ul>\n        </div>\n        <!-- clone template, modify href and inner text, and append to ptx-user-dropdown_rs-content -->\n        <template id=\"ptx-user-dropdown-content_item-template\">\n            <li role=\"presentation\" class=\"ptx-dropdown-item\">\n                <a href=\"url here\" role=\"menuitem\">title here</a>\n            </li>\n        </template>\n        <!-- clone and append to dropdown content area and add a separator within the menu -->\n        <template id=\"ptx-user-dropdown-content_separator-template\">\n            <li role=\"presentation\" class=\"ptx-dropdown-separator\"></li>\n        </template>\n    </xsl:if>\n</xsl:template>\n\n<!-- Scratch ActiveCode window, for all builds (powered by Runestone   -->\n<!-- Javascript).  But more languages available on a Runestone server. -->\n<!-- Only if requested, explicitly or implicitly, via publisher file.  -->\n<!-- Unicode Character 'PENCIL' (U+270F)                               -->\n<xsl:template name=\"runestone-scratch-activecode\">\n    <xsl:if test=\"$b-has-scratch-activecode\">\n        <xsl:variable name=\"scratch-localization\">\n            <xsl:apply-templates select=\".\" mode=\"type-name\">\n                <xsl:with-param name=\"string-id\" select=\"'scratch-activecode'\"/>\n            </xsl:apply-templates>\n        </xsl:variable>\n        <button onclick=\"runestoneComponents.popupScratchAC()\" class=\"activecode-toggle button\" title=\"{$scratch-localization}\">\n            <xsl:call-template name=\"insert-symbol\">\n                <xsl:with-param name=\"name\" select=\"'edit'\"/>\n            </xsl:call-template>\n            <span class=\"name\">\n                <xsl:value-of select=\"$scratch-localization\"/>\n            </span>\n        </button>\n    </xsl:if>\n</xsl:template>\n\n<!-- A convenience for attaching a Runestone id -->\n<!-- NB: we attempt to only use this template in this stylesheet. -->\n<!-- To enforce this, we *could* make a no-op, plus warning,      -->\n<!-- template in the \"pretext-html\" stylesheet, with this         -->\n<!-- implementation doing an overide.                             -->\n<xsl:template match=\"exercise|program|datafile|query|&PROJECT-LIKE;|task|video[@youtube]|exercises|worksheet\" mode=\"runestone-id-attribute\">\n    <xsl:variable name=\"id\">\n        <xsl:apply-templates select=\".\" mode=\"runestone-id\"/>\n    </xsl:variable>\n    <xsl:if test=\"$id != ''\">\n        <xsl:attribute name=\"id\">\n              <xsl:value-of select=\"$id\"/>\n        </xsl:attribute>\n    </xsl:if>\n</xsl:template>\n\n<!-- ############### -->\n<!-- Runestone Hooks -->\n<!-- ############### -->\n\n<!-- Various additions/modifications to the HTML output, but which  -->\n<!-- we isolate here in this stylesheet for organizational reasons. -->\n\n<!-- A textual and visual progress indicator of completed activities  -->\n<!-- for a book hosted on a RS server, only.  At the RS \"subchapter\"  -->\n<!-- level, which we shortcut by checking for a chapter-level parent. -->\n<xsl:template match=\"&STRUCTURAL;\" mode=\"runestone-progress-indicator\">\n    <xsl:if test=\"$b-host-runestone and (parent::chapter or parent::appendix)\">\n        <div id=\"scprogresscontainer\">You have attempted <span id=\"scprogresstotal\"/> of <span id=\"scprogressposs\"/> activities on this page.<div id=\"subchapterprogress\" aria-label=\"Page progress\"/></div>\n    </xsl:if>\n</xsl:template>\n\n<!-- A timed exam requires markup that wraps an entire collection -->\n<!-- of exercises, so we pass the exercises in as a parameter     -->\n<xsl:template match=\"exercises\" mode=\"runestone-timed-exam\">\n    <xsl:param name=\"the-exercises\"/>\n    <xsl:param name=\"b-manifest\" select=\"false()\"/>\n\n    <!-- Since the component wraps the exercises, we do not need any  -->\n    <!-- restriction about being at teh Runestone \"subchapter\" level. -->\n    <xsl:if test=\"$b-host-runestone\">\n        <div class=\"timedAssessment\">\n            <!-- for the manifest only, report information about -->\n            <!-- the \"exercises\" division being re-purposed      -->\n            <xsl:if test=\"$b-manifest\">\n                <title>\n                    <xsl:apply-templates select=\".\" mode=\"title-full\"/>\n                </title>\n                <number>\n                    <xsl:apply-templates select=\".\" mode=\"number\"/>\n                </number>\n            </xsl:if>\n            <ul data-component=\"timedAssessment\" data-question_label=\"\">\n                <!-- a Runestone id -->\n                <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n                <xsl:apply-templates select=\".\" mode=\"runestone-timed-exam-attributes\"/>\n                <!-- the actual list of exercises -->\n                <xsl:copy-of select=\"$the-exercises\"/>\n                <xsl:if test=\"not($b-manifest)\">\n                    <!-- only at \"section\" level. only when building for a Runestone server -->\n                    <xsl:apply-templates select=\".\" mode=\"runestone-progress-indicator\"/>\n                </xsl:if>\n            </ul>\n        </div>\n    </xsl:if>\n</xsl:template>\n\n<!-- These are the possible attributes the Runestone component -->\n<!-- expects for a timed exam, in a style that the Runestone   -->\n<!-- HTML uses.  We repeat them *verbatim* when the Runestone  -->\n<!-- manifect reports an \"exercises\" as a timed exam, as the   -->\n<!-- best way to endure some consistency in defaults, etc.     -->\n<xsl:template match=\"exercises\" mode=\"runestone-timed-exam-attributes\">\n    <!-- one mandatory attribute -->\n    <xsl:attribute name=\"data-time\">\n        <xsl:value-of select=\"@time-limit\"/>\n    </xsl:attribute>\n    <!-- result, timer, feedback, pause are *on* by  -->\n    <!-- default if a PreTeXt attribute is \"no\" then -->\n    <!-- issue empty \"data-no-*\" Runestone attribute -->\n    <xsl:if test=\"@results = 'no'\">\n        <xsl:attribute name=\"data-no-result\"/>\n    </xsl:if>\n    <xsl:if test=\"@timer = 'no'\">\n        <xsl:attribute name=\"data-no-timer\"/>\n    </xsl:if>\n    <xsl:if test=\"@feedback = 'no'\">\n        <xsl:attribute name=\"data-no-feedback\"/>\n    </xsl:if>\n    <xsl:if test=\"@pause = 'no'\">\n        <xsl:attribute name=\"data-no-pause\"/>\n    </xsl:if>\n</xsl:template>\n\n<!-- An \"exercises\" division can be a group work exercise, by virtue -->\n<!-- of selection and submission features at the bottom of the page. -->\n<xsl:template match=\"exercises|worksheet\" mode=\"runestone-groupwork\">\n    <div class=\"runestone\">\n        <div data-component=\"groupsub\">\n            <!-- the Runestone id -->\n            <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n            <xsl:attribute name=\"data-size_limit\">\n                <xsl:choose>\n                    <xsl:when test=\"@groupsize\">\n                        <xsl:value-of select=\"@groupsize\"/>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:text>3</xsl:text>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:attribute>\n            <!-- students select their partners in their group -->\n            <div>\n                <select multiple=\"\" class=\"assignment_partner_select\"  style=\"width: 100%\"/>\n            </div>\n            <!-- and a submit button once done -->\n            <div class=\"groupsub_button\"/>\n            <div class=\"para\">The Submit Group button will submit the answer for each each question on this page for each member of your group. It also logs you as the official group submitter.</div>\n        </div>\n    </div>\n</xsl:template>\n\n\n<!-- ################## -->\n<!-- Runestone Manifest -->\n<!-- ################## -->\n\n<!-- HTML ID and real title for each chapter and section -->\n<!-- A PTX \"section\" is a Runestone \"subchapter\"         -->\n<!-- Document hierarchy is preserved in XML structure    -->\n<!-- TODO: add exercises as \"question\"                   -->\n\n<!-- Conditional run-in -->\n<xsl:template name=\"runestone-manifest\">\n    <xsl:if test=\"$b-host-runestone and ($b-is-book or $b-is-article)\">\n        <!-- $document-root *will* be a book -->\n        <xsl:apply-templates select=\"$document-root\" mode=\"runestone-manifest\"/>\n    </xsl:if>\n</xsl:template>\n\n<!-- Compute list of any programs that are linked to from other programs, -->\n<!-- they will need to be rendered into the source. Result is a node-set  -->\n<!-- containing <token>id</token>                                         -->\n<xsl:variable name=\"linked-programs-list-rtf\">\n    <xsl:variable name=\"linked-id-string\">\n      <xsl:for-each select=\"//program[boolean(@add-files) or boolean(@include) or boolean(@compile-also)]\">\n          <xsl:value-of select=\"@add-files\"/>\n          <xsl:text>,</xsl:text>\n          <xsl:value-of select=\"@include\"/>\n          <xsl:text>,</xsl:text>\n          <xsl:value-of select=\"@compile-also\"/>\n          <xsl:text>,</xsl:text>\n      </xsl:for-each>\n    </xsl:variable>\n    <xsl:call-template name=\"unique-token-set\">\n        <xsl:with-param name=\"s\" select=\"$linked-id-string\"/>\n    </xsl:call-template>\n</xsl:variable>\n<xsl:variable name=\"linked-programs-list\" select=\"exsl:node-set($linked-programs-list-rtf)/token\"/>\n\n<xsl:template match=\"book|article\" mode=\"runestone-manifest\">\n    <exsl:document href=\"runestone-manifest.xml\" method=\"xml\" indent=\"yes\" encoding=\"UTF-8\">\n        <manifest>\n            <!-- version of Runestone Services used for this build -->\n            <runestone-services>\n                <xsl:attribute name=\"version\">\n                    <xsl:value-of select=\"$runestone-version\"/>\n                </xsl:attribute>\n            </runestone-services>\n            <!-- default programming language for book as specified in docinfo -->\n            <!-- if not specified, assume python                               -->\n            <default-language>\n                <xsl:choose>\n                    <xsl:when test=\"$default-active-programming-language != ''\">\n                        <xsl:value-of select=\"$default-active-programming-language\"/>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:text>python</xsl:text>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </default-language>\n            <!-- mine various bits and pieces of the source for RS metadata  -->\n            <!-- collection, which is technically a \"conf.py\" file, per-book -->\n            <library-metadata publisher=\"pretext\">\n                <!-- sanitizes footnotes, quotes, math for overall title-->\n                <title>\n                    <xsl:apply-templates select=\"$document-root\" mode=\"title-plain\"/>\n                </title>\n                <subtitle>\n                    <xsl:apply-templates select=\"$document-root\" mode=\"subtitle\"/>\n                </subtitle>\n                <xsl:for-each select=\"$document-root/frontmatter/bibinfo/author\">\n                    <author>\n                        <xsl:apply-templates select=\"personname\"/>\n                    </author>\n                </xsl:for-each>\n                <!-- edition, too? -->\n                <document-id>\n                    <!-- global variables defined in -common -->\n                    <xsl:attribute name=\"edition\">\n                        <xsl:value-of select=\"$edition\"/>\n                    </xsl:attribute>\n                    <xsl:value-of select=\"$document-id\"/>\n                </document-id>\n                <!-- duplicate blurb, blurb/@shelf for Runestone's convenience -->\n                <!-- use \"value-of\" to enforce assumption there is no markup   -->\n                <!-- NB: if absent in PTX source, these are empty in manifest  -->\n                <shelf>\n                    <xsl:value-of select=\"$docinfo/blurb/@shelf\"/>\n                </shelf>\n                <blurb>\n                    <xsl:value-of select=\"$docinfo/blurb\"/>\n                </blurb>\n            </library-metadata>\n            <!-- LaTeX packages and macros first -->\n            <latex-macros>\n                <xsl:text>&#xa;</xsl:text>\n                <xsl:value-of select=\"$latex-packages-mathjax\"/>\n                <xsl:value-of select=\"$latex-macros\"/>\n            </latex-macros>\n            <xsl:choose>\n                <xsl:when test=\"self::book\">\n                    <!-- Now recurse into chapters, appendix -->\n                    <xsl:apply-templates select=\"*\" mode=\"runestone-manifest\"/>\n                </xsl:when>\n                <xsl:when test=\"self::article\">\n                    <!-- Now recurse into sections, appendix  -->\n                    <!-- with a faux chapter, using \"article\" -->\n                    <chapter>\n                        <id>\n                            <xsl:apply-templates select=\".\" mode=\"html-id\"/>\n                        </id>\n                        <title>\n                            <xsl:apply-templates select=\".\" mode=\"title-full\"/>\n                        </title>\n                        <number>\n                            <xsl:apply-templates select=\".\" mode=\"number\"/>\n                        </number>\n                        <division>\n                            <xsl:value-of select=\"local-name()\"/>\n                        </division>\n                        <xsl:apply-templates select=\"*\" mode=\"runestone-manifest\"/>\n                    </chapter>\n                </xsl:when>\n            </xsl:choose>\n        </manifest>\n    </exsl:document>\n</xsl:template>\n\n<xsl:template match=\"chapter\" mode=\"runestone-manifest\">\n    <chapter>\n        <id>\n            <xsl:apply-templates select=\".\" mode=\"html-id\"/>\n        </id>\n        <title>\n            <xsl:apply-templates select=\".\" mode=\"title-full\"/>\n        </title>\n        <number>\n            <xsl:apply-templates select=\".\" mode=\"number\"/>\n        </number>\n        <division>\n            <xsl:value-of select=\"local-name()\"/>\n        </division>\n    <!-- Recurse into PTX sections, or if the chapter is not structured, -->\n    <!-- then pick up inline exercises directly within a chapter         -->\n    <xsl:apply-templates select=\"*\" mode=\"runestone-manifest\"/>\n    </chapter>\n</xsl:template>\n\n<!-- Every division at PreTeXt \"section\" level, potentially containing  -->\n<!-- an \"exercise\", e.g. a \"worksheet\", but not a \"references\", is a    -->\n<!-- Runestone \"subchapter\".  Runestone \"timed exams\" (on a per-chapter -->\n<!-- basis here), which are an \"exercises\" with a @time-limit, are      -->\n<!-- exceptional and have templates elsewhere.                          -->\n<xsl:template match=\"section|chapter/exercises[not(@time-limit)]|chapter/worksheet|chapter/handout|chapter/reading-questions\" mode=\"runestone-manifest\">\n    <subchapter>\n        <!-- some properties of the division -->\n        <xsl:apply-templates select=\".\" mode=\"runestone-division-properties\"/>\n        <!-- nearly a dead end, recurse into \"exercise\" and PROJECT-LIKE at *any* PTX -->\n        <!-- depth, for example within a \"subsection\" (which Runestone does not have) -->\n        <!-- If any of the next select are containers (full of \"task\") they will not  -->\n        <!-- meet the dead-end monster match below, and the default template will     -->\n        <!-- recurse into non-container \"task\" eventually, so \"task\" do get           -->\n        <!-- processed, even if they seem to be missing from this select.             -->\n        <!-- Exceptions (early in the select): we explicitly recurse into a           -->\n        <!-- \"exercises\" division at the PreTeXt \"subsection\" level that is a         -->\n        <!-- Runestone timed exam associated with some \"section\".  We also avoid      -->\n        <!-- collecting \"exercise\" at arbitrary depth for the timed exams, as the     -->\n        <!-- template for those divisions will do that collection.                    -->\n        <xsl:apply-templates select=\"exercises[@time-limit]|.//exercise[not(ancestor::exercises[@time-limit])]|.//project|.//activity|.//exploration|.//investigation|.//video[@youtube]|.//program[(@interactive = 'codelens') and not(parent::exercise)]|.//program[(@interactive = 'activecode') and not(parent::exercise)]|.//datafile\" mode=\"runestone-manifest\"/>\n\n        <!-- Now check for programs that have been included elsewhere. They need      -->\n        <!-- to be rendered into <source> elements.                                   -->\n        <xsl:apply-templates select=\".//program[@xml:id = $linked-programs-list]\" mode=\"runestone-manifest-source\"/>\n    </subchapter>\n    <!-- dead end structurally, no more recursion, even if \"subsection\", etc. -->\n</xsl:template>\n\n<!-- \"exercises\" divisions with @time-limit are Runestone \"timed-exams\".      -->\n<!-- They can be at the PreTeXt \"section\" level (as a Runestone \"subchapter\") -->\n<!-- or they are at the PreTeXt \"subsection\" level. Their contained           -->\n<!-- \"exercise\" are excluded previously, and are now collected here.          -->\n<xsl:template match=\"chapter/exercises[@time-limit]|chapter/section/exercises[@time-limit]\" mode=\"runestone-manifest\">\n    <!-- Duplicate the division, ehnhanced with indicators of a timed -->\n    <!-- exam.  Include the contained exercises as manifest items.    -->\n    <!-- Strictly speaking this not exactly correct, for example,     -->\n    <!-- we get a progress indicator we do not want.                  -->\n    <xsl:apply-templates select=\".\" mode=\"runestone-timed-exam\">\n        <xsl:with-param name=\"the-exercises\">\n            <xsl:apply-templates select=\".//exercise\" mode=\"runestone-manifest\"/>\n        </xsl:with-param>\n        <xsl:with-param name=\"b-manifest\" select=\"true()\"/>\n    </xsl:apply-templates>\n</xsl:template>\n\n<!-- Properties to report for each division -->\n<xsl:template match=\"*\" mode=\"runestone-division-properties\">\n    <id>\n        <xsl:apply-templates select=\".\" mode=\"html-id\"/>\n    </id>\n    <title>\n        <xsl:apply-templates select=\".\" mode=\"title-full\"/>\n    </title>\n    <number>\n        <xsl:apply-templates select=\".\" mode=\"number\"/>\n    </number>\n    <!-- report the division type -->\n    <division>\n        <xsl:value-of select=\"local-name()\"/>\n    </division>\n</xsl:template>\n\n<!-- A Runestone exercise needs to identify itself when an instructor wants   -->\n<!-- to select it for assignment, so we want to provide enough identification -->\n<!-- in the manifest, via a \"label\" element full of raw text.                 -->\n<xsl:template match=\"exercise|project|activity|exploration|investigation|task\" mode=\"runestone-manifest-label\">\n    <label>\n        <xsl:apply-templates select=\".\" mode=\"type-name\"/>\n        <xsl:text> </xsl:text>\n        <xsl:apply-templates select=\".\" mode=\"number\"/>\n        <xsl:text> </xsl:text>\n        <xsl:apply-templates select=\".\" mode=\"title-full\"/>\n    </label>\n</xsl:template>\n\n<!-- Minimal label.  In database for obvious reasons, -->\n<!-- this is best (only?) thing to use as a label.    -->\n<xsl:template match=\"datafile\" mode=\"runestone-manifest-label\">\n    <label>\n        <xsl:value-of select=\"@filename\"/>\n    </label>\n</xsl:template>\n\n<!-- Runestone tracks engagement with YouTube videos and \"stray\" -->\n<!-- ActiveCode and CodeLens (i.e. an \"inline\" \"program\", not as -->\n<!-- a portion of an \"exercise\".  As these are atomic elements,  -->\n<!-- there is little to grab onto for a label in a report for an -->\n<!-- instructor.  So we provide examination of an enclosing      -->\n<!-- figure (\"video\") or listing (\"program\").                    -->\n\n<xsl:template match=\"video[@youtube]|program[((@interactive = 'codelens') or (@interactive = 'activecode')) and not(parent::exercise)]\" mode=\"runestone-manifest-label\">\n    <label>\n        <!-- three ways to get a type-name -->\n        <xsl:choose>\n            <xsl:when test=\"self::video[@youtube]\">\n                <xsl:apply-templates select=\".\" mode=\"type-name\"/>\n            </xsl:when>\n            <xsl:when test=\"self::program[@interactive = 'codelens']\">\n                <xsl:apply-templates select=\".\" mode=\"type-name\">\n                    <xsl:with-param name=\"string-id\" select=\"'program-codelens'\"/>\n                </xsl:apply-templates>\n            </xsl:when>\n            <xsl:when test=\"self::program[@interactive = 'activecode']\">\n                <xsl:apply-templates select=\".\" mode=\"type-name\">\n                    <xsl:with-param name=\"string-id\" select=\"'program-activecode'\"/>\n                </xsl:apply-templates>\n            </xsl:when>\n        </xsl:choose>\n        <!-- \"video\" can be a \"figure\", and \"program\" can be in a -->\n        <!-- \"listing\", but the two situations are similar enough -->\n        <!-- to combine and work with a generic parent/enclosure. -->\n        <!-- This could well be empty if inline objects.          -->\n        <xsl:variable name=\"enclosure\" select=\"parent::figure|parent::listing\"/>\n        <xsl:variable name=\"b-title\" select=\"boolean(title)\"/>\n        <xsl:variable name=\"b-enclosure\" select=\"boolean($enclosure)\"/>\n        <!-- more coming, use a separator -->\n        <xsl:if test=\"$b-title or $b-enclosure\">\n            <xsl:text>: </xsl:text>\n        </xsl:if>\n        <!-- object's title is \"closer\" (or may be only  -->\n        <!-- possible identification if standalone) -->\n        <xsl:if test=\"$b-title\">\n            <xsl:apply-templates select=\".\" mode=\"title-full\"/>\n        </xsl:if>\n        <!-- if an abundance, use a separator -->\n        <xsl:if test=\"$b-title and $b-enclosure\">\n            <xsl:text>; </xsl:text>\n        </xsl:if>\n        <xsl:if test=\"$b-enclosure\">\n            <xsl:apply-templates select=\"$enclosure\" mode=\"type-name\"/>\n            <xsl:text> </xsl:text>\n            <xsl:apply-templates select=\"$enclosure\" mode=\"number\"/>\n            <xsl:if test=\"$enclosure/title\">\n                <xsl:text> </xsl:text>\n                <xsl:apply-templates select=\"$enclosure\" mode=\"title-full\"/>\n            </xsl:if>\n        </xsl:if>\n        <!-- last ditch effor for a YouTube video -->\n        <xsl:if test=\"self::video[@youtube] and not($b-title) and not($b-enclosure)\">\n            <xsl:text>: </xsl:text>\n            <!-- need to know Runestone CSS to make this code/monospace -->\n            <xsl:value-of select=\"@youtube\"/>\n        </xsl:if>\n    </label>\n</xsl:template>\n\n<!-- Exercises to the Runestone manifest                                 -->\n<!-- This is includes some things that can't exist. e.g. webwork in task -->\n<!-- but standardized treatment is easier to maintain than explicit      -->\n<!-- listing of expected combinations.                                   -->\n<!-- Intentionally matching all containers and then filtering with if on -->\n<!-- attribute. Explicit listing in template match might be slightly more-->\n<!-- efficient but has proven to be a popular spot for bugs.             -->\n<xsl:template match=\"exercise|&PROJECT-LIKE;|task\" mode=\"runestone-manifest\">\n    <xsl:variable name=\"manifestable-interactives-fenced\">|truefalse|multiplechoice|parson|parson-horizontal|cardsort|matching|clickablearea|select|fillin-basic|fillin|coding|dual|shortanswer|webwork|</xsl:variable>\n    <xsl:if test=\"contains($manifestable-interactives-fenced, concat('|', @pi:exercise-interactive, '|'))\">\n        <question>\n            <!-- A divisional exercise (\"exercises/../exercise\") is not really   -->\n            <!-- a reading activity in the Runestone model, so we flag these     -->\n            <!-- exercises as such.  Also, interactive \"task\" come through here, -->\n            <!-- so we need to look to an ancestor to see if the containing      -->\n            <!-- \"exercise\" is divisional. The @optional attribute matches the   -->\n            <!-- \"optional\" flag in the Runestone database.  We simply set the   -->\n            <!-- value to \"yes\" and never bother to say \"no\".  The  only         -->\n            <!-- consumer is the import into the Runestone database, so any      -->\n            <!-- change needs only coordinate there.                             -->\n            <xsl:if test=\"(@pi:exercise-customization = 'divisional') or\n                          (self::task and ancestor::exercise[@pi:exercise-customization = 'divisional'])\">\n                <xsl:attribute name=\"optional\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:attribute>\n            </xsl:if>\n            <!-- label is from the \"exercise\" -->\n            <xsl:apply-templates select=\".\" mode=\"runestone-manifest-label\"/>\n            <!-- Duplicate, but still should look like original (ID, etc.),  -->\n            <!-- not knowled. Solutions are available in the originals, via  -->\n            <!-- an \"in context\" link off the Assignment page                -->\n            <htmlsrc>\n                <!-- next template produces nothing, unless the  -->\n                <!-- \"exercise\" is in an \"exercisegroup\" (\"eg\")  -->\n                <xsl:apply-templates select=\".\" mode=\"eg-introduction\"/>\n                <xsl:choose>\n                    <!-- with \"webwork\" guts, the HTML is exceptional -->\n                    <xsl:when test=\"@pi:exercise-interactive = 'webwork'\">\n                        <xsl:apply-templates select=\".\" mode=\"webwork-core\">\n                            <xsl:with-param name=\"b-original\" select=\"true()\"/>\n                            <xsl:with-param name=\"heading-level\" select=\"3\"/>\n                        </xsl:apply-templates>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <!-- next template collects \"introduction\" preceding a \"task\" -->\n                        <!-- Note: we are explicitly dodging webwork/task             -->\n                        <xsl:apply-templates select=\".\" mode=\"task-introductions\"/>\n\n                        <!-- determine which components publisher wants rendered-->\n                        <xsl:variable name=\"ex-components-rtf\">\n                            <xsl:apply-templates select=\".\" mode=\"exercise-components-report\"/>\n                        </xsl:variable>\n                        <xsl:variable name=\"ex-components-report\" select=\"exsl:node-set($ex-components-rtf)/exercise-component-report\"/>\n\n                        <xsl:apply-templates select=\".\" mode=\"exercise-components\">\n                            <xsl:with-param name=\"b-original\" select=\"true()\"/>\n                            <xsl:with-param name=\"block-type\" select=\"'visible'\"/>\n                            <xsl:with-param name=\"heading-level\" select=\"3\"/>\n                            <xsl:with-param name=\"b-has-statement\" select=\"true()\"/>\n                            <xsl:with-param name=\"b-has-hint\" select=\"$ex-components-report/@has-hint = 'true'\"/>\n                            <xsl:with-param name=\"b-has-answer\" select=\"$ex-components-report/@has-answer = 'true'\"/>\n                            <xsl:with-param name=\"b-has-solution\" select=\"$ex-components-report/@has-solution = 'true'\"/>\n                        </xsl:apply-templates>\n\n                        <!-- next template collects \"conclusion\" preceding a \"task\" -->\n                        <!-- Note: we are explicitly dodging webwork/task           -->\n                        <xsl:apply-templates select=\".\" mode=\"task-conclusions\"/>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </htmlsrc>\n        </question>\n    </xsl:if>\n    <!-- The match for this template will include \"exercise\" and &PROJECT-LIKE     -->\n    <!-- that are just containers for a bunch of \"task\".  In other words, they     -->\n    <!-- will not be marked with the \"@pi:exercise-interactive\" attribute.  So the -->\n    <!-- \"xsl:if\" above will fail.  And right here is a dead-end.  We need to      -->\n    <!-- recurse into \"task\" for the possibility they are marked with              -->\n    <!-- \"@pi:exercise-interactive\" so they can potentially get placed properly in -->\n    <!-- the manifest.                                                             -->\n    <xsl:apply-templates select=\"task\" mode=\"runestone-manifest\"/>\n</xsl:template>\n\n<!-- For an \"exercise\" divorced from it's \"exercisegroup\" \"introduction\", -->\n<!-- we pick it up to be part of what is shown to the student on the      -->\n<!-- Runestone Assignment page.                                           -->\n\n<xsl:template match=\"*\" mode=\"eg-introduction\"/>\n\n<xsl:template match=\"exercisegroup/exercise\" mode=\"eg-introduction\">\n    <xsl:apply-templates select=\"parent::exercisegroup/introduction\"/>\n</xsl:template>\n\n<!-- Next two templates replicate all ancestral \"introduction\"   -->\n<!-- and \"conclusion\" on a per-task basis so that when a \"task\"  -->\n<!-- is viewed in the Runestone assignment builder, any overall  -->\n<!-- explanatory text is available.                              -->\n\n<xsl:template match=\"task\" mode=\"task-introductions\">\n    <!-- collect in a variable, so processing is subsequently in document order -->\n    <xsl:variable name=\"introductions\" select=\"ancestor-or-self::task/preceding-sibling::introduction\"/>\n    <xsl:apply-templates select=\"$introductions\"/>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"task-introductions\"/>\n\n<xsl:template match=\"task\" mode=\"task-conclusions\">\n    <!-- collect in a variable, so processing is subsequently in document order -->\n    <xsl:variable name=\"conclusions\" select=\"ancestor-or-self::task/following-sibling::conclusion\"/>\n    <xsl:apply-templates select=\"$conclusions\"/>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"task-conclusions\"/>\n\n<!-- TODO: by renaming/refactoring the templates inside of   -->\n<!-- \"htmlsrc\" then perhaps several of these templates with  -->\n<!-- similar structure can be combined via one larger match. -->\n\n<xsl:template match=\"video[@youtube]\" mode=\"runestone-manifest\">\n    <question>\n        <!-- label is from the \"video\", or enclosing \"figure\" -->\n        <xsl:apply-templates select=\".\" mode=\"runestone-manifest-label\"/>\n        <htmlsrc>\n            <xsl:apply-templates select=\".\" mode=\"runestone-youtube-embed\"/>\n        </htmlsrc>\n    </question>\n</xsl:template>\n\n<xsl:template match=\"program[(@interactive = 'codelens') and not(parent::*[self::exercise or &PROJECT-FILTER;])]\" mode=\"runestone-manifest\">\n    <question>\n        <!-- label is from the \"program\", or enclosing \"listing\" -->\n        <xsl:apply-templates select=\".\" mode=\"runestone-manifest-label\"/>\n        <htmlsrc>\n            <xsl:apply-templates select=\".\" mode=\"runestone-codelens\"/>\n        </htmlsrc>\n    </question>\n</xsl:template>\n\n<xsl:template match=\"program[(@interactive = 'activecode') and not(parent::*[self::exercise or &PROJECT-FILTER;])]\" mode=\"runestone-manifest\">\n    <!-- verify that program is in a language that can be made active -->\n    <xsl:variable name=\"active-language\">\n        <xsl:apply-templates select=\".\" mode=\"active-language\"/>\n    </xsl:variable>\n    <xsl:if test=\"$active-language != ''\">\n        <question>\n            <!-- label is from the \"program\", or enclosing \"listing\" -->\n            <xsl:apply-templates select=\".\" mode=\"runestone-manifest-label\"/>\n            <htmlsrc>\n                <xsl:apply-templates select=\".\" mode=\"runestone-activecode\"/>\n            </htmlsrc>\n        </question>\n    </xsl:if>\n</xsl:template>\n\n<!-- Source for every program that is linked to goes in as a <source>              -->\n<!-- For activecode/codelens, source will also appear in a <question> element      -->\n<!-- but in that location it will be buried in a pile of html.                     -->\n<xsl:template match=\"program\" mode=\"runestone-manifest-source\">\n    <xsl:variable name=\"filename\">\n        <xsl:apply-templates select=\".\" mode=\"runestone-filename\"/>\n    </xsl:variable>\n    <source>\n        <xsl:attribute name=\"filename\">\n            <xsl:value-of select=\"$filename\"/>\n        </xsl:attribute>\n        <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n        <xsl:call-template name=\"sanitize-text\">\n            <xsl:with-param name=\"text\" select=\"code\"/>\n        </xsl:call-template>\n    </source>\n</xsl:template>\n\n<!-- Get filename to use for an element, fallback on label if filename is missing -->\n<xsl:template match=\"program|datafile\" mode=\"runestone-filename\">\n    <xsl:choose>\n        <xsl:when test=\"@filename\">\n            <xsl:value-of select=\"@filename\"/>\n        </xsl:when>\n        <xsl:when test=\"@label\">\n            <xsl:value-of select=\"@label\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>Missing filename attribute on </xsl:text>\n            <xsl:value-of select=\"name()\"/>\n            <xsl:text> with xml:id </xsl:text>\n            <xsl:value-of select=\"@xml:id\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- In database with the same structure as an exercise/question.     -->\n<!-- When datafile is in appendix, we want to wrap it with <datafile> -->\n<!-- and not write it as a question, which are expected to be in      -->\n<!-- numbered chapters.                                               -->\n<xsl:template match=\"datafile\" mode=\"runestone-manifest\">\n    <xsl:variable name=\"container-name\">\n        <xsl:choose>\n            <xsl:when test=\"ancestor::appendix\">\n                <xsl:text>datafile</xsl:text>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>question</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:element name=\"{$container-name}\">\n        <xsl:attribute name=\"optional\">\n            <xsl:text>yes</xsl:text>\n        </xsl:attribute>\n        <!-- label is from the \"program\", or enclosing \"listing\" -->\n        <xsl:apply-templates select=\".\" mode=\"runestone-manifest-label\"/>\n        <htmlsrc>\n            <xsl:apply-templates select=\".\" mode=\"runestone-to-interactive\"/>\n        </htmlsrc>\n    </xsl:element>\n</xsl:template>\n\n<!-- Appendix is currently not allowed to have \"questions\" as Runestone  -->\n<!-- requires those to have a chapter with an integer number             -->\n<!-- But look for code and datafiles that should go in source_code table -->\n<xsl:template match=\"appendix[.//program or .//datafile]\" mode=\"runestone-manifest\">\n    <appendix>\n        <!-- Check for programs that have been included elsewhere.           -->\n        <xsl:apply-templates select=\".//program[@xml:id = $linked-programs-list]\" mode=\"runestone-manifest-source\"/>\n        <!-- Check for datafiles, and write them as \"<datafile>\"s            -->\n        <xsl:apply-templates select=\".//datafile\" mode=\"runestone-manifest\"/>\n    </appendix>\n</xsl:template>\n<!-- If no programs or datafiles, do nothing -->\n<xsl:template match=\"appendix\" mode=\"runestone-manifest\"/>\n\n<!-- Traverse the tree,looking for things to do          -->\n<!-- http://stackoverflow.com/questions/3776333/         -->\n<!-- stripping-all-elements-except-one-in-xml-using-xslt -->\n<xsl:template match=\"*\" mode=\"runestone-manifest\">\n    <xsl:apply-templates select=\"*\" mode=\"runestone-manifest\"/>\n</xsl:template>\n\n<!-- ########## -->\n<!-- Components -->\n<!-- ########## -->\n\n<!-- The \"runestone-to-interactive\" templates will combine a   -->\n<!-- \"regular\" PreTeXt statement together with some additional -->\n<!-- interactive material to make a hybrid \"statement\"         -->\n\n<!-- The application of the \"runestone-to-interactive\" template is   -->\n<!-- controlled by a surrounding \"match\" that limits elements        -->\n<!-- to \"exercise\", PROJECT-LIKE, and soon \"task\".  So the           -->\n<!-- matches here are fine with a *[@pi:exercise-interactive='foo'], -->\n<!-- as a convenience.                                               -->\n\n<!-- True/False -->\n\n<xsl:template match=\"*[@pi:exercise-interactive = 'truefalse']\" mode=\"runestone-to-interactive\">\n    <div class=\"ptx-runestone-container\">\n        <div class=\"runestone multiplechoice_section\">\n            <!-- ul can have multiple answer attribute -->\n            <ul data-component=\"multiplechoice\" data-multipleanswers=\"false\">\n                <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n                <!-- Q: the statement is not a list item, but appears *inside* the list? -->\n                <!-- overall statement, not per-choice -->\n                <xsl:apply-templates select=\"statement\"/>\n                <!-- radio button for True -->\n                <li data-component=\"answer\">\n                    <xsl:attribute name=\"id\">\n                        <xsl:apply-templates select=\".\" mode=\"runestone-id\"/>\n                        <xsl:text>_opt_t</xsl:text>\n                    </xsl:attribute>\n                    <!-- Correct answer if problem statement is correct/True -->\n                    <xsl:if test=\"statement/@correct = 'yes'\">\n                        <xsl:attribute name=\"data-correct\"/>\n                    </xsl:if>\n                    <p>True.</p>\n                </li>\n                <li data-component=\"feedback\">\n                    <xsl:attribute name=\"id\">\n                        <xsl:apply-templates select=\".\" mode=\"runestone-id\"/>\n                        <xsl:text>_opt_t</xsl:text>\n                    </xsl:attribute>\n                    <!-- identical feedback for each reader responses -->\n                    <xsl:apply-templates select=\"feedback\"/>\n                </li>\n                <!-- radio button for False -->\n                <li data-component=\"answer\">\n                    <xsl:attribute name=\"id\">\n                        <xsl:apply-templates select=\".\" mode=\"runestone-id\"/>\n                        <xsl:text>_opt_f</xsl:text>\n                    </xsl:attribute>\n                    <!-- Correct answer if problem statement is incorrect/False -->\n                    <xsl:if test=\"statement/@correct = 'no'\">\n                        <xsl:attribute name=\"data-correct\"/>\n                    </xsl:if>\n                    <p>False.</p>\n                </li>\n                <li data-component=\"feedback\">\n                    <xsl:attribute name=\"id\">\n                        <xsl:apply-templates select=\".\" mode=\"runestone-id\"/>\n                        <xsl:text>_opt_f</xsl:text>\n                    </xsl:attribute>\n                    <!-- identical feedback for each reader responses -->\n                    <xsl:apply-templates select=\"feedback\"/>\n                </li>\n            </ul>\n        </div>\n    </div>\n</xsl:template>\n\n<!-- Multiple Choice -->\n\n<xsl:template match=\"*[@pi:exercise-interactive = 'multiplechoice']\" mode=\"runestone-to-interactive\">\n    <div class=\"ptx-runestone-container\">\n        <div class=\"runestone multiplechoice_section\">\n            <!-- overall statement, not per-choice -->\n            <div class=\"exercise-statement\">\n                <xsl:apply-templates select=\"statement\"/>\n            </div>\n            <!-- ul can have multiple answer attribute -->\n            <ul data-component=\"multiplechoice\" class=\"exercise-interactives\">\n                <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n                <xsl:variable name=\"ncorrect\" select=\"count(choices/choice[@correct = 'yes'])\"/>\n                <xsl:attribute name=\"data-multipleanswers\">\n                    <xsl:choose>\n                        <xsl:when test=\"choices/@multiple-correct = 'yes'\">\n                            <xsl:text>true</xsl:text>\n                        </xsl:when>\n                        <xsl:when test=\"choices/@multiple-correct = 'no'\">\n                            <xsl:text>false</xsl:text>\n                        </xsl:when>\n                        <xsl:when test=\"$ncorrect > 1\">\n                            <xsl:text>true</xsl:text>\n                        </xsl:when>\n                        <xsl:otherwise>\n                            <xsl:text>false</xsl:text>\n                        </xsl:otherwise>\n                    </xsl:choose>\n                </xsl:attribute>\n                <!-- bare attribute, iff requested -->\n                <xsl:if test=\"choices/@randomize = 'yes'\">\n                    <xsl:attribute name=\"data-random\"/>\n                </xsl:if>\n                <xsl:apply-templates select=\"choices/choice\">\n                    <xsl:with-param name=\"the-id\">\n                        <xsl:apply-templates select=\".\" mode=\"runestone-id\"/>\n                    </xsl:with-param>\n                </xsl:apply-templates>\n            </ul>\n        </div>\n    </div>\n</xsl:template>\n\n<xsl:template match=\"choices/choice\">\n    <xsl:param name=\"the-id\"/>\n\n    <!-- id for each \"choice\"                  -->\n    <!-- with common base, then a, b, c suffix -->\n    <!-- Used *twice* on adjacent \"li\"?        -->\n    <xsl:variable name=\"choice-id\">\n        <xsl:value-of select=\"$the-id\"/>\n        <xsl:text>_opt_</xsl:text>\n        <!-- will count preceding \"choice\" only -->\n        <xsl:number format=\"a\"/>\n    </xsl:variable>\n    <li data-component=\"answer\">\n        <xsl:attribute name=\"id\">\n            <xsl:value-of select=\"$choice-id\"/>\n        </xsl:attribute>\n        <!-- mark correct answers (empty attribute value) -->\n        <xsl:if test=\"@correct = 'yes'\">\n            <xsl:attribute name=\"data-correct\"/>\n        </xsl:if>\n        <!-- per-choice statement -->\n        <xsl:apply-templates select=\"statement\"/>\n    </li>\n    <li data-component=\"feedback\">\n        <xsl:attribute name=\"id\">\n            <xsl:value-of select=\"$choice-id\"/>\n        </xsl:attribute>\n        <!-- per-choice explanation -->\n        <xsl:apply-templates select=\"feedback\"/>\n    </li>\n</xsl:template>\n\n<!-- Parsons Problem -->\n\n<xsl:template match=\"*[@pi:exercise-interactive = 'parson']\" mode=\"runestone-to-interactive\">\n    <!-- active-language only used if runnable but needed multiple places -->\n    <xsl:variable name=\"active-language\">\n        <xsl:apply-templates select=\".\" mode=\"active-language\"/>\n    </xsl:variable>\n    <!-- determine this option before context switches -->\n    <xsl:variable name=\"b-natural\" select=\"($active-language = '') or ($active-language = 'natural')\"/>\n    <div class=\"ptx-runestone-container\">\n        <div class=\"runestone parsons_section\" style=\"max-width: none;\">\n            <div data-component=\"parsons\" class=\"parsons\">\n                <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n                <div class=\"parsons_question parsons-text\" >\n                    <!-- the prompt -->\n                    <xsl:apply-templates select=\"statement\"/>\n                </div>\n                <pre class=\"parsonsblocks\" data-question_label=\"\" style=\"visibility: hidden;\">\n                    <!-- presence of a program implies runnable when completed -->\n                    <xsl:if test=\"program\">\n                        <xsl:choose>\n                            <xsl:when test=\"$active-language != ''\">\n                                <xsl:attribute name=\"data-runnable\">\n                                    <xsl:text>true</xsl:text>\n                                </xsl:attribute>\n                            </xsl:when>\n                            <xsl:otherwise>\n                                <xsl:variable name=\"id\">\n                                    <xsl:apply-templates select=\".\" mode=\"unique-id\"/>\n                                </xsl:variable>\n                                <xsl:message>PTX:WARNING:  Parsons problems need a @language that is a valid activecode language to be runnable</xsl:message>\n                                <xsl:message>              id: <xsl:value-of select=\"$id\"></xsl:value-of></xsl:message>\n                            </xsl:otherwise>\n                        </xsl:choose>\n                    </xsl:if>\n                    <!-- author opts-in to adaptive problems -->\n                    <xsl:attribute name=\"data-language\">\n                        <xsl:choose>\n                            <xsl:when test=\"$b-natural\">\n                                <xsl:text>natural</xsl:text>\n                            </xsl:when>\n                            <xsl:otherwise>\n                                <!-- must now have a language -->\n                                <xsl:value-of select=\"$active-language\"/>\n                            </xsl:otherwise>\n                        </xsl:choose>\n                    </xsl:attribute>\n                    <!-- do not confuse this attribute with the  @pi:numbered -->\n                    <!-- attribute for numbered equations                     -->\n                    <xsl:variable name=\"numbered\" select=\"blocks/@numbered\"/>\n                    <xsl:choose>\n                        <xsl:when test=\"($numbered = 'left') or ($numbered = 'right')\">\n                            <xsl:attribute name=\"data-numbered\">\n                                <xsl:value-of select=\"$numbered\"/>\n                            </xsl:attribute>\n                        </xsl:when>\n                        <!-- default is un-numbered, so no attribute at all -->\n                        <xsl:when test=\"$numbered = 'no'\"/>\n                        <xsl:otherwise/>\n                    </xsl:choose>\n                    <xsl:if test=\"@adaptive = 'yes'\">\n                        <xsl:attribute name=\"data-adaptive\">\n                            <xsl:text>true</xsl:text>\n                        </xsl:attribute>\n                    </xsl:if>\n                    <xsl:if test=\"blocks/block/@depends\">\n                        <xsl:attribute name=\"data-grader\">\n                            <xsl:text>dag</xsl:text>\n                        </xsl:attribute>\n                    </xsl:if>\n                    <!-- Fixed-order rendering, gated by blocks/@randomize='no' -->\n                    <xsl:if test=\"blocks/@randomize = 'no'\">\n                        <xsl:attribute name=\"data-order\">\n                            <xsl:apply-templates select=\"blocks\" mode=\"parsons-data-order\"/>\n                        </xsl:attribute>\n                    </xsl:if>\n                    <!-- author asks student to provide indentation via  -->\n                    <!-- the indentation-enabled \"drop\" text window      -->\n                    <!-- (not relevant for natural language)             -->\n                    <xsl:attribute name=\"data-noindent\">\n                        <xsl:choose>\n                            <xsl:when test=\"@indentation = 'hide'\">\n                                <xsl:text>false</xsl:text>\n                            </xsl:when>\n                            <!-- default is 'show' -->\n                            <xsl:otherwise>\n                                <xsl:text>true</xsl:text>\n                            </xsl:otherwise>\n                        </xsl:choose>\n                    </xsl:attribute>\n                    <!-- the blocks -->\n                    <xsl:apply-templates select=\"blocks/block\" mode=\"vertical-blocks\">\n                        <xsl:with-param name=\"b-natural\" select=\"$b-natural\"/>\n                    </xsl:apply-templates>\n                </pre>\n            </div>\n            <xsl:if test=\"program\">\n                <!-- Parsons is executable when finished -->\n                <div style=\"display: none\">\n                    <xsl:attribute name=\"id\">\n                        <xsl:apply-templates select=\".\" mode=\"runestone-id\"/>\n                        <xsl:text>-runnable</xsl:text>\n                    </xsl:attribute>\n                    <div data-component=\"parsons-runnable\">\n                        <xsl:attribute name=\"id\">\n                            <xsl:apply-templates select=\".\" mode=\"runestone-id\"/>\n                            <xsl:text>-runnable-ac</xsl:text>\n                        </xsl:attribute>\n                        <textarea data-lang=\"{$active-language}\" data-audio=\"\" data-coach=\"true\" style=\"visibility: hidden;\">\n                            <xsl:variable name=\"hosting\">\n                                <xsl:apply-templates select=\".\" mode=\"activecode-host\"/>\n                            </xsl:variable>\n                            <!-- loop just to set context. program should be single -->\n                            <xsl:for-each select=\"program\">\n                                <xsl:call-template name=\"runestone-activecode-editor-attributes\">\n                                    <xsl:with-param name=\"active-language\" select=\"$active-language\"/>\n                                    <xsl:with-param name=\"hosting\" select=\"$hosting\"/>\n                                </xsl:call-template>\n                            </xsl:for-each>\n                            <!-- the content -->\n                            <xsl:text>&#xa;</xsl:text>\n                            <xsl:call-template name=\"add-indentation\">\n                                <xsl:with-param name=\"text\">\n                                    <xsl:call-template name=\"sanitize-text\">\n                                        <xsl:with-param name=\"text\" select=\"program-preamble\"/>\n                                        <xsl:with-param name=\"preserve-end\" select=\"true()\"/>\n                                    </xsl:call-template>\n                                </xsl:with-param>\n                                <xsl:with-param name=\"indent\"><xsl:value-of select=\"program-preamble/@indent\"/></xsl:with-param>\n                            </xsl:call-template>\n                            <!-- placeholder for user code -->\n                            <xsl:text>==PARSONSCODE==&#xa;</xsl:text>\n                            <xsl:call-template name=\"add-indentation\">\n                                <xsl:with-param name=\"text\">\n                                    <xsl:call-template name=\"sanitize-text\">\n                                        <xsl:with-param name=\"text\" select=\"program-postamble\"/>\n                                        <xsl:with-param name=\"preserve-start\" select=\"true()\"/>\n                                    </xsl:call-template>\n                                </xsl:with-param>\n                                <xsl:with-param name=\"indent\"><xsl:value-of select=\"program-postamble/@indent\"/></xsl:with-param>\n                            </xsl:call-template>\n                        </textarea>\n                    </div>\n                </div>\n            </xsl:if>\n        </div>\n    </div>\n</xsl:template>\n\n<!-- Helper: build the @data-order list (comma-separated, -->\n<!-- 0-based) in the order specified by @order on each    -->\n<!-- block.  A block containing \"choice\" children does    -->\n<!-- not get an index; each choice gets one in its place. -->\n<xsl:template match=\"blocks\" mode=\"parsons-data-order\">\n    <xsl:for-each select=\"block\">\n        <xsl:sort select=\"@order\" data-type=\"number\"/>\n        <xsl:if test=\"position() &gt; 1\">\n            <xsl:text>,</xsl:text>\n        </xsl:if>\n        <xsl:choose>\n            <xsl:when test=\"choice\">\n                <xsl:for-each select=\"choice\">\n                    <xsl:if test=\"position() &gt; 1\">\n                        <xsl:text>,</xsl:text>\n                    </xsl:if>\n                    <!-- This choice is a leaf.  Its 0-based index is the count  -->\n                    <!-- of leaves preceding it: choice-less blocks and choices  -->\n                    <!-- of blocks before its parent, plus its earlier siblings. -->\n                    <xsl:value-of select=\"count(../preceding-sibling::block[not(choice)])\n                                          + count(../preceding-sibling::block/choice)\n                                          + count(preceding-sibling::choice)\"/>\n                </xsl:for-each>\n            </xsl:when>\n            <xsl:otherwise>\n                <!-- This choice-less block is a leaf.  Its 0-based index   -->\n                <!-- is the count of leaves preceding it: choice-less       -->\n                <!-- blocks, plus choices belonging to blocks-with-choices. -->\n                <xsl:value-of select=\"count(preceding-sibling::block[not(choice)])\n                                      + count(preceding-sibling::block/choice)\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:for-each>\n</xsl:template>\n\n<xsl:template match=\"blocks/block\" mode=\"vertical-blocks\">\n    <xsl:param name=\"b-natural\"/>\n    <xsl:variable name=\"name\">\n        <xsl:choose>\n            <xsl:when test=\"@name|@depends\">\n                <xsl:text> #tag:</xsl:text>\n                <xsl:value-of select=\"@name\"/>\n                <xsl:text>; depends:</xsl:text>\n                <xsl:value-of select=\"str:replace(@depends, ' ', ',')\"/>\n                <xsl:text>;</xsl:text>\n            </xsl:when>\n        </xsl:choose>\n    </xsl:variable>\n\n    <xsl:choose>\n        <xsl:when test=\"choice\">\n            <!-- put single correct choice first      -->\n            <!-- default on \"choice\" is  correct=\"no\" -->\n            <xsl:apply-templates select=\"choice[@correct = 'yes']\">\n                <xsl:with-param name=\"b-natural\" select=\"$b-natural\"/>\n                <xsl:with-param name=\"name\" select=\"$name\"/>\n            </xsl:apply-templates>\n            <xsl:apply-templates select=\"choice[not(@correct = 'yes')]\">\n                <xsl:with-param name=\"b-natural\" select=\"$b-natural\"/>\n                <xsl:with-param name=\"name\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:choose>\n                <xsl:when test=\"$b-natural\">\n                    <xsl:apply-templates/>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:for-each select=\"cline\">\n                        <xsl:value-of select=\".\"/>\n                        <xsl:if test=\"following-sibling::cline\">\n                            <xsl:text>&#xa;</xsl:text>\n                        </xsl:if>\n                    </xsl:for-each>\n                </xsl:otherwise>\n            </xsl:choose>\n            <!-- default on \"block\" is  correct=\"yes\" -->\n            <xsl:if test=\"@correct = 'no'\">\n                <xsl:text> #distractor</xsl:text>\n            </xsl:if>\n            <xsl:value-of select=\"$name\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n    <xsl:if test=\"following-sibling::block\">\n        <xsl:text>&#xa;---&#xa;</xsl:text>\n    </xsl:if>\n</xsl:template>\n\n<xsl:template match=\"blocks/block/choice\">\n    <xsl:param name=\"b-natural\"/>\n    <xsl:param name=\"name\"/>\n\n    <!-- Exactly one choice is correct, it is placed first. -->\n    <!-- Then the  n - 1  separators can be placed on all   -->\n    <!-- the \"wrong\" choices.                               -->\n    <xsl:if test=\"not(@correct = 'yes')\">\n        <xsl:text>&#xa;---&#xa;</xsl:text>\n    </xsl:if>\n    <xsl:choose>\n        <xsl:when test=\"$b-natural\">\n            <xsl:apply-templates select=\"*\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:for-each select=\"cline\">\n                <xsl:value-of select=\".\"/>\n                <xsl:if test=\"following-sibling::cline\">\n                    <xsl:text>&#xa;</xsl:text>\n                </xsl:if>\n            </xsl:for-each>\n        </xsl:otherwise>\n    </xsl:choose>\n    <xsl:if test=\"not(@correct = 'yes')\">\n        <xsl:text> #paired</xsl:text>\n    </xsl:if>\n    <xsl:value-of select=\"$name\"/>\n</xsl:template>\n\n<!-- Parsons Problem (Horizontal)-->\n\n<xsl:template  match=\"*[@pi:exercise-interactive = 'parson-horizontal']\" mode=\"runestone-to-interactive\">\n    <!-- determine these options before context switches -->\n    <xsl:variable name=\"active-language\">\n      <xsl:apply-templates select=\".\" mode=\"active-language\"/>\n    </xsl:variable>\n    <xsl:variable name=\"b-natural\" select=\"($active-language = '') or ($active-language = 'natural')\"/>\n    <!-- randomize by default, so must explicitly turn off -->\n    <xsl:variable name=\"b-randomize\" select=\"not(blocks/@randomize = 'no')\"/>\n    <!-- A @ref is automatic indicator, else reuse has been requested on blocks -->\n    <xsl:variable name=\"b-reuse\" select=\"blocks/block[@ref] or (blocks/@reuse = 'yes')\"/>\n    <!-- We loop over blocks, as authored, so this is just a convenience -->\n    <xsl:variable name=\"authored-blocks\" select=\"blocks/block\"/>\n    <!-- A block with @ref indicates reuse of some other block, for answer         -->\n    <!-- specifications we want to treat them as duplicates.  And we do not        -->\n    <!-- write them into the HTML either.  So we make a subset of *unique* blocks. -->\n    <xsl:variable name=\"unique-blocks\" select=\"blocks/block[not(@ref)]\"/>\n\n     <div class=\"ptx-runestone-container\">\n        <div class=\"runestone hparsons_section\">\n            <div data-component=\"hparsons\" class=\"hparsons_section\">\n                <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n                <div class=\"hp_question\">\n                    <!-- the prompt -->\n                    <xsl:apply-templates select=\"statement\"/>\n                </div>\n                <!-- empty div seems necessary? -->\n                <div class=\"hparsons\"/>\n                <textarea style=\"visibility: hidden\">\n                    <!-- A SQL database can be provided for automated  -->\n                    <!-- testing of correct answers via unit tests.    -->\n                    <!-- This is a location in the external directory. -->\n                    <!-- NB: sample had paths with a leading backslash -->\n                    <xsl:if test=\"@database\">\n                        <xsl:attribute name=\"data-dburl\">\n                            <xsl:value-of select=\"$external-directory\"/>\n                            <xsl:value-of select=\"@database\"/>\n                        </xsl:attribute>\n                    </xsl:if>\n                    <!-- for natural language, just skip attribute -->\n                    <xsl:if test=\"not($b-natural)\">\n                        <xsl:attribute name=\"data-language\">\n                            <xsl:value-of select=\"$active-language\"/>\n                        </xsl:attribute>\n                    </xsl:if>\n                    <!-- default is to randomize, so only set -->\n                    <!-- to \"false\" when explicitly requested -->\n                    <xsl:attribute name=\"data-randomize\">\n                        <xsl:choose>\n                            <xsl:when test=\"$b-randomize\">\n                                <xsl:text>true</xsl:text>\n                            </xsl:when>\n                            <xsl:otherwise>\n                                <xsl:text>false</xsl:text>\n                            </xsl:otherwise>\n                        </xsl:choose>\n                    </xsl:attribute>\n                    <!-- default is to not allow reuse, so only  -->\n                    <!-- set to \"true\" when explicitly requested -->\n                    <xsl:attribute name=\"data-reuse\">\n                        <xsl:choose>\n                            <xsl:when test=\"$b-reuse\">\n                                <xsl:text>true</xsl:text>\n                            </xsl:when>\n                            <xsl:otherwise>\n                                <xsl:text>false</xsl:text>\n                            </xsl:otherwise>\n                        </xsl:choose>\n                    </xsl:attribute>\n                    <!-- the @blockanswer attribute is a space-separated  -->\n                    <!-- list of the block numbers, *in the order listed  -->\n                    <!-- in the HTML* (see below), starting at zero, that -->\n                    <!-- consitutes a correct answer.  But the authored   -->\n                    <!-- order is the corrrect answer, so we loop over    -->\n                    <!-- those blocks as we determine positions/locations -->\n                    <!-- in the HTML list.                                -->\n                    <!-- NB: the \"blockanswer\" appears to be parsed based  -->\n                    <!-- on *exactly* one space between separating indices -->\n                    <xsl:variable name=\"blockanswer\">\n                        <!-- answer is list as long as authored blocks, -->\n                        <!-- so loop over authored in every case        -->\n                        <xsl:for-each select=\"$authored-blocks\">\n                            <!-- save off the block in question before context shifts below -->\n                            <xsl:variable name=\"the-block\" select=\".\"/>\n                            <xsl:choose>\n                                <!-- Randomized or not (below), a distractor is a distractor  -->\n                                <!-- and does not go in the \"blockanswer\" attribute. -->\n                                <xsl:when test=\"@correct = 'no'\"/>\n                                <!-- For the randomized case the answer is list of       -->\n                                <!-- non-negative integers in order, but interrupted     -->\n                                <!-- by duplicates authored as references as references. -->\n                                <xsl:when test=\"$b-randomize\">\n                                    <xsl:choose>\n                                        <!-- placeholder/pointer/resuse, locate origin -->\n                                        <xsl:when test=\"@ref\">\n                                            <xsl:variable name=\"target\" select=\"id(@ref)\"/>\n                                            <!-- error-check $target here? -->\n                                            <xsl:for-each select=\"$unique-blocks\">\n                                                <xsl:if test=\"count(.|$target) = 1\">\n                                                    <xsl:value-of select=\"position() - 1\"/>\n                                                </xsl:if>\n                                            </xsl:for-each>\n                                        </xsl:when>\n                                        <!-- \"original\" block, count place among originals -->\n                                        <xsl:otherwise>\n                                            <xsl:for-each select=\"$unique-blocks\">\n                                                <xsl:if test=\"count(.|$the-block) = 1\">\n                                                    <xsl:value-of select=\"position() - 1\"/>\n                                                </xsl:if>\n                                            </xsl:for-each>\n                                        </xsl:otherwise>\n                                    </xsl:choose>\n                                </xsl:when>\n                                <!-- For the fixed rearrangement case, the blocks are    -->\n                                <!-- rearranged in the HTML, so we re-create that        -->\n                                <!-- order when determining the location/number of any   -->\n                                <!-- given block.  The \"choose\" stanza here is identical -->\n                                <!-- to the above, except the unique blocks are sorted   -->\n                                <!-- into their HTML order.  (Can't see how to vary an   -->\n                                <!-- unsorted list versus a sorted list as a parameter   -->\n                                <!-- to remove duplication.)                             -->\n                                <xsl:otherwise>\n                                    <xsl:choose>\n                                        <!-- placeholder/pointer/resuse, locate origin -->\n                                        <xsl:when test=\"@ref\">\n                                            <xsl:variable name=\"target\" select=\"id(@ref)\"/>\n                                            <!-- error-check $target here? -->\n                                            <xsl:for-each select=\"$unique-blocks\">\n                                                <xsl:sort select=\"@order\"/>\n                                                <xsl:if test=\"count(.|$target) = 1\">\n                                                    <xsl:value-of select=\"position() - 1\"/>\n                                                </xsl:if>\n                                            </xsl:for-each>\n                                        </xsl:when>\n                                        <!-- \"original\" block, count place among originals -->\n                                        <xsl:otherwise>\n                                            <xsl:for-each select=\"$unique-blocks\">\n                                                <xsl:sort select=\"@order\"/>\n                                                <xsl:if test=\"count(.|$the-block) = 1\">\n                                                    <xsl:value-of select=\"position() - 1\"/>\n                                                </xsl:if>\n                                            </xsl:for-each>\n                                        </xsl:otherwise>\n                                    </xsl:choose>\n                                </xsl:otherwise>\n                            </xsl:choose>\n                            <!-- space-separated list, per block, one extra at the very end -->\n                            <!-- when a distractor is skipped, do not place a separator     -->\n                            <xsl:if test=\"not(@correct= 'no')\">\n                                <xsl:text> </xsl:text>\n                            </xsl:if>\n                        </xsl:for-each>\n                    </xsl:variable>\n                    <!-- strip an extra space separator created just above -->\n                    <xsl:attribute name=\"data-blockanswer\">\n                        <xsl:value-of select=\"substring($blockanswer, 1, string-length($blockanswer) - 1)\"/>\n                    </xsl:attribute>\n                    <!-- blocks themselves, left justified on margin      -->\n                    <!-- reused blocks are not presented, distractors are -->\n                    <!-- leading newline is just cosmetic                 -->\n                    <xsl:text>&#xa;--blocks--&#xa;</xsl:text>\n                    <xsl:choose>\n                        <!-- just go with authored order as canonical -->\n                        <xsl:when test=\"$b-randomize\">\n                            <xsl:apply-templates select=\"$unique-blocks\" mode=\"horizontal-blocks\">\n                                <xsl:with-param name=\"b-natural\" select=\"$b-natural\"/>\n                            </xsl:apply-templates>\n                        </xsl:when>\n                        <!-- sort by the order provided  by author -->\n                        <xsl:otherwise>\n                            <xsl:for-each select=\"$unique-blocks\">\n                                <xsl:sort select=\"@order\"/>\n                                <xsl:apply-templates select=\".\" mode=\"horizontal-blocks\">\n                                    <xsl:with-param name=\"b-natural\" select=\"$b-natural\"/>\n                                </xsl:apply-templates>\n                            </xsl:for-each>\n                        </xsl:otherwise>\n                    </xsl:choose>\n                    <!-- a block of unit tests for automatic feedback (with, say, an SQL database) -->\n                    <!-- NB: could mimic \"program/tests\" to avoid empty \"tests\" elements           -->\n                    <xsl:if test=\"tests\">\n                        <xsl:text>--unittest--&#xa;</xsl:text>\n                        <xsl:call-template name=\"sanitize-text\">\n                            <xsl:with-param name=\"text\" select=\"tests\" />\n                        </xsl:call-template>\n                    </xsl:if>\n                </textarea>\n            </div>\n        </div>\n    </div>\n</xsl:template>\n\n<!-- Assumes a \"tight\" run of text, or a \"c\", no newlines authored. -->\n<!-- Non-reused block.  Perhaps text should be massaged here?       -->\n<!-- We do not ever dump duplicates into HTML or to the reader      -->\n<xsl:template match=\"blocks/block[not(@ref)]\" mode=\"horizontal-blocks\">\n    <xsl:param name=\"b-natural\"/>\n\n    <xsl:choose>\n        <xsl:when test=\"$b-natural\">\n            <xsl:apply-templates select=\".\"/>\n        </xsl:when>\n        <!-- Now this a problem with code, requiring a \"c\" wrapper -->\n        <!-- 2023-03-07: can move to warnings or validation-plus, semi-deprecated -->\n        <xsl:when test=\"not(c)\">\n            <xsl:message>PTX:WARNING:  a block of a horizontal Parson problem with</xsl:message>\n            <xsl:message>              code needs to be enclosed in a \"c\" element</xsl:message>\n            <xsl:apply-templates select=\".\"/>\n            <xsl:text> (NEEDS \"c\" ELEMENT)</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"c\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n    <xsl:text>&#xa;</xsl:text>\n</xsl:template>\n\n<!-- Carsort Problem -->\n\n<xsl:template match=\"*[@pi:exercise-interactive = 'cardsort']\" mode=\"runestone-to-interactive\">\n    <div class=\"ptx-runestone-container\">\n        <div class=\"runestone cardsort_section\">\n            <ul data-component=\"dragndrop\" data-question_label=\"\" style=\"visibility: hidden;\">\n                <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n                <span data-subcomponent=\"question\">\n                    <xsl:apply-templates select=\"statement\"/>\n                </span>\n                <xsl:if test=\"feedback\">\n                    <span data-subcomponent=\"feedback\">\n                        <xsl:apply-templates select=\"feedback\"/>\n                    </span>\n                </xsl:if>\n                <!-- NB: need to compute Runestone ID in current context -->\n                <!-- and save off before changing context with for-each  -->\n                <xsl:variable name=\"rsid\">\n                    <xsl:apply-templates select=\".\" mode=\"runestone-id\"/>\n                </xsl:variable>\n                <xsl:for-each select=\"cardsort/match\">\n\n                    <!-- PTX premise = RS draggable -->\n                    <!-- may be multiple premise or none -->\n                    <xsl:for-each select=\"premise\">\n                        <li data-subcomponent=\"draggable\">\n                            <xsl:attribute name=\"id\">\n                                <xsl:value-of select=\"$rsid\"/>\n                                <xsl:text>_drag</xsl:text>\n                                <xsl:number count=\"premise\" from=\"cardsort\" level=\"any\"/>\n                            </xsl:attribute>\n                            <xsl:apply-templates select=\"parent::match\" mode=\"category-attribute\"/>\n                            <xsl:apply-templates select=\".\"/>\n                        </li>\n                    </xsl:for-each>\n                    <!-- PTX response = RS dropzone -->\n                    <!-- one response, or none -->\n                    <xsl:for-each select=\"response\">\n                        <li data-subcomponent=\"dropzone\">\n                            <xsl:attribute name=\"for\">\n                                <xsl:value-of select=\"$rsid\"/>\n                                <xsl:text>_drag</xsl:text>\n                                <xsl:number count=\"response\" from=\"cardsort\" level=\"any\"/>\n                            </xsl:attribute>\n                            <xsl:apply-templates select=\"parent::match\" mode=\"category-attribute\"/>\n                            <xsl:apply-templates select=\".\"/>\n                        </li>\n                    </xsl:for-each>\n                </xsl:for-each>\n            </ul>\n        </div>\n    </div>\n</xsl:template>\n\n<!-- A \"category\" is simply the sequence number of an     -->\n<!-- enclosing \"match\" element, which serves to group     -->\n<!-- any number of \"premise\" with zero or one \"response\", -->\n<!-- indicating they have a relationship (they match!).   -->\n<xsl:template match=\"match\" mode=\"category-attribute\">\n    <xsl:attribute name=\"data-category\">\n        <!-- no @count, then implies count=\"match\" (peers),   -->\n        <!-- from=\"cardsort\", while @level=\"single\" is default -->\n        <xsl:number/>\n    </xsl:attribute>\n</xsl:template>\n\n<!-- Matching Problem -->\n\n<xsl:template match=\"*[@pi:exercise-interactive = 'matching']\" mode=\"runestone-to-interactive\">\n    <div class=\"ptx-runestone-container\">\n        <div data-component=\"matching\" class=\"runestone\">\n            <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n            <!-- Note: Runestone will condition on script/@type as -->\n            <!-- it handles this (mostly to differentiate between  -->\n            <!-- JSON blobs.  Note below describes how this is     -->\n            <!-- really HTML, not XML.  So any adjustment here     -->\n            <!-- must be coordinated with the Runestone consumer.  -->\n            <script type=\"text/xml\">\n                <!-- one-off XML for Runestone JS to consume -->\n                <matching>\n                    <!-- Provide authored statement of the exercise. -->\n                    <!-- Here, and elsewhere, we need to be careful. -->\n                    <!-- We want to produce XML, but a rendered      -->\n                    <!-- \"statement\" will be HTML and have some      -->\n                    <!-- undesirable things, like unclosed tags      -->\n                    <!-- (e.g. \"img\").  We really want what was once -->\n                    <!-- called XHTML.  Our made-up XML below seems  -->\n                    <!-- to be OK when parsed as if it were HTML.    -->\n                    <statement>\n                        <xsl:apply-templates select=\"statement\"/>\n                    </statement>\n                    <!-- \"feedback\" is for the interactive interface -->\n                    <!-- to show to the reader at the right time     -->\n                    <feedback>\n                        <xsl:apply-templates select=\"feedback\"/>\n                    </feedback>\n                    <!-- sequence of \"premise\" -->\n                    <xsl:apply-templates select=\"matching/premise\" mode=\"node-info\"/>\n                    <!-- sequence of \"response\" -->\n                    <xsl:apply-templates select=\"matching/response\" mode=\"node-info\"/>\n                    <!-- sequence of \"edge\" -->\n                    <xsl:apply-templates select=\"matching\" mode=\"matching-adjacencies\"/>\n                </matching>\n            </script>\n        </div>\n    </div>\n</xsl:template>\n\n<!-- utility template to create unique ID for each premise and       -->\n<!-- response for use in the user interface, invisible to the reader -->\n<xsl:template match=\"matching/premise|matching/response\" mode=\"matching-identification\">\n    <xsl:value-of select=\"parent::matching/parent::*/@label\"/>\n    <xsl:text>-</xsl:text>\n    <xsl:choose>\n        <xsl:when test=\"self::premise\">\n            <xsl:text>p</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"self::response\">\n            <xsl:text>r</xsl:text>\n        </xsl:when>\n    </xsl:choose>\n    <!-- counts among elements of current type -->\n    <xsl:number/>\n</xsl:template>\n\n<xsl:template match=\"premise|response\" mode=\"node-info\">\n    <xsl:variable name=\"element-name\" select=\"local-name(.)\"/>\n    <xsl:element name=\"{$element-name}\">\n        <id>\n            <xsl:apply-templates select=\".\" mode=\"matching-identification\"/>\n        </id>\n        <label>\n            <xsl:apply-templates select=\".\"/>\n        </label>\n    </xsl:element>\n</xsl:template>\n\n\n<xsl:template match=\"matching\" mode=\"matching-adjacencies\">\n    <!-- Run over all response, to see if their single @xml:id -->\n    <!-- is present in the premise's multi-valued @ref         -->\n    <!-- array of pairs -->\n    <xsl:for-each select=\"premise\">\n        <!-- save off some \"premise\" info before context change -->\n        <xsl:variable name=\"the-ref-fenced\" select=\"concat('|', translate(@ref, ' ', '|'), '|')\"/>\n        <xsl:variable name=\"the-premise-identification\">\n            <xsl:apply-templates select=\".\" mode=\"matching-identification\"/>\n        </xsl:variable>\n        <!-- note context is no longer \"matching\", so step up -->\n        <xsl:for-each select=\"../response\">\n            <xsl:variable name=\"response-xmlid-fenced\" select=\"concat('|', @xml:id, '|')\"/>\n            <!-- finally, the test for adjacency -->\n            <xsl:if test=\"contains($the-ref-fenced, $response-xmlid-fenced)\">\n                <!-- a pair, connecting \"premise\" to \"response\"-->\n                <edge>\n                    <label>\n                        <!-- \"matching-identification\", saved off above -->\n                        <xsl:value-of select=\"$the-premise-identification\"/>\n                    </label>\n                    <label>\n                        <xsl:apply-templates select=\".\" mode=\"matching-identification\"/>\n                    </label>\n                </edge>\n            </xsl:if>\n        </xsl:for-each>\n    </xsl:for-each>\n</xsl:template>\n\n\n<!-- Clickable Area Problem -->\n\n<xsl:template match=\"*[@pi:exercise-interactive = 'clickablearea']\" mode=\"runestone-to-interactive\">\n    <div class=\"ptx-runestone-container\">\n        <div class=\"runestone clickablearea_section\">\n            <div data-component=\"clickablearea\" data-question_label=\"\" style=\"visibility: hidden;\">\n                <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n                <span data-question=\"\">\n                    <xsl:apply-templates select=\"statement\"/>\n                </span>\n                <span data-feedback=\"\">\n                    <xsl:apply-templates select=\"feedback\"/>\n                </span>\n                <xsl:apply-templates select=\"areas\" mode=\"clickable-html\"/>\n            </div>\n        </div>\n    </div>\n</xsl:template>\n\n<!-- We use modal templates, primarily for the case of code, -->\n<!-- so we do not mangle text() using routines in -common    -->\n<!-- and to preserve the structure of the program.           -->\n\n<xsl:template match=\"areas\" mode=\"clickable-html\">\n    <xsl:choose>\n        <xsl:when test=\"cline\">\n            <!-- code, so make the \"pre\" structure -->\n            <pre>\n                <xsl:apply-templates select=\"cline\" mode=\"clickable-html\"/>\n            </pre>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- regular text, this will match a default template later -->\n            <xsl:apply-templates select=\"*\" mode=\"clickable-html\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- A mix of text and \"area\", and needs a newline -->\n<xsl:template match=\"areas/cline\" mode=\"clickable-html\">\n    <xsl:apply-templates select=\"text()|area\" mode=\"clickable-html\"/>\n    <xsl:text>&#xa;</xsl:text>\n</xsl:template>\n\n<!-- Avoid falling into low-level manipulations to remain verbatim -->\n<xsl:template match=\"areas/cline/text()\" mode=\"clickable-html\">\n    <xsl:value-of select=\".\"/>\n</xsl:template>\n\n<!-- Constructions for regular text (\"p\", \"ul\", etc) should   -->\n<!-- drop out to default templates, as will an \"area\" element -->\n<!-- (both code and regular text).                            -->\n<xsl:template match=\"*\" mode=\"clickable-html\">\n    <xsl:apply-templates select=\".\"/>\n</xsl:template>\n\n<!-- NB: we want a generic template (not modal) for use within      -->\n<!-- sentences, etc.  As such it will then be available in every    -->\n<!-- derived conversion, *but* the \"area\" element should not        -->\n<!-- survive a conversion to a static form, so will not be present. -->\n<xsl:template match=\"area\">\n    <span>\n        <xsl:choose>\n            <xsl:when test=\"@correct = 'no'\">\n                <xsl:attribute name=\"data-incorrect\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:attribute name=\"data-correct\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n        <xsl:apply-templates/>\n    </span>\n</xsl:template>\n\n<!-- Select Questions -->\n\n<!-- \"Select\" questions come in three types                            -->\n<!--   * Question List - several equivalent problems,                  -->\n<!--     reader is assigned just one (good for exams)                  -->\n<!--   * A/B Experiment - two choices, experiment managed by Runestone -->\n<xsl:template match=\"*[@pi:exercise-interactive = 'select']\" mode=\"runestone-to-interactive\">\n    <!-- identify the type of \"select\"                -->\n    <!-- duplicated in \"pretext-runestone-static.xsl\" -->\n    <xsl:variable name=\"select-variant\">\n        <xsl:choose>\n            <!-- Runestone JS picks a random problem from many-->\n            <xsl:when test=\"select/@grade='random'\">\n                <xsl:text>random</xsl:text>\n            </xsl:when>\n            <!-- Two questions, split across roster into A, B groups. -->\n            <xsl:when test=\"select/@grade='ab-experiment'\">\n                <xsl:text>ab-experiment</xsl:text>\n            </xsl:when>\n            <!-- Two questions (usually), the first will always be graded,  -->\n            <!-- while any others may be worked and may be helpful.         -->\n            <!-- Colloquially known as a \"toggle lock\" question.            -->\n            <xsl:when test=\"select/@grade='first'\">\n                <xsl:text>first</xsl:text>\n            </xsl:when>\n            <!-- Two questions (usually), any one may be     -->\n            <!-- chosen by the reader to be graded.          -->\n            <!-- Colloquially known as a \"toggle \" question. -->\n            <xsl:when test=\"select/@grade='any'\">\n                <xsl:text>any</xsl:text>\n            </xsl:when>\n            <!-- default to \"random\" selection -->\n            <xsl:otherwise>\n                <xsl:text>random</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!--  -->\n    <div class=\"ptx-runestone-container\">\n        <div class=\"runestone sqcontainer selectquestion_section\">\n            <div data-component=\"selectquestion\" data-points=\"1\" data-limit-basecourse=\"false\">\n                <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n                <!-- attributes vary by type of select question -->\n                <xsl:choose>\n                    <!-- no attributes for generic selection -->\n                    <xsl:when test=\"$select-variant='random'\"/>\n                    <!-- @experiment name is required (and is a signal) -->\n                    <xsl:when test=\"$select-variant='ab-experiment'\">\n                         <xsl:attribute name=\"data-ab\">\n                            <xsl:value-of select=\"select/@experiment-name\"/>\n                        </xsl:attribute>\n                    </xsl:when>\n                    <!-- set lock on first question -->\n                    <xsl:when test=\"$select-variant='first'\">\n                        <xsl:attribute name=\"data-toggleoptions\">\n                            <xsl:text>toggle, lock</xsl:text>\n                        </xsl:attribute>\n                        <xsl:attribute name=\"data-togglelabels\">\n                            <xsl:text>togglelabels:</xsl:text>\n                        </xsl:attribute>\n                    </xsl:when>\n                    <!-- allow any question to be chosen by reader -->\n                    <xsl:when test=\"$select-variant='any'\">\n                        <xsl:attribute name=\"data-toggleoptions\">\n                            <xsl:text>toggle</xsl:text>\n                        </xsl:attribute>\n                        <xsl:attribute name=\"data-togglelabels\">\n                            <xsl:text>togglelabels:</xsl:text>\n                        </xsl:attribute>\n                    </xsl:when>\n                </xsl:choose>\n                <!-- always form the list of ids for the questions -->\n                <xsl:attribute name=\"data-questionlist\">\n                    <xsl:call-template name=\"runestone-targets\">\n                        <xsl:with-param name=\"id-list\" select=\"select/@questions\"/>\n                        <xsl:with-param name=\"separator\" select=\"', '\"/>\n                    </xsl:call-template>\n                </xsl:attribute>\n                <p>Loading a select question (grading type: <xsl:value-of select=\"$select-variant\"/>)...</p>\n            </div>\n        </div>\n    </div>\n</xsl:template>\n\n\n<!-- Fill-in-the-Blanks problem -->\n\n<!-- Runestone structure -->\n<xsl:template match=\"*[@pi:exercise-interactive = 'fillin-basic']\" mode=\"runestone-to-interactive\">\n    <div class=\"ptx-runestone-container\">\n        <div class=\"runestone fillintheblank_section\">\n            <!-- dropped \"visibility: hidden\" on next div -->\n            <div data-component=\"fillintheblank\" data-question_label=\"\">\n                <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n                <xsl:apply-templates select=\"statement\"/>\n                <script type=\"application/json\">\n                    <xsl:apply-templates select=\"setup\" mode=\"json-conditions\"/>\n                </script>\n            </div>\n        </div>\n    </div>\n</xsl:template>\n\n<!-- simple substitution in output -->\n<xsl:template match=\"exercise/statement//var\">\n    <!-- NB: this code is used in formulating static representations -->\n    <!-- count location of (context) \"var\" in problem statement      -->\n    <xsl:variable name=\"location\">\n        <xsl:number from=\"statement\"/>\n    </xsl:variable>\n    <!-- locate corresponding \"var\" in \"setup\" -->\n    <xsl:variable name=\"setup-var\" select=\"ancestor::exercise/setup/var[position() = $location]\"/>\n\n    <!-- Know can tell what sort of data goes into the form entry -->\n    <xsl:variable name=\"placeholder-hint\">\n        <xsl:choose>\n            <xsl:when test=\"$setup-var/condition[1]/@number\">\n                <xsl:text>Number</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"$setup-var/condition[1]/@string\">\n                <xsl:text>Text</xsl:text>\n            </xsl:when>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- the actual form fill-in, with hint and width -->\n    <input type=\"text\" placeholder=\"{$placeholder-hint}\">\n        <xsl:if test=\"@width\">\n            <xsl:attribute name=\"size\">\n                <xsl:value-of select=\"@width\"/>\n            </xsl:attribute>\n        </xsl:if>\n    </input>\n</xsl:template>\n\n<!-- JSON list-of-list structure -->\n<xsl:template match=\"exercise/setup\"  mode=\"json-conditions\">\n    <!-- outermost list begin -->\n    <xsl:text>[</xsl:text>\n    <xsl:for-each select=\"var\">\n        <!-- per-var list begin -->\n        <xsl:text>[</xsl:text>\n        <xsl:for-each select=\"condition\">\n            <!-- where the real content originates -->\n            <xsl:apply-templates select=\".\" mode=\"condition-to-json\"/>\n            <!-- separate dictionaries for conditions -->\n            <xsl:if test=\"following-sibling::condition\">\n                <xsl:text>, </xsl:text>\n            </xsl:if>\n        </xsl:for-each>\n        <!-- per-var list end -->\n        <xsl:text>]</xsl:text>\n        <!-- separate vars -->\n        <xsl:if test=\"following-sibling::var\">\n            <xsl:text>, </xsl:text>\n        </xsl:if>\n    </xsl:for-each>\n    <!-- outermost list end -->\n    <xsl:text>]</xsl:text>\n</xsl:template>\n\n<!-- JSON dictionary for numerical condition -->\n<xsl:template match=\"setup/var/condition[@number]\" mode=\"condition-to-json\">\n    <!-- per-condition dictionary begin -->\n    <xsl:text>{</xsl:text>\n    <xsl:text>\"number\": [</xsl:text>\n    <xsl:choose>\n        <xsl:when test=\"@tolerance\">\n            <xsl:value-of select=\"@number - @tolerance\"/>\n            <xsl:text>,</xsl:text>\n            <xsl:value-of select=\"@number + @tolerance\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"@number\"/>\n            <xsl:text>, </xsl:text>\n            <xsl:value-of select=\"@number\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n    <xsl:text>]</xsl:text>\n    <xsl:if test=\"feedback\">\n        <xsl:text>, \"feedback\": \"</xsl:text>\n        <xsl:apply-templates select=\"feedback\" mode=\"serialize-feedback\"/>\n        <xsl:text>\"</xsl:text>\n    </xsl:if>\n    <!-- per-condition dictionary end -->\n    <xsl:text>}</xsl:text>\n</xsl:template>\n\n<!-- JSON dictionary for string condition -->\n<xsl:template match=\"setup/var/condition[@string]\" mode=\"condition-to-json\">\n    <!-- per-condition dictionary begin -->\n    <xsl:text>{</xsl:text>\n    <!-- regex string match, drop    -->\n    <!-- leading/trailing whitespace -->\n    <xsl:text>\"regex\": \"</xsl:text>\n    <!-- JSON escapes necessary for regular expression -->\n    <xsl:call-template name=\"escape-json-string\">\n        <xsl:with-param name=\"text\">\n            <xsl:text>^\\s*</xsl:text>\n            <xsl:value-of select=\"@string\"/>\n            <xsl:text>\\s*$</xsl:text>\n        </xsl:with-param>\n    </xsl:call-template>\n    <xsl:text>\"</xsl:text>\n    <!-- flag for case-sensitive match -->\n    <!-- default:  'sensitive'         -->\n    <xsl:text>, \"regexFlags\": \"</xsl:text>\n    <xsl:if test=\"parent::var/@case = 'insensitive'\">\n        <xsl:text>i</xsl:text>\n    </xsl:if>\n    <xsl:text>\"</xsl:text>\n    <!-- optional feedback -->\n    <xsl:if test=\"feedback\">\n        <xsl:text>, \"feedback\": \"</xsl:text>\n        <xsl:apply-templates select=\"feedback\" mode=\"serialize-feedback\"/>\n        <xsl:text>\"</xsl:text>\n    </xsl:if>\n    <!-- per-condition dictionary end -->\n    <xsl:text>}</xsl:text>\n</xsl:template>\n\n<xsl:template match=\"setup/var/condition/feedback\" mode=\"serialize-feedback\">\n    <xsl:variable name=\"feedback-rtf\">\n        <xsl:apply-templates select=\".\"/>\n    </xsl:variable>\n    <!-- serialize HTML as text, then escape as JSON -->\n    <xsl:call-template name=\"escape-json-string\">\n        <xsl:with-param name=\"text\">\n            <xsl:apply-templates select=\"exsl:node-set($feedback-rtf)\" mode=\"xml-to-string\"/>\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n\n<!-- Coding exercise -->\n\n<xsl:template match=\"*[@pi:exercise-interactive = 'coding']\" mode=\"runestone-to-interactive\">\n    <!-- We don't have a 'coding' attribute value  -->\n    <!-- unless one of the two tests below is true -->\n    <xsl:choose>\n        <xsl:when test=\"program/@interactive = 'codelens'\">\n            <xsl:apply-templates select=\"program\" mode=\"runestone-codelens\">\n                <xsl:with-param name=\"exercise-statement\" select=\"statement\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n        <xsl:when test=\"program/@interactive = 'activecode'\">\n            <xsl:apply-templates select=\"program\" mode=\"runestone-activecode\">\n                <xsl:with-param name=\"exercise-statement\" select=\"statement\"/>\n            </xsl:apply-templates>\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- Dual Form exercise (dynamic/static)-->\n\n<!-- 2025-11-11: Runestone HTML is speculative -->\n<xsl:template match=\"*[@pi:exercise-interactive = 'dual']\" mode=\"runestone-to-interactive\">\n    <div class=\"ptx-runestone-container\">\n        <div class=\"runestone dualquestion_section\">\n            <div data-component=\"dual\">\n                <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n                <!-- Assume only \"p\" and a single \"interactive\".  The -->\n                <!-- \"p\" could be expanded to include some options.   -->\n                <xsl:apply-templates select=\"statement/p|statement/interactive[1]\"/>\n            </div>\n        </div>\n    </div>\n</xsl:template>\n\n\n<!-- Short Answer problem -->\n\n<!-- Traditional form, but not converted like other interactive exercises -->\n<!-- Won't match indiscriminately, there is some control over when to be  -->\n<!-- interactive, see \"static\" v. \"dynamic\" publisher variables.          -->\n<!-- NB - not currently applying to short-form with no \"statement\" -->\n<!-- NB: match is recycled in manifest formation                   -->\n<xsl:template match=\"*[@pi:exercise-interactive = 'shortanswer']\" mode=\"runestone-to-interactive\">\n    <xsl:choose>\n        <xsl:when test=\"$b-host-runestone or ($short-answer-responses = 'always')\">\n            <!-- when \"response\" has attributes, perhaps they get interpreted here -->\n            <div class=\"ptx-runestone-container\">\n                <div class=\"runestone shortanswer_section\">\n                    <div data-component=\"shortanswer\" data-question_label=\"\" class=\"journal\" data-mathjax=\"\">\n                        <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n                        <!-- showing a box, but it can't be graded, so warn reader -->\n                        <xsl:if test=\"not($b-host-runestone)\">\n                            <xsl:attribute name=\"data-placeholder\">\n                                <xsl:text>You can write here, and it will be saved on this device, but your response will not be graded.</xsl:text>\n                            </xsl:attribute>\n                        </xsl:if>\n                        <!-- Author can indicate problem expects an  -->\n                        <!-- attachment. Effectively, default is no. -->\n                        <xsl:if test=\"(@attachment = 'yes') and $b-host-runestone\">\n                            <xsl:attribute name=\"data-attachment\"/>\n                        </xsl:if>\n                        <xsl:apply-templates select=\"statement\"/>\n                    </div>\n                </div>\n            </div>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- pointless to do fancy outside of a server/LMS situation -->\n            <xsl:apply-templates select=\"statement\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- YouTube Video -->\n<!-- When hosted on a Runestone server, we use a different embedding  -->\n<!-- for a YouTube video (only), which allows using a YouTube API for -->\n<!-- monitoring events from readers.  We have to pass in an actual    -->\n<!-- height and width (in pixels) for semi-custom attributes here.    -->\n<!-- Many PreTeXt video features (like posters) are lost.             -->\n<!-- The Runestone JavaScript will automatically include the          -->\n<!-- player_api JavaScript after it has set up the appropriate        -->\n<!-- events such as API loaded.                                       -->\n\n<!-- TODO: are start/end attributes useful?      -->\n<xsl:template match=\"video[@youtube]\" mode=\"runestone-youtube-embed\">\n    <xsl:param name=\"width\"/>\n    <xsl:param name=\"height\"/>\n\n    <xsl:variable name=\"hid\">\n        <xsl:apply-templates select=\".\" mode=\"runestone-id\"/>\n    </xsl:variable>\n\n    <div class=\"ptx-runestone-container\">\n        <div class=\"runestone yt_section\">\n            <div id=\"{$hid}\" data-component=\"youtube\" class=\"align-left youtube-video\"\n                 data-video-height=\"{$height}\" data-video-width=\"{$width}\"\n                 data-video-videoid=\"{@youtube}\" data-video-divid=\"{$hid}\"\n                 data-video-start=\"0\" data-video-end=\"-1\"/>\n        </div>\n    </div>\n</xsl:template>\n\n<!-- ########### -->\n<!-- Active Code -->\n<!-- ########### -->\n\n<!-- Runestone has support for various languages.  Some    -->\n<!-- are \"in-browser\" while others are backed by \"real\"    -->\n<!-- compilers as part of a Runestone server.  For an      -->\n<!-- exercise, we pass in some lead-in text, which is      -->\n<!-- the directions for using the ActiveCode component.    -->\n<!-- This template does the best job possible:             -->\n<!--   1.  Unsupported language, static rendering.         -->\n<!--   2.  Supported in-browser, always interactive.       -->\n<!--   3.  On a Runestone server, always interactive.      -->\n<!--                                                       -->\n<!-- When a \"program\" is part of an exercise/project-like, -->\n<!-- then we need to get the problem \"statement\" absorbed  -->\n<!-- into the ActiveCode.  This is an authored \"statement\" -->\n<!-- passed in via the $exercise-statement parameter.      -->\n<!-- Other times a \"program\" is an atomic item             -->\n<!-- and surrounding text explains its purpose, hence      -->\n<!-- \"exercise-statment\" appropriately defaults to an      -->\n<!-- empty node-set.                                       -->\n<xsl:template match=\"program\" mode=\"runestone-activecode\">\n    <xsl:param name=\"exercise-statement\" select=\"/..\"/>\n    <xsl:variable name=\"active-language\">\n        <xsl:apply-templates select=\".\" mode=\"active-language\"/>\n    </xsl:variable>\n    <xsl:variable name=\"hosting\">\n        <xsl:apply-templates select=\".\" mode=\"activecode-host\"/>\n    </xsl:variable>\n    <!-- Use an id from the \"program\" element, unless employed -->\n    <!-- inside an exercise/project-like, which is up a level  -->\n    <!-- (and could be many different types of project-like).  -->\n    <xsl:variable name=\"rsid\">\n        <xsl:choose>\n            <xsl:when test=\"$exercise-statement\">\n                <xsl:apply-templates select=\"parent::*\" mode=\"runestone-id\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:apply-templates select=\".\" mode=\"runestone-id\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:choose>\n        <!-- unsupported on Runestone, period -->\n        <xsl:when test=\"$active-language = ''\">\n            <xsl:apply-templates select=\"$exercise-statement\"/>\n            <xsl:apply-templates select=\".\" mode=\"code-inclusion\"/>\n        </xsl:when>\n        <!-- needs server, and we aren't there -->\n        <xsl:when test=\"($hosting = 'jobeserver') and not($b-host-runestone)\">\n            <xsl:apply-templates select=\"$exercise-statement\"/>\n            <xsl:apply-templates select=\".\" mode=\"code-inclusion\"/>\n        </xsl:when>\n        <!-- this is the logical negation of the previous, so could be \"otherwise\" -->\n        <xsl:when test=\"($hosting = 'browser') or $b-host-runestone\">\n            <div class=\"ptx-runestone-container\">\n                <div class=\"runestone explainer ac_section \">\n                    <div data-component=\"activecode\">\n                        <xsl:attribute name=\"id\">\n                            <xsl:value-of select=\"$rsid\"/>\n                        </xsl:attribute>\n                        <!-- filename used for this data if another program makes use of it -->\n                        <!-- via add-files                                                  -->\n                        <xsl:if test=\"@filename\">\n                            <xsl:attribute name=\"data-filename\">\n                                <xsl:value-of select=\"@filename\"/>\n                            </xsl:attribute>\n                        </xsl:if>\n                        <!-- add some lead-in text to the window -->\n                        <xsl:if test=\"$exercise-statement\">\n                            <div class=\"ac_question exercise-statement\">\n                                <xsl:attribute name=\"id\">\n                                    <xsl:value-of select=\"$rsid\"/>\n                                    <xsl:text>_question</xsl:text>\n                                </xsl:attribute>\n                                <xsl:apply-templates select=\"$exercise-statement\"/>\n                            </div>\n                        </xsl:if>\n                        <textarea data-lang=\"{$active-language}\" data-audio=\"\" data-coach=\"true\" style=\"visibility: hidden;\">\n                            <xsl:if test=\"stdin\">\n                                <xsl:attribute name=\"data-stdin\">\n                                    <xsl:call-template name=\"sanitize-text\">\n                                        <xsl:with-param name=\"text\" select=\"stdin\" />\n                                    </xsl:call-template>\n                                </xsl:attribute>\n                            </xsl:if>\n                            <xsl:attribute name=\"id\">\n                                <xsl:value-of select=\"$rsid\"/>\n                                <xsl:text>_editor</xsl:text>\n                            </xsl:attribute>\n                            <!-- conditional attributes shared with parsons activecodes -->\n                            <xsl:call-template name=\"runestone-activecode-editor-attributes\">\n                                <xsl:with-param name=\"active-language\" select=\"$active-language\"/>\n                                <xsl:with-param name=\"hosting\" select=\"$hosting\"/>\n                            </xsl:call-template>\n                            <!-- CodeTailor: when an author requests it, emit the data       -->\n                            <!-- The presence of @codetailor has Runestone offer the reader   -->\n                            <!-- an automatically-personalized Parsons puzzle as scaffolding  -->\n                            <!-- (a \"Get Help\" button) when they are stuck on the exercise.   -->\n                            <!-- The value \"all\" scrambles a complete solution, while         -->\n                            <!-- \"incorrect\" locks blocks the reader already has right, so    -->\n                            <!-- only wrong ones move.  A @codetailor-fallback names, by      -->\n                            <!-- @xml:id, a Parsons problem of this document to present when  -->\n                            <!-- a personalized puzzle cannot be generated; in its absence,   -->\n                            <!-- generation is always requested.                              -->\n                            <xsl:if test=\"@codetailor\">\n                                <xsl:attribute name=\"data-parsonspersonalize\">\n                                    <xsl:choose>\n                                        <xsl:when test=\"@codetailor = 'incorrect'\">\n                                            <xsl:text>partial</xsl:text>\n                                        </xsl:when>\n                                        <!-- \"all\", the only other value the schema admits -->\n                                        <xsl:otherwise>\n                                            <xsl:text>movable</xsl:text>\n                                        </xsl:otherwise>\n                                    </xsl:choose>\n                                </xsl:attribute>\n                                <xsl:attribute name=\"data-parsonsexample\">\n                                    <xsl:choose>\n                                        <xsl:when test=\"@codetailor-fallback\">\n                                            <xsl:call-template name=\"runestone-targets\">\n                                                <xsl:with-param name=\"id-list\" select=\"@codetailor-fallback\"/>\n                                                <xsl:with-param name=\"separator\" select=\"''\"/>\n                                            </xsl:call-template>\n                                        </xsl:when>\n                                        <xsl:otherwise>\n                                            <xsl:text>LLM-example</xsl:text>\n                                        </xsl:otherwise>\n                                    </xsl:choose>\n                                </xsl:attribute>\n                            </xsl:if>\n                            <!-- This is a bit awful, but we need to figure out how much margin     -->\n                            <!-- to add to runestone dividers. It must match indentation used for   -->\n                            <!-- the overall program.                                               -->\n                            <!-- To avoid as much as possible of the duplicate work, clean each     -->\n                            <!-- part and store those for reuse later.                              -->\n                            <xsl:variable name=\"program-preamble-trimmed\">\n                                <xsl:apply-templates select=\"preamble\" mode=\"program-part-processing\"/>\n                            </xsl:variable>\n                            <xsl:variable name=\"program-code-trimmed\">\n                                <xsl:apply-templates select=\"code\" mode=\"program-part-processing\"/>\n                            </xsl:variable>\n                            <xsl:variable name=\"program-postamble-trimmed\">\n                                <xsl:apply-templates select=\"postamble\" mode=\"program-part-processing\"/>\n                            </xsl:variable>\n                            <!-- Now temporarily assemble to count left margin spaces                -->\n                            <xsl:variable name=\"program-left-margin\">\n                                <xsl:call-template name=\"count-pad-length\">\n                                    <xsl:with-param name=\"text\">\n                                        <!-- need to clear any blank line left by empty preamble and/or -->\n                                        <!-- leading blank lines at the start of code if no preamble    -->\n                                        <xsl:call-template name=\"trim-start-lines\">\n                                            <xsl:with-param name=\"text\">\n                                                <xsl:value-of select=\"$program-preamble-trimmed\"/>\n                                                <xsl:value-of select=\"$program-code-trimmed\"/>\n                                                <xsl:value-of select=\"$program-postamble-trimmed\"/>\n                                            </xsl:with-param>\n                                        </xsl:call-template>\n                                    </xsl:with-param>\n                                </xsl:call-template>\n                            </xsl:variable>\n                            <!-- Build actual string we will prepend to magic dividers -->\n                            <xsl:variable name=\"left-margin-string\">\n                                <xsl:value-of select=\"str:padding($program-left-margin, ' ')\" />\n                            </xsl:variable>\n                            <!-- Now we are ready to build the real program text.                       -->\n                            <!-- For historical reasons, this does not include potential <tests> child. -->\n                            <xsl:variable name=\"program-text\">\n                                <xsl:for-each select=\"preamble\">\n                                    <!-- only expect one, for-each just for binding -->\n                                    <xsl:value-of select=\"$program-preamble-trimmed\"/>\n                                    <xsl:value-of select=\"$left-margin-string\"/>\n                                    <xsl:choose>\n                                        <xsl:when test='@visible = \"no\"'>\n                                            <xsl:text>^^^^&#xa;</xsl:text>\n                                        </xsl:when>\n                                        <xsl:otherwise>\n                                            <xsl:text>^^^!&#xa;</xsl:text>\n                                        </xsl:otherwise>\n                                    </xsl:choose>\n                                </xsl:for-each>\n                                <!-- code - clean up start and end                                             -->\n                                <xsl:value-of select=\"$program-code-trimmed\"/>\n                                <!-- postamble - clean up start                                                -->\n                                <xsl:for-each select=\"postamble\">\n                                    <!-- only expect one, for-each just for binding -->\n                                    <xsl:value-of select=\"$left-margin-string\"/>\n                                    <xsl:choose>\n                                        <xsl:when test='@visible = \"no\"'>\n                                            <xsl:text>====&#xa;</xsl:text>\n                                        </xsl:when>\n                                        <xsl:otherwise>\n                                            <xsl:text>===!&#xa;</xsl:text>\n                                        </xsl:otherwise>\n                                    </xsl:choose>\n                                    <xsl:value-of select=\"$program-postamble-trimmed\"/>\n                                </xsl:for-each>\n                            </xsl:variable>\n                            <!-- now sanitize the whole blob -->\n                            <xsl:call-template name=\"sanitize-text\">\n                                <xsl:with-param name=\"text\" select=\"$program-text\" />\n                            </xsl:call-template>\n                            <!-- optional unit testing -->\n                            <xsl:if test=\"tests\">\n                                <!-- Be wary of empty \"test\" elements which lead to -->\n                                <!-- empty files, which are possibly not legal      -->\n                                <!-- programs for their target languages, and hence -->\n                                <!-- raise errors due to  the Runestone back-end    -->\n                                <!-- trying to process them.                        -->\n                                <!-- NB: static versions never show \"tests\" anyway  -->\n                                <xsl:variable name=\"tests-content\">\n                                    <xsl:variable name=\"trimmed-text\">\n                                        <xsl:apply-templates select=\"tests\" mode=\"program-part-processing\"/>\n                                    </xsl:variable>\n                                    <xsl:call-template name=\"left-align-text\">\n                                        <xsl:with-param name=\"text\" select=\"$trimmed-text\" />\n                                    </xsl:call-template>\n                                </xsl:variable>\n                                <!-- guard against whitespace-only tests, could be tests/iotests -->\n                                <xsl:if test=\"not(normalize-space($tests-content) = '')\">\n                                    <xsl:choose>\n                                        <xsl:when test=\"tests[@visible = 'yes']\">\n                                            <xsl:choose>\n                                                <xsl:when test=\"postamble[@visible = 'no']\">\n                                                    <xsl:message>PTX:WARNING: There is no support for visible tests after an invisible postamble. (Issue in <xsl:value-of select=\"$rsid\"/>).</xsl:message>\n                                                </xsl:when>\n                                                <xsl:when test=\"not(postamble)\">\n                                                    <!-- need to add header -->\n                                                    <xsl:text>===!&#xa;</xsl:text>\n                                                </xsl:when>\n                                                <!-- otherwise header created by postamble -->\n                                            </xsl:choose>\n                                        </xsl:when>\n                                        <xsl:otherwise>\n                                            <!-- invisible tests, need header if not after invisible postamble -->\n                                            <xsl:if test=\"not(postamble[@visible = 'no'])\">\n                                                <xsl:text>====&#xa;</xsl:text>\n                                            </xsl:if>\n                                        </xsl:otherwise>\n                                    </xsl:choose>\n                                    <xsl:value-of select=\"$tests-content\"/>\n                                </xsl:if>\n                                <xsl:if test=\"tests/iotest\">\n                                    <xsl:choose>\n                                        <xsl:when test=\"not(normalize-space(tests/text()) = '')\">\n                                            <xsl:message>PTX:FALLBACK: You can either write text based tests or use iotests, but not both. iotests ignored in <xsl:value-of select=\"$rsid\"/>.</xsl:message>\n                                        </xsl:when>\n                                        <xsl:otherwise>\n                                            <xsl:text>===iotests===&#x0a;</xsl:text>\n                                            <xsl:text>[</xsl:text>\n                                            <xsl:for-each select=\"tests/iotest\">\n                                                <xsl:text>{\"input\":\"</xsl:text>\n                                                <xsl:call-template name=\"escape-json-string\">\n                                                    <xsl:with-param name=\"text\">\n                                                        <xsl:call-template name=\"sanitize-text\">\n                                                            <xsl:with-param name=\"text\">\n                                                                <xsl:value-of select=\"input\"/>\n                                                            </xsl:with-param>\n                                                        </xsl:call-template>\n                                                    </xsl:with-param>\n                                                </xsl:call-template>\n                                                <xsl:text>\",\"out\":\"</xsl:text>\n                                                <xsl:call-template name=\"escape-json-string\">\n                                                    <xsl:with-param name=\"text\">\n                                                        <xsl:call-template name=\"sanitize-text\">\n                                                            <xsl:with-param name=\"text\">\n                                                                <xsl:value-of select=\"output\"/>\n                                                            </xsl:with-param>\n                                                        </xsl:call-template>\n                                                    </xsl:with-param>\n                                                </xsl:call-template>\n                                                <xsl:text>\"}</xsl:text>\n                                                <xsl:if test=\"position() != last()\">\n                                                    <xsl:text>,</xsl:text>\n                                                </xsl:if>\n                                            </xsl:for-each>\n                                            <xsl:text>]&#x0a;</xsl:text>\n                                        </xsl:otherwise>\n                                    </xsl:choose>\n                                </xsl:if>\n                            </xsl:if>\n                        </textarea>\n                    </div>\n                </div>\n            </div>\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:template name=\"runestone-activecode-editor-attributes\">\n    <xsl:param name=\"active-language\"/>\n    <xsl:param name=\"hosting\"/>\n    <xsl:attribute name=\"data-question_label\"/>\n    <!-- Code Lens only for certain languages -->\n    <xsl:attribute name=\"data-codelens\">\n        <xsl:choose>\n            <xsl:when test=\"@codelens = 'no'\">\n                <xsl:text>false</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"($active-language = 'python') or ($active-language = 'python2') or ($active-language = 'python3')\">\n                <xsl:text>true</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"($active-language = 'c') or ($active-language = 'cpp') or ($active-language = 'java')\">\n                <xsl:text>true</xsl:text>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>false</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:attribute>\n    <!-- allow @datafile attribute on <program> -->\n    <xsl:if test=\"@datafile\">\n        <!-- multiple files, coma- or space- separated -->\n        <xsl:variable name=\"tokens\" select=\"str:tokenize(@datafile, ', ')\"/>\n        <xsl:attribute name=\"data-datafile\">\n            <xsl:for-each select=\"$tokens\">\n                <xsl:value-of select=\".\"/>\n                <!-- n - 1 separators, required by receiving Javascript -->\n                <!-- comma-separated this time                          -->\n                <xsl:if test=\"following-sibling::token\">\n                    <xsl:text>,</xsl:text>\n                </xsl:if>\n            </xsl:for-each>\n        </xsl:attribute>\n    </xsl:if>\n\n    <!-- Merge add-files and compile-also, get unique items               -->\n    <!-- This will be the list that we use as add-files for the manifest  -->\n    <xsl:variable name=\"all-extra-files\">\n        <xsl:variable name=\"id-list\">\n            <xsl:value-of select=\"@add-files\"/>\n            <xsl:if test=\"@add-files and @compile-also\">\n                <xsl:text>, </xsl:text>\n            </xsl:if>\n            <xsl:value-of select=\"@compile-also\"/>\n        </xsl:variable>\n        <xsl:variable name=\"unique-tokens\">\n            <xsl:call-template name=\"unique-token-set\">\n                <xsl:with-param name=\"s\" select=\"$id-list\"/>\n            </xsl:call-template>\n        </xsl:variable>\n        <xsl:for-each select=\"exsl:node-set($unique-tokens)/token\">\n            <xsl:value-of select=\".\"/>\n            <xsl:if test=\"following-sibling::token\">\n                <xsl:text>,</xsl:text>\n            </xsl:if>\n        </xsl:for-each>\n    </xsl:variable>\n\n    <!-- allow @add-files attribute on <program> -->\n    <xsl:if test=\"$all-extra-files != ''\">\n        <xsl:attribute name=\"data-add-files\">\n            <xsl:call-template name=\"runestone-targets\">\n                <xsl:with-param name=\"id-list\" select=\"$all-extra-files\"/>\n                <xsl:with-param name=\"separator\" select=\"','\"/>\n            </xsl:call-template>\n        </xsl:attribute>\n    </xsl:if>\n    <!-- allow @compile-with attribute on <program> -->\n    <xsl:if test=\"@compile-also\">\n        <xsl:attribute name=\"data-compile-also\">\n            <xsl:call-template name=\"runestone-targets\">\n                <xsl:with-param name=\"id-list\" select=\"@compile-also\"/>\n                <xsl:with-param name=\"separator\" select=\"','\"/>\n                <xsl:with-param name=\"output-field\" select=\"'filename'\"/>\n            </xsl:call-template>\n        </xsl:attribute>\n    </xsl:if>\n    <!-- allow @include attribute on <program> -->\n    <xsl:if test=\"@include\">\n        <!-- space-separated this time -->\n        <xsl:attribute name=\"data-include\">\n            <xsl:call-template name=\"runestone-targets\">\n                <xsl:with-param name=\"id-list\" select=\"@include\"/>\n                <xsl:with-param name=\"separator\" select=\"' '\"/>\n            </xsl:call-template>\n        </xsl:attribute>\n    </xsl:if>\n    <!-- SQL (only) needs an attribute so it can find some code -->\n    <xsl:if test=\"$active-language = 'sql'\">\n        <xsl:attribute name=\"data-wasm\">\n            <xsl:text>/_static</xsl:text>\n        </xsl:attribute>\n        <!-- A SQL database can be provided for automated  -->\n        <!-- testing of correct answers via unit tests.    -->\n        <!-- This is a location in the external directory. -->\n        <xsl:if test=\"@database\">\n            <xsl:attribute name=\"data-dburl\">\n                <xsl:value-of select=\"$external-directory\"/>\n                <xsl:value-of select=\"@database\"/>\n            </xsl:attribute>\n        </xsl:if>\n    </xsl:if>\n    <!-- GDScript (Godot WASM) needs to find the shell engine files -->\n    <xsl:if test=\"$active-language = 'gdscript'\">\n        <xsl:attribute name=\"data-wasm\">\n            <xsl:value-of select=\"$godot.shell\" />\n            <xsl:value-of select=\"$godot.version\" />\n        </xsl:attribute>\n        <!-- Optional: per-exercise pck directory in the external directory -->\n        <xsl:if test=\"@pck\">\n            <xsl:attribute name=\"data-pck\">\n                <xsl:value-of select=\"$generated-directory\"/>\n                <!-- add subdirectory -->\n                <xsl:text>gdscript/</xsl:text>\n                <!-- add template -->\n                <xsl:apply-templates select=\".\" mode=\"unique-id\" />\n                <xsl:text>.zip</xsl:text>\n            </xsl:attribute>\n        </xsl:if>\n        <!-- Scene path inside the .pck virtual filesystem -->\n        <xsl:if test=\"@scene\">\n            <xsl:attribute name=\"data-scene\">\n                <xsl:value-of select=\"@scene\"/>\n            </xsl:attribute>\n        </xsl:if>\n    </xsl:if>\n    <!-- interpreter arguments for hosted languages -->\n    <xsl:variable name=\"interpreter-args\">\n        <xsl:call-template name=\"get-program-attr-or-default\">\n            <xsl:with-param name=\"attr\" select=\"'interpreter-args'\"/>\n        </xsl:call-template>\n    </xsl:variable>\n    <xsl:if test=\"$interpreter-args != '' and ($hosting = 'jobeserver')\">\n        <xsl:attribute name=\"data-interpreterargs\">\n            <xsl:call-template name=\"comma-list-to-json-array\">\n                <xsl:with-param name=\"list\" select=\"$interpreter-args\"/>\n            </xsl:call-template>\n        </xsl:attribute>\n    </xsl:if>\n    <!-- compiler arguments for hosted languages -->\n    <xsl:variable name=\"compiler-args\">\n        <xsl:call-template name=\"get-program-attr-or-default\">\n            <xsl:with-param name=\"attr\" select=\"'compiler-args'\"/>\n        </xsl:call-template>\n    </xsl:variable>\n    <!-- extra compiler args, appended to compiler args -->\n    <xsl:variable name=\"extra-compiler-args\" select=\"@extra-compiler-args\"/>\n    <xsl:if test=\"($compiler-args != '' or $extra-compiler-args != '') and ($hosting = 'jobeserver')\">\n        <xsl:variable name=\"compiler-args-full\">\n            <xsl:value-of select=\"$compiler-args\"/>\n            <xsl:if test=\"$compiler-args != '' and $extra-compiler-args != ''\">\n                <xsl:text>,</xsl:text>\n            </xsl:if>\n            <xsl:value-of select=\"$extra-compiler-args\"/>\n        </xsl:variable>\n        <xsl:attribute name=\"data-compileargs\">\n            <xsl:call-template name=\"comma-list-to-json-array\">\n                <xsl:with-param name=\"list\" select=\"$compiler-args-full\"/>\n            </xsl:call-template>\n        </xsl:attribute>\n    </xsl:if>\n    <!-- linker arguments for hosted languages -->\n    <xsl:variable name=\"linker-args\">\n        <xsl:call-template name=\"get-program-attr-or-default\">\n            <xsl:with-param name=\"attr\" select=\"'linker-args'\"/>\n        </xsl:call-template>\n    </xsl:variable>\n    <xsl:if test=\"$linker-args != '' and ($hosting = 'jobeserver')\">\n        <xsl:attribute name=\"data-linkargs\">\n            <xsl:call-template name=\"comma-list-to-json-array\">\n                <xsl:with-param name=\"list\" select=\"$linker-args\"/>\n            </xsl:call-template>\n        </xsl:attribute>\n    </xsl:if>\n    <!-- timelimit -->\n    <xsl:variable name=\"timelimit\">\n        <xsl:call-template name=\"get-program-attr-or-default\">\n            <xsl:with-param name=\"attr\" select=\"'timelimit'\"/>\n            <xsl:with-param name=\"default\" select=\"'25000'\"/>\n        </xsl:call-template>\n    </xsl:variable>\n    <xsl:if test=\"$timelimit != ''\">\n        <xsl:attribute name=\"data-timelimit\">\n            <xsl:value-of select=\"$timelimit\"/>\n        </xsl:attribute>\n    </xsl:if>\n    <!-- assorted boolean flags -->\n    <xsl:variable name=\"download\">\n      <xsl:call-template name=\"get-program-attr-or-default\">\n          <xsl:with-param name=\"attr\" select=\"'download'\"/>\n          <xsl:with-param name=\"default\" select=\"''\"/>\n      </xsl:call-template>\n    </xsl:variable>\n    <xsl:if test=\"$download = 'yes'\">\n        <xsl:attribute name=\"data-enabledownload\">\n            <xsl:text>yes</xsl:text>\n        </xsl:attribute>\n    </xsl:if>\n    <xsl:if test=\"@autorun = 'yes'\">\n        <xsl:attribute name=\"data-autorun\">\n            <xsl:text>yes</xsl:text>\n        </xsl:attribute>\n    </xsl:if>\n    <xsl:if test=\"@hidecode = 'yes'\">\n        <xsl:attribute name=\"data-hidecode\">\n            <xsl:text>yes</xsl:text>\n        </xsl:attribute>\n    </xsl:if>\n    <xsl:if test=\"@chatcodes = 'yes'\">\n        <xsl:attribute name=\"data-chatcodes\">\n            <xsl:text>yes</xsl:text>\n        </xsl:attribute>\n    </xsl:if>\n    <!-- Pass on highlighted line numbering -->\n    <xsl:if test=\"@highlight-lines != ''\">\n        <xsl:attribute name=\"data-highlight-lines\">\n            <!-- force comma-, or space-separated, list to commas -->\n            <xsl:value-of select=\"translate(normalize-space(translate(@highlight-lines, ',', ' ')), ' ', ',')\"/>\n        </xsl:attribute>\n    </xsl:if>\n</xsl:template>\n\n\n<!-- ######## -->\n<!-- CodeLens -->\n<!-- ######## -->\n\n<xsl:template match=\"program[@interactive = 'codelens']\" mode=\"runestone-codelens\">\n    <xsl:param name=\"exercise-statement\" select=\"/..\"/>\n    <xsl:variable name=\"active-language\">\n      <xsl:apply-templates select=\".\" mode=\"active-language\"/>\n    </xsl:variable>\n    <!-- as a variable so it does not look like an AVT -->\n    <xsl:variable name=\"parameter-dictionary\">\n        <xsl:text>{</xsl:text>\n        <xsl:text>\"embeddedMode\": true, </xsl:text>\n        <xsl:text>\"lang\": \"</xsl:text>\n        <xsl:value-of select=\"$active-language\"/>\n        <xsl:text>\", </xsl:text>\n        <xsl:text>\"jumpToEnd\": false</xsl:text>\n        <xsl:text>}</xsl:text>\n    </xsl:variable>\n    <!-- locate trace data via a *.js file, managed or not -->\n    <xsl:variable name=\"trace-file\">\n        <xsl:value-of select=\"$generated-directory\"/>\n        <xsl:text>trace/</xsl:text>\n        <xsl:apply-templates select=\".\" mode=\"runestone-codelens-trace-filename\"/>\n    </xsl:variable>\n    <!-- the Runestone HTML -->\n    <div class=\"ptx-runestone-container\">\n        <div class=\"runestone codelens\">\n            <div class=\"cd_section\" data-component=\"codelens\" data-question_label=\"\">\n                <xsl:if test=\"$exercise-statement\">\n                    <div class=\"exercise-statement\">\n                        <xsl:apply-templates select=\"$exercise-statement\"/>\n                    </div>\n                </xsl:if>\n                <div class=\"pytutorVisualizer exercise-interactive\">\n                    <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n                    <xsl:attribute name=\"data-params\">\n                        <xsl:value-of select=\"$parameter-dictionary\"/>\n                    </xsl:attribute>\n                </div>\n                <!-- no caption, should go inside a listing? -->\n            </div>\n            <!-- access simple script with variable set to -->\n            <!-- the trace data via the @src attribute     -->\n            <script>\n                <xsl:attribute name=\"src\">\n                    <xsl:value-of select=\"$trace-file\"/>\n                </xsl:attribute>\n                <!-- script tag MUST not be self closing. force content to prevent -->\n                <xsl:text> </xsl:text>\n            </script>\n        </div>\n    </div>\n</xsl:template>\n\n<!-- Some Runestone languages are supported within a browser,      -->\n<!-- so can be used as part of Runestone for All, while others     -->\n<!-- require a JOBE server on the Runestone server.  This template -->\n<!-- simply returns the necessary hosting capability.              -->\n<!-- N.B. This match could be simply on \"program\", but a runnable  -->\n<!-- Parsons problem may have a @language on it as part of being   -->\n<!-- runnable, thus a more liberal match (which could be           -->\n<!-- tightened, most likely).                                      -->\n<xsl:template match=\"*\" mode=\"activecode-host\">\n    <xsl:variable name=\"language\">\n        <xsl:apply-templates select=\".\" mode=\"active-language\"/>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$language = 'python'\">      <xsl:text>browser</xsl:text></xsl:when>\n        <xsl:when test=\"$language = 'javascript'\">  <xsl:text>browser</xsl:text></xsl:when>\n        <xsl:when test=\"$language = 'html'\">        <xsl:text>browser</xsl:text></xsl:when>\n        <xsl:when test=\"$language = 'sql'\">         <xsl:text>browser</xsl:text></xsl:when>\n        <xsl:when test=\"$language = 'gdscript'\">    <xsl:text>browser</xsl:text></xsl:when>\n        <xsl:when test=\"$language = 'c'\">           <xsl:text>jobeserver</xsl:text></xsl:when>\n        <xsl:when test=\"$language = 'cpp'\">         <xsl:text>jobeserver</xsl:text></xsl:when>\n        <xsl:when test=\"$language = 'java'\">        <xsl:text>jobeserver</xsl:text></xsl:when>\n        <xsl:when test=\"$language = 'kotlin'\">      <xsl:text>jobeserver</xsl:text></xsl:when>\n        <xsl:when test=\"$language = 'python2'\">     <xsl:text>jobeserver</xsl:text></xsl:when>\n        <xsl:when test=\"$language = 'python3'\">     <xsl:text>jobeserver</xsl:text></xsl:when>\n        <xsl:when test=\"$language = 'octave'\">      <xsl:text>jobeserver</xsl:text></xsl:when>\n        <xsl:otherwise/>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Data Files -->\n<xsl:template match=\"datafile\" mode=\"runestone-to-interactive\">\n    <!-- Possibly annotate with the source                     -->\n    <xsl:apply-templates select=\".\" mode=\"view-source-widget\"/>\n    <!-- Some templates and variables are defined in -common for consistency -->\n\n    <!-- If there is a child \"pre\" element, then we build an un-editable  -->\n    <!-- HTML \"pre\" in the uneditable case and an editable HTML           -->\n    <!-- \"textarea\" in the editable case.  This discintion is mirrored in -->\n    <!-- this variable and a subsequent boolean.                          -->\n    <xsl:variable name=\"pre-element\">\n        <xsl:choose>\n            <!-- only a clear \"yes\" will yield editable, -->\n            <!-- default is \"no\" (or anything but \"yes\") -->\n            <xsl:when test=\"pre and not(@editable = 'yes')\">\n                <xsl:text>pre</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"pre and (@editable = 'yes')\">\n                <xsl:text>textarea</xsl:text>\n            </xsl:when>\n            <!-- safeguard, should not ever be queried -->\n            <!-- outside of \"pre\" in source            -->\n            <xsl:otherwise/>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"b-is-editable\" select=\"$pre-element = 'textarea'\"/>\n\n    <!-- The HTML that Runestone expects -->\n    <div class=\"runestone datafile\">\n        <div class=\"datafile_caption\">\n            <code class=\"code-inline tex2jax_ignore\">\n                <!-- Internationalize?  See comments in static conversion -->\n                <xsl:text>Data: </xsl:text>\n                <xsl:value-of select=\"@filename\" />\n            </code>\n        </div>\n        <xsl:choose>\n            <xsl:when test=\"image\">\n                <!-- filename is relative to author's source -->\n                <xsl:variable name=\"data-filename\">\n                    <xsl:apply-templates select=\".\"  mode=\"datafile-filename\"/>\n                </xsl:variable>\n                <xsl:variable name=\"image-b64-elt\" select=\"document($data-filename, $original)/pi:image-b64\"/>\n                <img data-component=\"datafile\" data-isimage=\"true\">\n                    <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n                    <xsl:attribute name=\"data-filename\">\n                        <xsl:value-of select=\"@filename\"/>\n                    </xsl:attribute>\n                    <xsl:attribute name=\"src\">\n                        <xsl:text>data:</xsl:text>\n                        <xsl:value-of select=\"$image-b64-elt/@pi:mime-type\"/>\n                        <xsl:text>;base64,</xsl:text>\n                        <xsl:value-of select=\"$image-b64-elt/@pi:base64\"/>\n                    </xsl:attribute>\n                </img>\n            </xsl:when>\n            <!-- text, an authored toy example, or a serious external file -->\n            <xsl:when test=\"pre\">\n                <xsl:element name=\"{$pre-element}\">\n                    <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n                    <xsl:attribute name=\"data-component\">\n                        <xsl:text>datafile</xsl:text>\n                    </xsl:attribute>\n                    <xsl:attribute name=\"data-filename\">\n                        <xsl:value-of select=\"@filename\"/>\n                    </xsl:attribute>\n                    <xsl:attribute name=\"data-edit\">\n                        <!-- conveniently, value is true/false -->\n                        <xsl:value-of select=\"$b-is-editable\"/>\n                    </xsl:attribute>\n                    <!-- Runestone can only hide non-editable text -->\n                    <xsl:if test=\"(not(@editable = 'yes')) and (@hide = 'yes')\">\n                        <xsl:attribute name=\"data-hidden\"/>\n                    </xsl:if>\n                    <xsl:attribute name=\"data-rows\">\n                        <xsl:choose>\n                            <xsl:when test=\"@rows\">\n                                <xsl:value-of select=\"@rows\"/>\n                            </xsl:when>\n                            <!-- default is 20 rows -->\n                            <xsl:otherwise>\n                                <xsl:value-of select=\"$datafile-default-rows\"/>\n                            </xsl:otherwise>\n                        </xsl:choose>\n                    </xsl:attribute>\n                    <xsl:attribute name=\"data-cols\">\n                        <xsl:choose>\n                            <xsl:when test=\"@cols\">\n                                <xsl:value-of select=\"@cols\"/>\n                            </xsl:when>\n                            <!-- default is 40 columns -->\n                            <xsl:otherwise>\n                                <xsl:value-of select=\"$datafile-default-cols\"/>\n                            </xsl:otherwise>\n                        </xsl:choose>\n                    </xsl:attribute>\n                    <xsl:apply-templates select=\".\" mode=\"datafile-text-contents\"/>\n                </xsl:element>\n            </xsl:when>\n            <!-- no other source/PTX element is supported , bail out-->\n            <xsl:otherwise/>\n        </xsl:choose>\n    </div>\n</xsl:template>\n\n<!-- ############# -->\n<!-- Tabbed Viewer -->\n<!-- ############# -->\n\n<!-- Strictly a presentational device, but useful in certain situations  -->\n<!-- as a pedogogical device.  But we start with presentation.  An       -->\n<!-- \"exercise\" or PROJECT-LIKE, structured by \"task\" can have each      -->\n<!-- top-level task go into a tab, along with tabs for \"introduction\"    -->\n<!-- and \"conclusion\".  We *never* do this for worksheets, to avoid      -->\n<!-- gumming up printing and spacing.  And WeBWorK problems manage       -->\n<!-- their own tasks.  The \"match\" here is pretty selective for          -->\n<!-- \"exercise\", should perhaps be tighter for PROJECT-LIKE.  Of course, -->\n<!-- Runestone Components play nicely with this device, along with more  -->\n<!-- boring exercises.                                                   -->\n\n<xsl:template match=\"exercise[task and not(@pi:exercise-customization = 'worksheet')]|&PROJECT-LIKE;\" mode=\"tabbed-tasks\">\n    <xsl:param name=\"heading-level\"/>\n    <div class=\"ptx-runestone-container\">\n        <div>\n            <xsl:attribute name=\"class\">\n                <xsl:text>runestone tabbed_section</xsl:text>\n                <!-- need to know if it contains an element that wants to be wide in wide layout -->\n                <xsl:if test=\".//program[@interactive = 'activecode'] or .//program[@interactive = 'codelens'] or .//exercise/blocks\">\n                    <xsl:text> contains-wide</xsl:text>\n                </xsl:if>\n            </xsl:attribute>\n            <!-- \"introduction\" first as lead-in, not as a tab -->\n            <xsl:if test=\"introduction\">\n                <div class=\"tabs-introduction exercise-leadin\">\n                    <xsl:apply-templates select=\"introduction\">\n                        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                    </xsl:apply-templates>\n                </div>\n            </xsl:if>\n            <!-- @data-component=\"tab\" do not need an HTML @id for any -->\n            <!-- purpose in Runestone (such as, say, tracking activity -->\n            <!-- as a reader clicks from tab to tab)                   -->\n            <div data-component=\"tabbedStuff\">\n                <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n                <xsl:for-each select=\"task\">\n                    <xsl:variable name=\"the-task-number\">\n                        <xsl:text>(</xsl:text>\n                        <xsl:apply-templates select=\".\" mode=\"serial-number\"/>\n                        <xsl:text>)</xsl:text>\n                    </xsl:variable>\n                    <div data-component=\"tab\" data-tabname=\"{$the-task-number}\">\n                        <xsl:apply-templates select=\".\">\n                            <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                        </xsl:apply-templates>\n                    </div>\n                </xsl:for-each>\n            </div>\n            <!--  -->\n            <!-- \"conclusion\" last as lead-out, not as a tab -->\n            <xsl:if test=\"conclusion\">\n                <div class=\"tabs-conclusion exercise-leadout\">\n                    <xsl:apply-templates select=\"conclusion\">\n                        <xsl:with-param name=\"heading-level\" select=\"$heading-level\"/>\n                    </xsl:apply-templates>\n                </div>\n            </xsl:if>\n        </div>\n    </div>\n</xsl:template>\n\n<!-- ####### -->\n<!-- Queries -->\n<!-- ####### -->\n\n<xsl:template match=\"query\" mode=\"runestone-to-interactive\">\n    <!-- <xsl:text>FOO</xsl:text> -->\n    <xsl:variable name=\"the-choices\" select=\"choices/choice\"/>\n    <div class=\"ptx-runestone-container\">\n        <div class=\"runestone\">\n            <ul data-component=\"poll\">\n                <xsl:apply-templates select=\".\" mode=\"runestone-id-attribute\"/>\n                <xsl:attribute name=\"data-results\">\n                    <xsl:choose>\n                        <xsl:when test=\"(@visibility = 'instructor') or (@visibility = 'all')\">\n                            <xsl:value-of select=\"@visibility\"/>\n                        </xsl:when>\n                        <xsl:otherwise>\n                            <xsl:text>instructor</xsl:text>\n                        </xsl:otherwise>\n                    </xsl:choose>\n                </xsl:attribute>\n                <xsl:apply-templates select=\"statement\"/>\n                <!-- infrastructure to here is common to a query with -->\n                <!-- explicit distinct choices, versus a query with a -->\n                <!-- simple scale for responses                       -->\n                <!-- NB: could define a variable early on indicating  -->\n                <!-- the nature of the poll, should there need to be  -->\n                <!-- more differentiation                             -->\n                <xsl:choose>\n                    <xsl:when test=\"choices\">\n                        <xsl:apply-templates select=\"choices/choice\"/>\n                    </xsl:when>\n                    <xsl:when test=\"foome\">\n                        <!-- context switch will allow \"position()\" to behave -->\n                        <xsl:for-each select=\"$the-choices\">\n                            <li>\n                                <span class=\"poll-choice\">\n                                    <xsl:value-of select=\"position()\"/>\n                                </span>\n                                <xsl:apply-templates/>\n                            </li>\n                        </xsl:for-each>\n                    </xsl:when>\n                    <xsl:when test=\"@scale\">\n                        <!-- generate list items with numbers recursively -->\n                        <xsl:call-template name=\"numbered-list-items\">\n                            <xsl:with-param name=\"max\" select=\"@scale\"/>\n                        </xsl:call-template>\n                    </xsl:when>\n                    <!-- could add error warning here?  Or rely on schema? -->\n                    <xsl:otherwise/>\n                </xsl:choose>\n            </ul>\n        </div>\n    </div>\n</xsl:template>\n\n<xsl:template match=\"query/choices/choice\">\n    <li>\n        <!-- <span class=\"poll-choice\">\n            <xsl:number/>\n        </span> -->\n        <xsl:number/>\n        <xsl:text>. </xsl:text>\n        <xsl:apply-templates/>\n    </li>\n</xsl:template>\n\n<xsl:template name=\"numbered-list-items\">\n    <!-- always initialize with 1 to start -->\n    <xsl:param name=\"current\" select=\"'1'\"/>\n    <xsl:param name=\"max\"/>\n\n    <xsl:choose>\n        <!-- $current is too big, done with recursion -->\n        <xsl:when test=\"$current > $max\"/>\n        <xsl:otherwise>\n            <!-- make numbered list-item -->\n            <li>\n                <xsl:value-of select=\"$current\"/>\n            </li>\n            <!-- recurse with next integer -->\n            <xsl:call-template name=\"numbered-list-items\">\n                <xsl:with-param name=\"current\" select=\"$current + 1\"/>\n                <xsl:with-param name=\"max\" select=\"$max\"/>\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- ######### -->\n<!-- Utilities -->\n<!-- ######### -->\n\n<!-- Interpreter/compiler/linker args all start as comma separated lists \"-Wall, -std=c++17\" -->\n<!-- and need to end up a JSON array of strings: \"['-Wall', '-std=c++17']\"                   -->\n<xsl:template name=\"comma-list-to-json-array\">\n    <xsl:param name=\"list\"/>\n    <!-- comma separated in PreTeXt source -->\n    <xsl:variable name=\"tokens\" select=\"str:tokenize($list, ',')\"/>\n    <xsl:text>[</xsl:text>\n    <xsl:for-each select=\"$tokens\">\n        <xsl:text>'</xsl:text>\n        <!-- prune leading/trailing spaces but leave ones in middle -->\n        <xsl:value-of select=\"normalize-space(.)\"/>\n        <xsl:text>'</xsl:text>\n        <xsl:if test=\"following-sibling::token\">\n            <xsl:text>, </xsl:text>\n        </xsl:if>\n    </xsl:for-each>\n    <xsl:text>]</xsl:text>\n</xsl:template>\n\n<!-- Runestone components, such as data files and select questions,  -->\n<!-- frequently point to other Runestone components in the database. -->\n<!--   * Authors point in their source with @xml:id                  -->\n<!--     values in a space- or comma- separated list                 -->\n<!--   * We locate the targets in the assembled tree, where a        -->\n<!--     database id (a @label) exists even when only an @xml:id     -->\n<!--     was authored (a backward-compatibility promotion)           -->\n<!--   * Compute the Runestone database id                           -->\n<!--   * Return a list (varying separator) to use in Runestone HTML. -->\n<xsl:template name=\"runestone-targets\">\n    <xsl:param name=\"id-list\"/>\n    <xsl:param name=\"separator\" select=\"'MISSING SEPARATOR'\"/>\n    <xsl:param name=\"output-field\" select=\"'runestone-id'\"/>\n\n    <!-- comma or space separated in PreTeXt source -->\n    <xsl:variable name=\"tokens\" select=\"str:tokenize($id-list, ', ')\"/>\n    <xsl:for-each select=\"$tokens\">\n        <!-- attribute value is an xml:id, get target interactive -->\n        <xsl:variable name=\"the-id\">\n            <xsl:value-of select=\".\"/>\n        </xsl:variable>\n        <!-- context shift so  id()  functions properly -->\n        <xsl:for-each select=\"$root\">\n            <xsl:variable name=\"target\" select=\"id($the-id)\"/>\n            <xsl:if test=\"not($target)\">\n                <xsl:message>PTX:ERROR:   an @xml:id value \"<xsl:value-of select=\"$the-id\"/>\" was used to specify a runestone component but no item with that id exists.</xsl:message>\n            </xsl:if>\n            <!-- build Runestone database id of the target -->\n            <xsl:choose>\n                <xsl:when test=\"$output-field = 'runestone-id'\">\n                    <xsl:apply-templates select=\"$target\" mode=\"runestone-id\"/>\n                </xsl:when>\n                <xsl:when test=\"$output-field = 'filename'\">\n                    <xsl:value-of select=\"$target/@filename\"/>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:apply-templates select=\"$target\" mode=\"runestone-id\"/>\n                    <xsl:message>PTX:BUG:     runestone-targets template was called with an invalid @output-field value \"<xsl:value-of select=\"$output-field\"/>\"</xsl:message>\n                </xsl:otherwise>\n            </xsl:choose>\n            <!-- n - 1 separators, required by receiving Javascript -->\n        </xsl:for-each>\n        <xsl:if test=\"following-sibling::token\">\n            <xsl:value-of select=\"$separator\"/>\n        </xsl:if>\n    </xsl:for-each>\n</xsl:template>\n\n\n</xsl:stylesheet>\n","pretext-text-utilities.xsl":"<?xml version='1.0'?>\n\n<!--********************************************************************\nCopyright (C) 2022-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- Indicated basic utilities are from:                      -->\n<!-- XSLT Cookbook, 2nd Edition                               -->\n<!-- Copyright 2006, O'Reilly Media, Inc.                     -->\n<!--                                                          -->\n<!-- From the section of the Preface, \"Using Code Examples\":  -->\n<!-- \"You do not need to contact us for permission unless     -->\n<!-- you're reproducing a significant portion of the code.    -->\n<!-- For example, writing a program that uses several chunks  -->\n<!-- of code from this book does not require permission.\"     -->\n\n<!-- This stylesheet is meant to xsl:include'd into other stylesheets.     -->\n<!-- All the templates were once part of \"pretext-common.xsl\" (2022-03-27) -->\n<!-- and so are being included at the point where the vast majority were   -->\n<!-- originally created.  Perhaps the include can move to a more obvious   -->\n<!-- location near the top of that file.  There is no entry template and   -->\n<!-- every template is a named template which relies on parameters, not    -->\n<!-- context or a match/select mechanism.  (With some exceptions.)         -->\n<!--                                                                       -->\n<!-- Used in:                                                              -->\n<!--     xsl/pretext-common.xsl (2022-03-27)                               -->\n<!--     xsl/pretext/pretext-runestone-static.xsl (2022-03-28)             -->\n\n<!-- \"unit\" tests for these templates are (partially) implemented in       -->\n<!-- xsl/tests/pretext-text-utilities-test.xsl                             -->\n<!-- Before modifying any templates in this file, you are encouraged to    -->\n<!-- make sure there is a set of tests for the template(s) and use those   -->\n<!-- to verify changes allong with diffs of sample-book/sample-article     -->\n\n<!-- There are &LOWERCASE; and &UPPERCASE; entities  -->\n<!-- in the \"file-extension\" template (only?) -->\n<!DOCTYPE xsl:stylesheet [\n    <!ENTITY % entities SYSTEM \"entities.ent\">\n    %entities;\n]>\n\n<!-- EXSL needed for token list template (only?) -->\n<xsl:stylesheet\n    xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\"\n    xmlns:xml=\"http://www.w3.org/XML/1998/namespace\"\n    xmlns:pi=\"http://pretextbook.org/2020/pretext/internal\"\n    xmlns:str=\"http://exslt.org/strings\"\n    xmlns:exsl=\"http://exslt.org/common\"\n    xmlns:math=\"http://exslt.org/math\"\n    xmlns:set=\"http://exslt.org/sets\"\n    extension-element-prefixes=\"pi str math\"\n>\n\n<!-- Allow serialization of XML in various contexts     -->\n<!-- See the XSL file for more info about Lenz' utility -->\n<xsl:import href=\"./xml-to-string.xsl\"/>\n\n<!-- ########################## -->\n<!-- Text Manipulation Routines -->\n<!-- ########################## -->\n\n<!-- Various bits of textual material            -->\n<!-- (eg Sage, code, verbatim, LaTeX)            -->\n<!-- require manipulation to                     -->\n<!--                                             -->\n<!--   (a) behave in some output format          -->\n<!--   (b) produce human-readable output (LaTeX) -->\n\n<!-- We need to identify particular characters   -->\n<!-- space, tab, carriage return, newline        -->\n<xsl:variable name=\"whitespaces\">\n    <xsl:text>&#x20;&#x9;&#xD;&#xA;</xsl:text>\n</xsl:variable>\n\n<!-- Sanitize Code -->\n<!-- No leading whitespace, no trailing -->\n<!-- http://stackoverflow.com/questions/1134318/xslt-xslstrip-space-does-not-work -->\n<!-- Trim all whitespace at end of code hunk -->\n<!-- Append carriage return to mark last line, remove later -->\n<!-- preserve-intentional keeps all whitespace that comes   -->\n<!-- before the last newline                                -->\n<xsl:template name=\"trim-end\">\n   <xsl:param name=\"text\"/>\n   <xsl:param name=\"preserve-intentional\" select=\"false()\" />\n   <xsl:variable name=\"last-char\" select=\"substring($text, string-length($text), 1)\" />\n   <xsl:choose>\n        <xsl:when test=\"$last-char=''\">\n            <xsl:text>&#xA;</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"($preserve-intentional = true()) and ($last-char = '&#xA;')\">\n            <xsl:value-of select=\"$text\"/>\n        </xsl:when>\n        <xsl:when test=\"contains($whitespaces, $last-char)\">\n            <xsl:call-template name=\"trim-end\">\n                <xsl:with-param name=\"text\" select=\"substring($text, 1, string-length($text) - 1)\" />\n                <xsl:with-param name=\"preserve-intentional\" select=\"$preserve-intentional\" />\n            </xsl:call-template>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"$text\" />\n            <xsl:text>&#xA;</xsl:text>\n        </xsl:otherwise>\n   </xsl:choose>\n</xsl:template>\n\n<!-- Trim all totally whitespace lines from beginning of code hunk -->\n<!-- preserve-intentional removes all whitespace through first     -->\n<!-- newline (inclusive) and preserves the rest.                   -->\n<xsl:template name=\"trim-start-lines\">\n   <xsl:param name=\"text\"/>\n   <xsl:param name=\"pad\" select=\"''\"/>\n   <xsl:param name=\"preserve-intentional\" select=\"false()\" />\n   <xsl:variable name=\"first-char\" select=\"substring($text, 1, 1)\" />\n   <xsl:choose>\n        <!-- Possibly nothing, return just final carriage return -->\n        <xsl:when test=\"$first-char=''\">\n            <xsl:text>&#xA;</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$first-char='&#xA;'\">\n            <xsl:choose>\n                <xsl:when test=\"$preserve-intentional=true()\">\n                    <xsl:value-of select=\"substring($text, 2)\" />\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:call-template name=\"trim-start-lines\">\n                        <xsl:with-param name=\"text\" select=\"substring($text, 2)\" />\n                    </xsl:call-template>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <xsl:when test=\"contains($whitespaces, $first-char)\">\n            <xsl:call-template name=\"trim-start-lines\">\n                <xsl:with-param name=\"text\" select=\"substring($text, 2)\" />\n                <xsl:with-param name=\"pad\"  select=\"concat($pad, $first-char)\" />\n                <xsl:with-param name=\"preserve-intentional\" select=\"$preserve-intentional\" />\n            </xsl:call-template>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"concat($pad, $text)\" />\n        </xsl:otherwise>\n   </xsl:choose>\n</xsl:template>\n\n<!-- Compute length of indentation of first line                   -->\n<!-- Assumes no leading blank lines                                -->\n<xsl:template name=\"count-pad-length\">\n    <xsl:param name=\"text\"/>\n    <xsl:param name=\"index\" select=\"1\"/>\n    <xsl:variable name=\"first-char\" select=\"substring($text, $index, 1)\" />\n    <xsl:choose>\n        <!-- reached end of string or newline... bail out -->\n        <xsl:when test=\"$first-char = '' or $first-char = '&#xA;'\">\n            <xsl:value-of select=\"$index - 1\"/>\n        </xsl:when>\n        <xsl:when test=\"contains($whitespaces, $first-char)\">\n            <xsl:call-template name=\"count-pad-length\">\n                <xsl:with-param name=\"text\" select=\"$text\" />\n                <xsl:with-param name=\"index\" select=\"$index + 1\" />\n            </xsl:call-template>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"$index - 1\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Compute width of left margin                                -->\n<!-- Assumes each line ends in a newline                         -->\n<!-- A blank line will not contribute                            -->\n<!-- Intentionally non-recursive to avoid recursion depth issues -->\n<!-- on long code samples                                        -->\n<xsl:template name=\"left-margin\">\n    <xsl:param name=\"text\" />\n\n    <!-- construct a variable that is just a list of padding counts -->\n    <!-- as pad nodes                                               -->\n    <xsl:variable name=\"lines\" select=\"str:tokenize($text, '&#xA;')\" />\n    <xsl:variable name=\"pad-counts-rtf\">\n        <xsl:for-each select=\"$lines\">\n            <!-- str:tokenize in current implementation does not produce -->\n            <!-- zero-length strings. (e.g. string between two newlines) -->\n            <!-- but that appears to differ between implementations, so  -->\n            <!-- guard against it                                        -->\n            <xsl:if test=\". != ''\">\n                <pad>\n                    <xsl:call-template name=\"count-pad-length\">\n                        <xsl:with-param name=\"text\" select=\".\" />\n                    </xsl:call-template>\n                </pad>\n            </xsl:if>\n        </xsl:for-each>\n    </xsl:variable>\n    <xsl:variable name=\"pad-counts\" select=\"exsl:node-set($pad-counts-rtf)\"/>\n\n    <!-- grab minimum value from list-->\n    <xsl:variable name=\"min-pad\" select=\"math:min($pad-counts/pad)\" />\n\n    <!-- min-pad will be NaN if there was nothing to count -->\n    <xsl:choose>\n        <xsl:when test=\"string($min-pad)='NaN'\">\n            <xsl:value-of select=\"0\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"$min-pad\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- Divide and conquer strip-indentation                              -->\n<!-- Appropriate for long chunks of text. Minimal overhead on small    -->\n<!-- chunks of text.                                                   -->\n<!-- An \"out-dented\" line is assumed to be intermediate blank line     -->\n<!-- indent parameter is a number giving number of characters to strip -->\n<xsl:template name=\"strip-indentation\">\n    <xsl:param name=\"text\" />\n    <xsl:param name=\"indent\" />\n\n    <!-- string length at which to give up divide and conquer          -->\n    <xsl:variable name=\"divide-threshold\" select=\"500\" />\n\n    <xsl:variable name=\"text-len\" select=\"string-length($text)\" />\n    <xsl:choose>\n        <!-- short string, hand off to line by line algorithm -->\n        <xsl:when test=\"$divide-threshold > $text-len\">\n            <xsl:call-template name=\"strip-indentation-core\">\n                <xsl:with-param name=\"text\" select=\"$text\" />\n                <xsl:with-param name=\"indent\" select=\"$indent\" />\n            </xsl:call-template>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- Cut string in half -->\n            <xsl:variable name=\"cut-location\" select=\"floor(string-length($text) div 2)\"/>\n            <xsl:variable name=\"first-half\" select=\"substring($text, 1, $cut-location)\"/>\n            <xsl:variable name=\"second-half\" select=\"substring($text, $cut-location + 1)\"/>\n            <!-- First half needs to take on everything before first newline -->\n            <!-- in second-half and have a trailing newline                  -->\n            <xsl:variable name=\"first-half-augmented\" select=\"concat($first-half, substring-before($second-half, '&#xA;'), '&#xA;')\"/>\n            <!-- Second half only gets text after the first newline in it    -->\n            <xsl:variable name=\"second-half-augmented\" select=\"substring-after($second-half, '&#xA;')\"/>\n\n            <!-- Stop dividing? -->\n            <xsl:choose>\n                <xsl:when test=\"$second-half-augmented = ''\">\n                    <!-- Nothing in second half (can happen with really long lines) -->\n                    <!-- Give up and hand first half to line-by-line                -->\n                    <xsl:call-template name=\"strip-indentation-core\">\n                        <xsl:with-param name=\"text\" select=\"$first-half-augmented\" />\n                        <xsl:with-param name=\"indent\" select=\"$indent\" />\n                    </xsl:call-template>\n                </xsl:when>\n                <xsl:otherwise>\n                    <!-- Recurse on each half -->\n                    <xsl:call-template name=\"strip-indentation\">\n                        <xsl:with-param name=\"text\" select=\"$first-half-augmented\" />\n                        <xsl:with-param name=\"indent\" select=\"$indent\" />\n                    </xsl:call-template>\n                    <xsl:call-template name=\"strip-indentation\">\n                        <xsl:with-param name=\"text\" select=\"$second-half-augmented\" />\n                        <xsl:with-param name=\"indent\" select=\"$indent\" />\n                    </xsl:call-template>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Line by line strip-indentation                                    -->\n<!-- should only be called on shortish chunks of text                  -->\n<!-- (dozens of lines not hundreds)                                    -->\n<!-- An \"out-dented\" line is assumed to be intermediate blank line     -->\n<!-- indent parameter is a number giving number of characters to strip -->\n<xsl:template name=\"strip-indentation-core\">\n    <xsl:param name=\"text\" />\n    <xsl:param name=\"indent\" />\n    <xsl:if test=\"$text != ''\">\n        <xsl:variable name=\"first-line\" select=\"substring-before($text, '&#xA;')\" />\n        <xsl:if test=\"string-length($first-line) > $indent\" >\n            <xsl:value-of select=\"substring($first-line, $indent + 1)\" />\n        </xsl:if>\n        <xsl:text>&#xA;</xsl:text>\n        <xsl:call-template name=\"strip-indentation-core\">\n            <xsl:with-param name=\"text\" select=\"substring-after($text, '&#xA;')\" />\n            <xsl:with-param name=\"indent\" select=\"$indent\" />\n        </xsl:call-template>\n    </xsl:if>\n</xsl:template>\n\n<!-- Add a common string in front of every line of a block -->\n<!-- Typically spaces to format output block for doctest   -->\n<!-- indent parameter is a string                          -->\n<!-- Assumes last character is xA                          -->\n<!-- Result has trailing xA                                -->\n<xsl:template name=\"add-indentation\">\n    <xsl:param name=\"text\" />\n    <xsl:param name=\"indent\" />\n    <xsl:if test=\"$text != ''\">\n        <xsl:value-of select=\"concat($indent,substring-before($text, '&#xA;'))\" />\n        <xsl:text>&#xA;</xsl:text>\n        <xsl:call-template name=\"add-indentation\">\n            <xsl:with-param name=\"text\" select=\"substring-after($text, '&#xA;')\" />\n            <xsl:with-param name=\"indent\" select=\"$indent\" />\n        </xsl:call-template>\n    </xsl:if>\n</xsl:template>\n\n<!-- Shift all lines in text to the left far enough that   -->\n<!-- line with the least indentation is at the left margin -->\n<xsl:template name=\"left-align-text\">\n    <xsl:param name=\"text\" />\n    <xsl:variable name=\"left-margin\">\n        <xsl:call-template name=\"left-margin\">\n            <xsl:with-param name=\"text\" select=\"$text\" />\n        </xsl:call-template>\n    </xsl:variable>\n    <xsl:variable name=\"stripped-text\">\n        <xsl:call-template name=\"strip-indentation\">\n            <!-- strip-indentation requires trailing newline -->\n            <!-- add one here and trim it when done          -->\n            <xsl:with-param name=\"text\" select=\"concat($text, '&#xA;')\" />\n            <xsl:with-param name=\"indent\" select=\"$left-margin\" />\n        </xsl:call-template>\n    </xsl:variable>\n    <!-- produce value without the added newline -->\n    <xsl:value-of select=\"substring($stripped-text, 1, string-length($stripped-text) - 1)\" />\n</xsl:template>\n\n\n<!-- Main template for cleaning up hunks of raw text      -->\n<!--                                                      -->\n<!-- 1) Trim all trailing whitespace                      -->\n<!-- 2) Add carriage return marker to last line           -->\n<!-- 3) Strip all totally blank leading lines             -->\n<!-- 4) Determine indentation of left-most non-blank line -->\n<!-- 5) Strip indentation from all lines                  -->\n<!-- 6) Allow intermediate blank lines                    -->\n\n<xsl:template name=\"sanitize-text\">\n    <xsl:param name=\"text\" />\n    <xsl:param name=\"preserve-end\" select=\"false()\" />\n    <xsl:param name=\"preserve-start\" select=\"false()\" />\n    <xsl:variable name=\"trimmed-text\">\n        <xsl:call-template name=\"trim-start-lines\">\n            <xsl:with-param name=\"text\">\n                <xsl:call-template name=\"trim-end\">\n                    <xsl:with-param name=\"text\" select=\"$text\" />\n                    <xsl:with-param name=\"preserve-intentional\" select=\"$preserve-end\" />\n                </xsl:call-template>\n            </xsl:with-param>\n            <xsl:with-param name=\"preserve-intentional\" select=\"$preserve-start\" />\n        </xsl:call-template>\n    </xsl:variable>\n    <xsl:call-template name=\"left-align-text\" >\n        <xsl:with-param name=\"text\" select=\"$trimmed-text\" />\n    </xsl:call-template>\n</xsl:template>\n\n<!-- Substrings at last markers               -->\n<!-- XSLT Cookbook, 2nd Edition               -->\n<!-- Copyright 2006, O'Reilly Media, Inc.     -->\n<!-- Recipe 2.4, nearly verbatim, reformatted -->\n<xsl:template name=\"substring-before-last-iterative\">\n    <xsl:param name=\"input\" />\n    <xsl:param name=\"substr\" />\n    <xsl:if test=\"$substr and contains($input, $substr)\">\n        <xsl:variable name=\"temp\" select=\"substring-after($input, $substr)\" />\n        <xsl:value-of select=\"substring-before($input, $substr)\" />\n        <xsl:if test=\"contains($temp, $substr)\">\n            <xsl:value-of select=\"$substr\" />\n            <xsl:call-template name=\"substring-before-last-iterative\">\n                <xsl:with-param name=\"input\" select=\"$temp\" />\n                <xsl:with-param name=\"substr\" select=\"$substr\" />\n            </xsl:call-template>\n        </xsl:if>\n    </xsl:if>\n</xsl:template>\n\n<!-- Substrings at last markers                                 -->\n<!-- Approach - keep throwing away the first half of the string -->\n<!-- until we reach a point where one more slice would result   -->\n<!-- in no more copies of substr. Produce everything that was   -->\n<!-- sliced, then let iterative version handle the rest.        -->\n<!-- Implemented mostly to prevent lxml from dying due to       -->\n<!-- depth limit when processing large strings                  -->\n<xsl:template name=\"substring-before-last\">\n    <xsl:param name=\"input\" />\n    <xsl:param name=\"substr\" />\n\n    <xsl:variable name=\"mid-index\" select=\"ceiling(string-length($input) div 2)\"/>\n    <xsl:variable name=\"front\" select=\"substring($input, 1, $mid-index)\"/>\n    <xsl:variable name=\"back\" select=\"substring($input, $mid-index + 1)\"/>\n\n    <xsl:choose>\n        <xsl:when test=\"contains($back, $substr)\">\n            <!-- Need front for sure, recurse on back -->\n            <xsl:value-of select=\"$front\" />\n            <xsl:call-template name=\"substring-before-last\">\n                <xsl:with-param name=\"input\" select=\"$back\" />\n                <xsl:with-param name=\"substr\" select=\"$substr\" />\n            </xsl:call-template>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- substr might be in front, or bridging front and back -->\n            <!-- hand off entire string to iterative version          -->\n            <xsl:call-template name=\"substring-before-last-iterative\">\n                <xsl:with-param name=\"input\" select=\"$input\" />\n                <xsl:with-param name=\"substr\" select=\"$substr\" />\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- substring from $input after first instance of $substr         -->\n<!-- if no match, returns original string                          -->\n<!-- similar to substring-after() function but preserves original  -->\n<xsl:template name=\"substring-after-preserve\">\n    <xsl:param name=\"input\"/>\n    <xsl:param name=\"substr\"/>\n    <!-- Extract the string which comes after the first occurrence -->\n    <xsl:variable name=\"temp\" select=\"substring-after($input,$substr)\"/>\n    <xsl:choose>\n        <xsl:when test=\"$temp = ''\">\n            <xsl:value-of select=\"$input\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"$temp\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- If the substring is not contained, the first substring-after()   -->\n<!-- will return empty and entire template will return empty.  To     -->\n<!-- get the whole string, prepend $input with $substr prior to using -->\n<xsl:template name=\"substring-after-last\">\n    <xsl:param name=\"input\"/>\n    <xsl:param name=\"substr\"/>\n    <!-- Extract the string which comes after the first occurrence -->\n    <xsl:variable name=\"temp\" select=\"substring-after($input,$substr)\"/>\n    <xsl:choose>\n        <!-- If it still contains the search string then recursively process -->\n        <xsl:when test=\"$substr and contains($temp,$substr)\">\n            <xsl:call-template name=\"substring-after-last\">\n                <xsl:with-param name=\"input\" select=\"$temp\"/>\n                <xsl:with-param name=\"substr\" select=\"$substr\"/>\n            </xsl:call-template>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"$temp\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Duplicating Strings                      -->\n<!-- XSLT Cookbook, 2nd Edition               -->\n<!-- Copyright 2006, O'Reilly Media, Inc.     -->\n<!-- Recipe 2.5, nearly verbatim, reformatted -->\n<xsl:template name=\"duplicate-string\">\n     <xsl:param name=\"text\" />\n     <xsl:param name=\"count\" select=\"1\" />\n     <xsl:choose>\n          <xsl:when test=\"not($count) or not($text)\" />\n          <xsl:when test=\"$count = 1\">\n               <xsl:value-of select=\"$text\" />\n          </xsl:when>\n          <xsl:otherwise>\n               <!-- If $count is odd, append one copy of input -->\n               <xsl:if test=\"$count mod 2\">\n                    <xsl:value-of select=\"$text\" />\n               </xsl:if>\n               <!-- Recursively apply template, after -->\n               <!-- doubling input and halving count  -->\n               <xsl:call-template name=\"duplicate-string\">\n                    <xsl:with-param name=\"text\" select=\"concat($text,$text)\" />\n                    <xsl:with-param name=\"count\" select=\"floor($count div 2)\" />\n               </xsl:call-template>\n          </xsl:otherwise>\n     </xsl:choose>\n</xsl:template>\n\n<!-- Prepending Strings -->\n<!-- Add  count  copies of the string  pad  to  each line of  text -->\n<!-- Presumes  text  has a newline character at the very end       -->\n<xsl:template name=\"prepend-string\">\n    <xsl:param name=\"text\" />\n    <xsl:param name=\"pad\" />\n    <xsl:param name=\"count\" select=\"1\" />\n    <xsl:variable name=\"bigpad\">\n        <xsl:call-template name=\"duplicate-string\">\n            <xsl:with-param name=\"text\" select=\"$pad\" />\n            <xsl:with-param name=\"count\" select=\"$count\" />\n        </xsl:call-template>\n    </xsl:variable>\n    <!-- Quit when string becomes empty -->\n    <xsl:if test=\"string-length($text)\">\n        <xsl:variable name=\"first-line\" select=\"substring-before($text, '&#xa;')\" />\n        <xsl:value-of select=\"$bigpad\" />\n        <xsl:value-of select=\"$first-line\" />\n        <xsl:text>&#xa;</xsl:text>\n        <!-- recursive call on remaining lines -->\n        <xsl:call-template name=\"prepend-string\">\n            <xsl:with-param name=\"text\" select=\"substring-after($text, '&#xa;')\" />\n            <xsl:with-param name=\"pad\" select=\"$bigpad\" />\n            <xsl:with-param name=\"count\" select=\"1\" />\n        </xsl:call-template>\n    </xsl:if>\n</xsl:template>\n\n<!-- Counting Substrings -->\n<xsl:template name=\"count-substring\">\n    <xsl:param name=\"text\" />\n    <xsl:param name=\"word\" />\n    <xsl:param name=\"count\" select=\"'0'\" />\n    <xsl:choose>\n        <xsl:when test=\"not(contains($text, $word))\">\n            <xsl:value-of select=\"$count\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:call-template name=\"count-substring\">\n                <xsl:with-param name=\"text\" select=\"substring-after($text, $word)\" />\n                <xsl:with-param name=\"word\" select=\"$word\" />\n                <xsl:with-param name=\"count\" select=\"$count + 1\" />\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Remove empty lines -->\n<!-- These are lines with no characters -->\n<!-- at all, just a newline             -->\n<!-- 2017-01-22: UNUSED, UNTESTED, incorporate with caution  -->\n<xsl:template name=\"strip-empty-lines\">\n    <xsl:param name=\"text\" />\n    <xsl:choose>\n        <!-- no more splitting, output $text, empty or not -->\n        <xsl:when test=\"not(contains($text, '&#xa;'))\">\n            <xsl:value-of select=\"$text\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:variable name=\"firstline\" select=\"substring-before($text, '&#xa;')\" />\n            <xsl:choose>\n                <!-- silently drop an empty line, newline already gone -->\n                <xsl:when test=\"not($firstline)\" />\n                <!-- output first line with restored newline -->\n                <xsl:otherwise>\n                    <xsl:value-of select=\"concat($firstline, '&#xa;')\" />\n                </xsl:otherwise>\n            </xsl:choose>\n            <!-- recurse with remainder -->\n            <xsl:call-template name=\"strip-empty-lines\">\n                <xsl:with-param name=\"text\" select=\"substring-after($text, '&#xa;')\" />\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Merge consecutive empty lines -->\n<!-- In other words, if there are three or more consecutive newline -->\n<!-- characters, replace them with just two newline characters.     -->\n<xsl:template name=\"consolidate-empty-lines\">\n    <xsl:param name=\"text\" />\n    <xsl:choose>\n        <xsl:when test=\"not(contains($text, '&#xa;&#xa;&#xa;'))\">\n            <xsl:value-of select=\"$text\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:call-template name=\"consolidate-empty-lines\">\n                <xsl:with-param name=\"text\" select=\"str:replace($text,'&#xa;&#xa;&#xa;','&#xa;&#xa;')\" />\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Gobble leading whitespace -->\n<!-- Drop consecutive leading spaces and tabs, only     -->\n<!-- Designed for a single line as input                -->\n<!-- Used after maniplating sentence ending punctuation -->\n<xsl:template name=\"strip-leading-blanks\">\n    <xsl:param name=\"text\" />\n    <xsl:variable name=\"first-char\" select=\"substring($text, 1, 1)\" />\n    <xsl:choose>\n        <!-- if empty, done -->\n        <xsl:when test=\"not($first-char)\" />\n        <!-- first character is space, tab, drop it -->\n        <xsl:when test=\"contains('&#x20;&#x9;', $first-char)\">\n            <xsl:call-template name=\"strip-leading-blanks\">\n                <xsl:with-param name=\"text\" select=\"substring($text, 2)\" />\n            </xsl:call-template>\n        </xsl:when>\n        <!-- finished stripping, output as-is -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$text\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Shove text left -->\n<!-- Remove all leading whitespace from every line -->\n<!-- Note: very similar to \"sanitize-latex\" below           -->\n<!-- 2017-01-22: UNUSED, UNTESTED, incorporate with caution -->\n<xsl:template name=\"slide-text-left\">\n    <xsl:param name=\"text\" />\n    <xsl:choose>\n        <!-- no more splitting, strip leading whitespace -->\n        <xsl:when test=\"not(contains($text, '&#xa;'))\">\n            <xsl:call-template name=\"strip-leading-blanks\">\n                <xsl:with-param name=\"text\">\n                    <xsl:value-of select=\"$text\" />\n                </xsl:with-param>\n            </xsl:call-template>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:call-template name=\"strip-leading-blanks\">\n                <xsl:with-param name=\"text\" select=\"concat(substring-before($text, '&#xa;'), '&#xa;')\" />\n            </xsl:call-template>\n            <!-- recurse with remainder -->\n            <xsl:call-template name=\"slide-text-left\">\n                <xsl:with-param name=\"text\" select=\"substring-after($text, '&#xa;')\" />\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Strip whitespace after line break -->\n<!-- A hard line-break (newline) in authors' source will typically  -->\n<!-- introduce leading whitespace (spaces) prior to the next line.  -->\n<!-- This template scrubs the spaces, but leaves the newline (which -->\n<!-- can be dealt with by the consumer).  Strategy is to replace    -->\n<!-- <newline><space> by <newline> until it cannot be done anymore. -->\n<xsl:template name=\"reduce-line-break\">\n    <xsl:param name=\"text\"/>\n\n    <xsl:choose>\n        <xsl:when test=\"not(contains($text, '&#xa;&#x20;'))\">\n            <xsl:value-of select=\"$text\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:call-template name=\"reduce-line-break\">\n                <xsl:with-param name=\"text\" select=\"str:replace($text, '&#xa;&#x20;', '&#xa;')\"/>\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Sanitize Nemeth Braille -->\n<!-- We receive Nemeth braille from MathJax and Speech Rule Engine (SRE) as -->\n<!--                                                                        -->\n<!--   1. Optional indentation U+2800 for second, and subsequent lines of   -->\n<!--      2D layout display math                                            -->\n<!--   2. Actual content with U+2800 as spaces                              -->\n<!--   3. An optional run of U+2800 to form a uniform right margin for      -->\n<!--      (eventual) 2D physical devices.                                   -->\n<!--                                                                        -->\n<!--  To play nice with liblouis we let U+2800 be an unbreakable space      -->\n<!--  and U+0020 (\"regular\" space) be a breakable space.  So                -->\n<!--    -->\n<!--   1.  We preserve indentation as unbreakable spaces.                   -->\n<!--   2.  We convert content spaces to \"regular\" spaces.  In some cases    -->\n<!--       we make convert them back to unbreakable spaces.                 -->\n<!--   3.  We drop trailing (right margin) whitespace, as unnecessary,      -->\n<!--       and even problematic.                                            -->\n\n\n<!-- Break on newlines.  Trim trailing whitespace, massage whitespace in   -->\n<!-- remainder.  Reconstitute with same patter of newlines.  Note: for     -->\n<!-- single-line braille from SRE there is no indentation and no trailing  -->\n<!-- whitespace for a right margin.                                        -->\n<!-- NB: \"otherwise\" might be simpler if some conditioning was different   -->\n<!-- in the \"when.                                                         -->\n\n<xsl:template name=\"sanitize-nemeth-braille\">\n    <xsl:param name=\"text\"/>\n    <xsl:choose>\n        <xsl:when test=\"contains($text, '&#xa;')\">\n            <xsl:variable name=\"one-line\" select=\"substring-before($text, '&#xa;')\"/>\n            <!-- strip end of a single line of U+2800, a braille empty cell -->\n            <xsl:variable name=\"end-trimmed\">\n                <xsl:call-template name=\"trim-nemeth-trailing-whitespace\">\n                    <xsl:with-param name=\"text\" select=\"$one-line\"/>\n                </xsl:call-template>\n            </xsl:variable>\n            <xsl:call-template name=\"convert-nemeth-whitespace\">\n                <xsl:with-param name=\"text\" select=\"$end-trimmed\"/>\n            </xsl:call-template>\n            <!-- restore \"split-out\" newline -->\n            <xsl:text>&#xa;</xsl:text>\n            <!-- recursively process remainder -->\n            <xsl:call-template name=\"sanitize-nemeth-braille\">\n                <xsl:with-param name=\"text\" select=\"substring-after($text, '&#xa;')\"/>\n            </xsl:call-template>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- last line, needs manipulation -->\n            <xsl:variable name=\"end-trimmed\">\n                <xsl:call-template name=\"trim-nemeth-trailing-whitespace\">\n                    <xsl:with-param name=\"text\" select=\"$text\"/>\n                </xsl:call-template>\n            </xsl:variable>\n            <xsl:call-template name=\"convert-nemeth-whitespace\">\n                <xsl:with-param name=\"text\" select=\"$end-trimmed\"/>\n            </xsl:call-template>\n            <!-- no newline to restore     -->\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Work in from right margin, dropping consecutive U+2800 -->\n<xsl:template name=\"trim-nemeth-trailing-whitespace\">\n   <xsl:param name=\"text\"/>\n   <xsl:variable name=\"last-char\" select=\"substring($text, string-length($text), 1)\" />\n   <xsl:choose>\n        <xsl:when test=\"$last-char = '&#x2800;'\">\n            <xsl:call-template name=\"trim-nemeth-trailing-whitespace\">\n                <xsl:with-param name=\"text\" select=\"substring($text, 1, string-length($text) - 1)\" />\n            </xsl:call-template>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"$text\" />\n        </xsl:otherwise>\n   </xsl:choose>\n</xsl:template>\n\n<!-- Work in from the left.  The $b-indentation boolean signals that       -->\n<!-- the last character examined was a U+2800 from the run of indentation  -->\n<!-- (which we simply duplicate).  It begins true as the default value,    -->\n<!-- which is not present in initial call.  Once it flips false, it stays  -->\n<!-- false.  Spaces within content convert to \"regular\" spaces.            -->\n<!-- Note: once $b-indentation flips false, we could just do a             -->\n<!-- search/replace on the string to output with a \"value-of\"              -->\n\n<xsl:template name=\"convert-nemeth-whitespace\">\n   <xsl:param name=\"text\"/>\n   <xsl:param name=\"b-indentation\" select=\"true()\"/>\n\n   <xsl:choose>\n        <xsl:when test=\"$text\">\n            <xsl:variable name=\"first-char\" select=\"substring($text, 1, 1)\"/>\n            <xsl:variable name=\"b-found-indentation\" select=\"$b-indentation and ($first-char = '&#x2800;')\"/>\n            <xsl:choose>\n                <!-- echo a leading U+2800 in the indentation-->\n                <xsl:when test=\"$b-found-indentation\">\n                    <xsl:text>&#x2800;</xsl:text>\n                </xsl:when>\n                <!-- convert space in content into a regular space -->\n                <xsl:when test=\"$first-char = '&#x2800;'\">\n                    <xsl:text>&#x0020;</xsl:text>\n                </xsl:when>\n                <!-- echo any other character -->\n                <xsl:otherwise>\n                    <xsl:value-of select=\"$first-char\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n            <!-- Recurse with all but the first character -->\n            <xsl:call-template name=\"convert-nemeth-whitespace\">\n                <xsl:with-param name=\"text\" select=\"substring($text, 2, string-length($text) - 1)\"/>\n                <xsl:with-param name=\"b-indentation\" select=\"$b-found-indentation\"/>\n            </xsl:call-template>\n        </xsl:when>\n        <!-- $text is empty string, done -->\n        <xsl:otherwise/>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- Sanitize LaTex -->\n<!-- We allow authors to include whitespace for readability          -->\n<!--                                                                 -->\n<!-- (1) Newlines used to format complicated math (eg matrices)      -->\n<!-- (2) Newlines used to avoid word-wrapping in editing tools       -->\n<!-- (3) Newlines to support atomic version control changesets       -->\n<!-- (4) Source indentation of above, consonant with XML indentation -->\n<!--                                                                 -->\n<!-- But once we form LaTeX output we want to                        -->\n<!--                                                                 -->\n<!--   (i)   Remove 100% whitespace lines                            -->\n<!--   (ii)  Remove leading whitespace                               -->\n<!--   (iii) Finish without a newline                                -->\n<!--                                                                 -->\n<!-- So we                                                           -->\n<!--                                                                 -->\n<!-- (a) Strip all leading whitespace                                -->\n<!-- (b) Remove any 100% resulting empty lines (newline only)        -->\n<!-- (c) Preserve remaining newlines (trailing after content)        -->\n<!-- (d) Preserve remaining whitespace (eg, within expressions)      -->\n<!-- (e) Take care with trailing characters, except final newline    -->\n<!--                                                                 -->\n<!-- We can do this because of the limited purposes of the           -->\n<!-- m, me, men, md, mdn elements.  The whitespace we strip is not   -->\n<!-- relevant/important, and what we leave does not change output    -->\n<xsl:template name=\"sanitize-latex\">\n    <xsl:param name=\"text\" />\n    <xsl:variable name=\"first-char\" select=\"substring($text, 1, 1)\" />\n    <xsl:choose>\n        <!-- empty, end recursion -->\n        <xsl:when test=\"$first-char = ''\" />\n        <!-- first character is whitespace, including newline -->\n        <!-- silently drop it as we recurse on remainder      -->\n        <xsl:when test=\"contains($whitespaces, $first-char)\">\n            <xsl:call-template name=\"sanitize-latex\">\n                <xsl:with-param name=\"text\" select=\"substring($text, 2)\" />\n            </xsl:call-template>\n        </xsl:when>\n        <!-- content followed by newline                           -->\n        <!-- split, preserve newline, output, and recurse, but     -->\n        <!-- drop a newline that only protects trailing whitespace -->\n        <xsl:when test=\"contains($text, '&#xa;')\">\n            <xsl:value-of select=\"substring-before($text, '&#xa;')\" />\n            <xsl:variable name=\"remainder\" select=\"substring-after($text, '&#xa;')\" />\n            <xsl:choose>\n                <xsl:when test=\"normalize-space($remainder) = ''\" />\n                <xsl:otherwise>\n                    <xsl:text>&#xa;</xsl:text>\n                    <xsl:call-template name=\"sanitize-latex\">\n                        <xsl:with-param name=\"text\" select=\"$remainder\" />\n                    </xsl:call-template>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- content, no following newline -->\n        <!-- output in full, end recursion -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$text\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- This collects \"clause-ending\" punctuation     -->\n<!-- from the *front* of a text node.  It does not -->\n<!-- change the text node, but simply outputs the  -->\n<!-- punctuation for use by another template       -->\n<xsl:template name=\"leading-clause-punctuation\">\n    <xsl:param name=\"text\" />\n    <xsl:variable name=\"first-char\" select=\"substring($text, 1, 1)\" />\n    <xsl:choose>\n        <!-- empty, quit -->\n        <xsl:when test=\"not($first-char)\" />\n        <!-- if punctuation, output and recurse -->\n        <!-- else silently quit recursion       -->\n        <xsl:when test=\"contains($clause-ending-marks, $first-char)\">\n            <xsl:value-of select=\"$first-char\" />\n            <xsl:call-template name=\"leading-clause-punctuation\">\n                <xsl:with-param name=\"text\" select=\"substring($text, 2)\" />\n            </xsl:call-template>\n        </xsl:when>\n        <!-- consecutive only, stop collecting -->\n        <xsl:otherwise />\n    </xsl:choose>\n</xsl:template>\n\n<!-- If we absorb punctuation, we need to scrub it by    -->\n<!-- examining and manipulating the text node with       -->\n<!-- those characters.  We drop consecutive punctuation. -->\n<xsl:template name=\"drop-clause-punctuation\">\n    <xsl:param name=\"text\" />\n    <xsl:variable name=\"first-char\" select=\"substring($text, 1, 1)\" />\n    <xsl:choose>\n        <!-- if empty, done -->\n        <xsl:when test=\"not($first-char)\" />\n        <!-- first character ends sentence, drop it, recurse -->\n        <xsl:when test=\"contains($clause-ending-marks, $first-char)\">\n            <xsl:call-template name=\"drop-clause-punctuation\">\n                <xsl:with-param name=\"text\" select=\"substring($text, 2)\" />\n            </xsl:call-template>\n        </xsl:when>\n        <!-- no more punctuation, output as-is -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$text\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Remove consecutive run of blanks and  -->\n<!-- newlines in first portion of a string -->\n<!-- Performance audited 2024-12-15 - this is so frequently called -->\n<!-- in the simple case (nothing to strip) that just about any     -->\n<!-- optimization for the general case ends up being slower.       -->\n<xsl:template name=\"strip-leading-whitespace\">\n    <xsl:param name=\"text\" />\n    <xsl:variable name=\"first-char\" select=\"substring($text, 1, 1)\" />\n    <xsl:choose>\n        <!-- if empty, quit -->\n        <xsl:when test=\"not($first-char)\" />\n        <!-- if first character is whitespace, drop it -->\n        <xsl:when test=\"contains($whitespaces, $first-char)\">\n            <xsl:call-template name=\"strip-leading-whitespace\">\n                <xsl:with-param name=\"text\" select=\"substring($text, 2)\" />\n            </xsl:call-template>\n        </xsl:when>\n        <!-- else finished stripping, output as-is -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$text\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Remove consecutive run of blanks and -->\n<!-- newlines in last portion of a string -->\n<!-- Performance audited 2024-12-15 - this is so frequently called -->\n<!-- in the simple case (nothing to strip) that just about any     -->\n<!-- optimization for the general case ends up being slower.       -->\n<xsl:template name=\"strip-trailing-whitespace\">\n    <xsl:param name=\"text\" />\n    <xsl:variable name=\"last-char\" select=\"substring($text, string-length($text), 1)\" />\n    <xsl:choose>\n        <!-- if empty, quit -->\n        <xsl:when test=\"not($last-char)\" />\n        <!-- if last character is whitespace, drop it -->\n        <xsl:when test=\"contains($whitespaces, $last-char)\">\n            <xsl:call-template name=\"strip-trailing-whitespace\">\n                <xsl:with-param name=\"text\" select=\"substring($text, 1, string-length($text)-1)\" />\n            </xsl:call-template>\n        </xsl:when>\n        <!-- else finished stripping, output as-is -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$text\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Collapse each newline, and the horizontal space around -->\n<!-- it, to a single space: hard-wrapped, indented source   -->\n<!-- becomes one long line                                  -->\n<xsl:template name=\"flatten-line-breaks\">\n    <xsl:param name=\"text\"/>\n    <xsl:choose>\n        <xsl:when test=\"contains($text, '&#xa;')\">\n            <xsl:call-template name=\"strip-trailing-whitespace\">\n                <xsl:with-param name=\"text\" select=\"substring-before($text, '&#xa;')\"/>\n            </xsl:call-template>\n            <xsl:text> </xsl:text>\n            <xsl:call-template name=\"flatten-line-breaks\">\n                <xsl:with-param name=\"text\">\n                    <xsl:call-template name=\"strip-leading-whitespace\">\n                        <xsl:with-param name=\"text\" select=\"substring-after($text, '&#xa;')\"/>\n                    </xsl:call-template>\n                </xsl:with-param>\n            </xsl:call-template>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"$text\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- spurious newlines introduce whitespace on either side -->\n<!-- we split at newlines, strip consecutive whitesapce on either side, -->\n<!-- and replace newlines by spaces (could restore a single newline) -->\n<xsl:template name=\"strip-newlines\">\n    <xsl:param name=\"text\" />\n    <xsl:choose>\n        <!-- if has newline, modify newline-free front portion -->\n        <!-- replace splitting newline with new separator      -->\n        <!-- modify trailing portion, and recurse with it      -->\n        <xsl:when test=\"contains($text, '&#xa;')\">\n            <!-- clean trailing portion of left half -->\n            <xsl:call-template name=\"strip-trailing-whitespace\">\n                <xsl:with-param name=\"text\" select=\"substring-before($text, '&#xa;')\" />\n            </xsl:call-template>\n            <!-- restore a separator, blank now -->\n            <!-- Note: this could be a newline, perhaps optionally (whitespace=\"breaks\") -->\n            <!-- Note: this could be \" %\\n\" in LaTeX output to be super explicit -->\n            <xsl:text> </xsl:text>\n            <!-- recurse with modified right half -->\n            <xsl:call-template name=\"strip-newlines\">\n                <xsl:with-param name=\"text\">\n                    <!-- clean leading portion of right half -->\n                    <xsl:call-template name=\"strip-leading-whitespace\">\n                        <xsl:with-param name=\"text\" select=\"substring-after($text, '&#xa;')\" />\n                    </xsl:call-template>\n                </xsl:with-param>\n            </xsl:call-template>\n        </xsl:when>\n        <!-- else finished stripping, output as-is -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$text\" />\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- JSON Escaped Strings -->\n<!-- Convert a string, just prior to dropping it into a  -->\n<!-- JSON data structure, so this presumes nothing       -->\n<!-- special has been done with the contents before-hand -->\n<!-- In order converted, using the standard JSON names:  -->\n<!--     reverse solidus (backslash), solidus (slash),   -->\n<!--     quotation mark, backspace, horizontal tab,      -->\n<!--     newline, form feed, carriage return             -->\n<!-- Escaping solidus (forward slash) is only necessary  -->\n<!-- for <\\ inside a script tag (or similar?)  It makes  -->\n<!-- URLs ugly, but we do it anyway so we don't get bit. -->\n<!-- Strictly needed:  backslash, double quote, newline. -->\n<!-- XSLT3:                                              -->\n<!-- But XML 1.0 does not allow x08 (backspace) and x0c  -->\n<!-- (form feed) so we ignore them for now.  Perhaps see -->\n<!-- https://stackoverflow.com/questions/404107/         -->\n<!-- why-are-control-characters-illegal-in-xml-1-0       -->\n\n<!-- First define the replacements. These must be in     -->\n<!-- order as search + replace pairs                     -->\n<!-- Other control character replacements are not        -->\n<!-- included because they would not be valid at an      -->\n<!-- earlier stage.                                      -->\n<xsl:variable name=\"json-replacements\">\n    <search>\\</search>\n    <replace>\\\\</replace>\n    <search>/</search>\n    <replace>\\/</replace>\n    <search><xsl:value-of select=\"string('&#x0a;')\"/></search>\n    <replace>\\n</replace>\n    <search><xsl:value-of select=\"string('&#x09;')\"/></search>\n    <replace>\\t</replace>\n    <search><xsl:value-of select=\"string('&#x0d;')\"/></search>\n    <replace>\\r</replace>\n    <search><xsl:value-of select=\"string('&#x22;')\"/></search>\n    <replace>\\&#x22;</replace>\n    <search><xsl:value-of select=\"string('&#x2028;')\"/></search>\n    <replace>\\u2028</replace>\n    <search><xsl:value-of select=\"string('&#x2029;')\"/></search>\n    <replace>\\u2029</replace>\n</xsl:variable>\n<xsl:variable name=\"json-replacements-search-set\" select=\"exsl:node-set($json-replacements)/search\" />\n<xsl:variable name=\"json-replacements-replace-set\" select=\"exsl:node-set($json-replacements)/replace\" />\n\n<xsl:template name=\"escape-json-string\">\n    <xsl:param name=\"text\"/>\n\n    <xsl:value-of select=\"str:replace($text, $json-replacements-search-set, $json-replacements-replace-set)\" />\n</xsl:template>\n\n<!-- REGEX Escaped Strings -->\n<!-- When a string will be passed for comparison using regexp   -->\n<!-- but we want a literal match, we need to escape all of the  -->\n<!-- special characters by putting a slash in front.            -->\n<xsl:variable name=\"regexp-replacements\">\n    <search>\\</search>\n    <replace>\\\\</replace>\n    <search>.</search>\n    <replace>\\.</replace>\n    <search>^</search>\n    <replace>\\^</replace>\n    <search>$</search>\n    <replace>\\$</replace>\n    <search>*</search>\n    <replace>\\*</replace>\n    <search>+</search>\n    <replace>\\+</replace>\n    <search>?</search>\n    <replace>\\?</replace>\n    <search>{</search>\n    <replace>\\{</replace>\n    <search>}</search>\n    <replace>\\}</replace>\n    <search>[</search>\n    <replace>\\[</replace>\n    <search>]</search>\n    <replace>\\]</replace>\n    <search>(</search>\n    <replace>\\(</replace>\n    <search>)</search>\n    <replace>\\)</replace>\n    <search>|</search>\n    <replace>\\|</replace>\n</xsl:variable>\n<xsl:variable name=\"regexp-replacements-search-set\" select=\"exsl:node-set($regexp-replacements)/search\" />\n<xsl:variable name=\"regexp-replacements-replace-set\" select=\"exsl:node-set($regexp-replacements)/replace\" />\n\n<xsl:template name=\"escape-regexp-literal\">\n    <xsl:param name=\"text\"/>\n\n    <xsl:value-of select=\"str:replace($text, $regexp-replacements-search-set, $regexp-replacements-replace-set)\" />\n</xsl:template>\n\n<xsl:template name=\"quote-string\">\n    <xsl:param name=\"text\" />\n    <xsl:text>\"</xsl:text>\n    <xsl:value-of select=\"$text\" />\n    <xsl:text>\"</xsl:text>\n</xsl:template>\n\n<xsl:template name=\"quote-strip-string\">\n    <xsl:param name=\"text\" />\n    <xsl:text>\"</xsl:text>\n    <xsl:call-template name=\"strip-newlines\">\n        <xsl:with-param name=\"text\" select=\"$text\" />\n    </xsl:call-template>\n    <xsl:text>\"</xsl:text>\n</xsl:template>\n\n<xsl:template name=\"escape-quote-string\">\n    <xsl:param name=\"text\" />\n    <xsl:call-template name=\"quote-string\">\n        <xsl:with-param name=\"text\">\n            <xsl:call-template name=\"escape-json-string\">\n                <xsl:with-param name=\"text\" select=\"$text\"/>\n            </xsl:call-template>\n        </xsl:with-param>\n    </xsl:call-template>\n</xsl:template>\n\n<xsl:template name=\"escape-quote-xml\">\n    <xsl:param name=\"xml_content\"/>\n    <xsl:variable name=\"xml_text\">\n        <xsl:apply-templates select=\"exsl:node-set($xml_content)\" mode=\"xml-to-string\"/>\n    </xsl:variable>\n    <xsl:call-template name=\"escape-quote-string\">\n        <xsl:with-param name=\"text\" select=\"$xml_text\"/>\n    </xsl:call-template>\n</xsl:template>\n\n<!-- File Extension -->\n<!-- Input: full filename                       -->\n<!-- Output: extension (no period), lowercase'd -->\n<!-- Note: appended query string is stripped    -->\n<xsl:template name=\"file-extension\">\n    <xsl:param name=\"filename\" />\n    <!-- Add a question mark, then grab leading substring -->\n    <!-- This will fail if \"?\" is encoded                 -->\n    <xsl:variable name=\"no-query-string\" select=\"substring-before(concat($filename, '?'), '?')\" />\n    <!-- Reduce to the last path segment first, else a period in a host -->\n    <!-- name or a directory (\"media.w3.org\", \"v1.2\") would be read as  -->\n    <!-- the start of an extension.  The leading slash is what makes    -->\n    <!-- \"substring-after-last\" return a bare filename unchanged.       -->\n    <xsl:variable name=\"final-segment\">\n        <xsl:call-template name=\"substring-after-last\">\n            <xsl:with-param name=\"input\" select=\"concat('/', $no-query-string)\" />\n            <xsl:with-param name=\"substr\" select=\"'/'\" />\n        </xsl:call-template>\n    </xsl:variable>\n    <!-- get extension after last period   -->\n    <!-- will return empty if no extension -->\n    <xsl:variable name=\"extension\">\n        <xsl:call-template name=\"substring-after-last\">\n            <xsl:with-param name=\"input\" select=\"$final-segment\" />\n            <xsl:with-param name=\"substr\" select=\"'.'\" />\n        </xsl:call-template>\n    </xsl:variable>\n    <!-- to lowercase -->\n    <xsl:value-of select=\"translate($extension, &UPPERCASE;, &LOWERCASE;)\" />\n</xsl:template>\n\n<!-- ################# -->\n<!-- String Utilities -->\n<!-- ################# -->\n\n<!-- Find a delimiter: find a character that can be wrapped around a string -->\n<!-- Take a string as one input and a list of characters as another input   -->\n<!-- Return the first character from the list that is not in the string     -->\n<xsl:template name=\"find-unused-character\">\n    <xsl:param name=\"string\" select=\"''\"/>\n    <!-- set of characters that are candidates for use as delimiters -->\n    <!-- with empty string as default, failure is guaranteed         -->\n    <xsl:param name=\"charset\" select=\"''\"/>\n    <!-- If a character in $charset is inside the string, then we do   -->\n    <!-- not want to use it as a delimiter.  The translate() function  -->\n    <!-- operates so as to morph its first argument, $charset.  Called -->\n    <!-- this way, each character of the $charset that is in $string,  -->\n    <!-- will be replaced by an empty string.  So any character of     -->\n    <!-- $charset that survives un-translated, is not in $string.      -->\n    <xsl:variable name=\"characters\" select=\"translate($charset, $string, '')\"/>\n\n    <!-- We fail, big time, or elect to use the first available character -->\n    <xsl:choose>\n        <xsl:when test=\"$characters = ''\">\n            <xsl:message>PTX:FATAL:   Unable to find an unused character in:&#xa;<xsl:value-of select=\"$string\" />&#xa;using characters from: <xsl:value-of select=\"$charset\" /></xsl:message>\n            <xsl:apply-templates select=\".\" mode=\"location-report\" />\n            <xsl:message terminate=\"yes\">PTX:FATAL:   Quitting...</xsl:message>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"substring($characters, 1, 1)\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- ############### -->\n<!-- Token Utilities -->\n<!-- ############### -->\n\n<!-- The \"tokenize()\" function could replace this? -->\n<!-- And then dependence on EXSL might be removed. -->\n\n<!-- Routines that can be employed in a recursive      -->\n<!-- formulation to process a string (attribute value, -->\n<!-- usually) that is separated by spaces or by commas -->\n\n<!-- Replace commas by blanks, constrict blanks to singletons, -->\n<!-- add trailing blank for last step of iteration             -->\n<xsl:template name=\"prepare-token-list\">\n    <xsl:param name=\"token-list\" />\n    <xsl:value-of select=\"concat(normalize-space(str:replace($token-list, ',', ' ')), ' ')\" />\n</xsl:template>\n\n<!-- Now, to work through the $token-list                          -->\n<!--   1. If $token-list = '', end recursion                       -->\n<!--   2. Process substring-before($token-list, ' ') as next token -->\n<!--   3. Pass substring-after($token-list, ' ') recursively       -->\n\n<!-- Generate a unique set of tokens from a given string                  -->\n<!-- Final structure will consist of set of <token>value</token> elements -->\n<!-- Produces a RTF, so result must be converted to nodeset               -->\n<xsl:template name=\"unique-token-set\">\n    <xsl:param name=\"s\" />\n    <xsl:param name=\"delimiter\" select=\"', '\" />\n    <xsl:variable name=\"token-list\" select=\"str:tokenize($s, $delimiter)\"/>\n    <xsl:variable name=\"token-set-temp\" select=\"set:distinct($token-list)\"/>\n    <!-- Next step is currently a no-op as str:tokenize drops empty strings. But that -->\n    <!-- appears to not be part of the spec. So for safety, get difference with       -->\n    <!-- a nodeset composed of a single empty token                                   -->\n    <xsl:variable name=\"token-set\" select=\"set:difference($token-set-temp, str:tokenize(''))\"/>\n    <xsl:copy-of select=\"$token-set\" />\n</xsl:template>\n\n\n<!-- ################################## -->\n<!-- Runestone Services General Support -->\n<!-- ################################## -->\n\n<!-- Some items that are in play relative to Runestone Services -->\n<!-- that are independendt of dynamic/static and which can      -->\n<!-- promote consistence if defined only once.  End game is the -->\n<!-- text of a datafile, so appropriate here.  However, they    -->\n<!-- are a bit different than above in spirit, as they involve  -->\n<!-- global variables, file manipulations, and are not named    -->\n<!-- templates generally.  They are necessary to create static  -->\n<!-- versions of Runestone datafile elements during the         -->\n<!-- assembly phase, and the enhanced-source stylesheet avoids  -->\n<!-- using -common, hence movement here on 2023-10-30.          -->\n\n<!-- Datafiles have default rows and columns -->\n<xsl:variable name=\"datafile-default-rows\" select=\"20\"/>\n<xsl:variable name=\"datafile-default-cols\" select=\"60\"/>\n\n<!-- Get a \"view\" of a chunk of text, from the \"upper-left corner\".  -->\n<!-- Motivation is a static version of a (large) datafile of text    -->\n<!-- for interactive programs to consume.                            -->\n<!--   text: the text, we provide a version hit by \"santitize-tex\"   -->\n<!--         above, which pulls left, and drops leading blank lines. -->\n<!--   nrows: the number of (initial) lines output                   -->\n<!--   ncols: the number of (initial) characters on each line        -->\n<!--          if not provided, the entire line is output             -->\n<!--                                                                 -->\n<!-- NB: there can be excess blank lines (nrows in not a maximum)    -->\n<!-- TODO: could be extended to have a \"start\" location other than   -->\n<!-- upper left corner.  Consume initial lines with no action,       -->\n<!-- decrementing start line, then switch to outputing lines         -->\n<!-- themselves.  Substring selection should be obvious.             -->\n<xsl:template name=\"text-viewport\">\n    <xsl:param name=\"text\"/>\n    <xsl:param name=\"nrows\"/>\n    <xsl:param name=\"ncols\" select=\"''\"/>\n\n    <xsl:choose>\n        <!-- decremented (or initialized) to zero or below -->\n        <xsl:when test=\"$nrows &lt; 1\"/>\n        <!-- produce a line and recurse -->\n        <xsl:otherwise>\n            <xsl:variable name=\"line\" select=\"substring-before($text, '&#xa;')\"/>\n            <xsl:choose>\n                <!-- sentinel: output whole line -->\n                <xsl:when test=\"$ncols = ''\">\n                    <xsl:value-of select=\"$line\"/>\n                </xsl:when>\n                <!-- within length limit: output whole line -->\n                <xsl:when test=\"string-length($line) &lt;= $ncols\">\n                    <xsl:value-of select=\"$line\"/>\n                </xsl:when>\n                <!-- truncate line to value of $ncols-1, and add  -->\n                <!-- a simple right arrow to indicate truncation  -->\n                <xsl:otherwise>\n                    <xsl:value-of select=\"substring($line, 1, $ncols - 1)\"/>\n                    <!-- Unicode Character 'RIGHTWARDS ARROW' -->\n                    <xsl:text>&#x2192;</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n            <!-- restore the missing line-break -->\n            <xsl:value-of select=\"'&#xa;'\"/>\n            <!-- rceurse, with remainder of text, requesting  -->\n            <!-- one less row, and simply passing along ncols -->\n            <xsl:call-template name=\"text-viewport\">\n                <xsl:with-param name=\"text\" select=\"substring-after($text, '&#xa;')\"/>\n                <xsl:with-param name=\"nrows\" select=\"$nrows - 1\"/>\n                <xsl:with-param name=\"ncols\" select=\"$ncols\"/>\n            </xsl:call-template>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n</xsl:stylesheet>\n","pretext-view-source.xsl":"<?xml version='1.0'?> <!-- As XML file -->\n\n<!--********************************************************************\nCopyright (C) 2019-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!-- http://pimpmyxslt.com/articles/entity-tricks-part2/ -->\n<!DOCTYPE xsl:stylesheet [\n    <!ENTITY % entities SYSTEM \"entities.ent\">\n    %entities;\n]>\n\n<!-- Identify as a stylesheet -->\n<!-- We choose to not include a default namespace       -->\n<!-- (in particular  http://www.w3.org/1999/xhtml),     -->\n<!-- even if this complicates adding namespaces onto    -->\n<!-- derivatives, such as HTML destined for EPUB output -->\n<!-- xmlns=\"http://www.w3.org/1999/xhtml\"               -->\n<xsl:stylesheet\n    xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\"\n    xmlns:pi=\"http://pretextbook.org/2020/pretext/internal\"\n    xmlns:xml=\"http://www.w3.org/XML/1998/namespace\"\n    xmlns:exsl=\"http://exslt.org/common\"\n    exclude-result-prefixes=\"pi\"\n    extension-element-prefixes=\"exsl\"\n>\n\n<!--                       IMPORTANT                         -->\n<!-- The \"sanitize-text\" template can be called on sizeable  -->\n<!-- chunks of text, in a recursive manner, and then looks   -->\n<!-- like runaway recursion.  \"xsltproc\" has a \"-maxdepth\"   -->\n<!-- argument.  For the sample article, we increased it from -->\n<!-- 3000 to 6000 to prevent a spurious error.               -->\n\n<!-- We assume the source is in great shape, typically having been -->\n<!-- created by a pretty-printing tool.  So we keep all the        -->\n<!-- whitespace as being of interest to human reader.   This is    -->\n<!-- the beauty of a separate stylesheet here:                     -->\n<!--   (a) we can override the strip-space declarations            -->\n<!--       of the main HTML stylesheet                             -->\n<!--   (b) the election of the addition of source annotations      -->\n<!--       is made by simply using a different stylesheet          -->\n<xsl:preserve-space elements=\"*\"/>\n<!-- But whitespace in the root element gets regurgitated          -->\n<!-- outside/before/above any file writing and ends up on the      -->\n<!-- terminal.  So we kill it with no loss.                        -->\n<xsl:strip-space elements=\"pretext\"/>\n\n<!-- Below, we use a purpose-built attribute to match elements which    -->\n<!-- have been through the pre-proccessor with their (nearly-)original  -->\n<!-- progenitors.  So we need this id here, late in the game, but we    -->\n<!-- don't want authors wondering if they should be authoring it in     -->\n<!-- their source.  So at the last minute, while creating text versions -->\n<!-- of source material, we kill it.  Any similar leakage could be      -->\n<!-- handled the same way.                                              -->\n<xsl:template match=\"@pi:original-id\" mode=\"xml-to-string\"/>\n\n\n<!-- N.B.: the -assembly stylesheet first construct a \"version\" which   -->\n<!-- is the resolution of version support and customizations.  Then     -->\n<!-- \"original-id\" are added in the next pass.  These are solely for    -->\n<!-- the purpose of \"going back\" to this second pass to identify pieces -->\n<!-- of a document before the assembly process perturbs them.  So the   -->\n<!-- key tree this next template acts on is in the variable             -->\n<!-- $original-labeled.  Just above we explain how these id's get       -->\n<!-- scrubbed before presenting source to the reader.                   -->\n\n<!-- The template to place into the HTML stylesheet, which is        -->\n<!-- overriding a do-nothing stub in the HTML stylesheet.  This is   -->\n<!-- a no-op unless the $b-view-source has been set to true()        -->\n<!-- electively.  Not too much of a performance hit as bailing out   -->\n<!-- is quick, and use is limited to divisions and blocks (roughly). -->\n<xsl:template match=\"*\" mode=\"view-source-widget\">\n    <!-- Footnotes are silly to annotate, and are also automatically -->\n    <!-- generated for URLs and hence have no original source, so we -->\n    <!-- kill them here.  Careful experiments suggest these are the  -->\n    <!-- only elements without source.                               -->\n    <xsl:variable name=\"b-banned\" select=\"boolean(self::fn)\"/>\n    <xsl:if test=\"$b-view-source and not($b-banned)\">\n        <!-- Part 1: Serialize the source -->\n        <!-- Save off the id of the element being annotated -->\n        <xsl:variable name=\"the-element-id\" select=\"@pi:original-id\"/>\n        <!-- Locate the element with the same id, but in a very early -->\n        <!-- pass of the assembly stylesheet, so with as little (no?) -->\n        <!-- extraneous manufactured markup as possible.              -->\n        <xsl:variable name=\"original-element\" select=\"$original-labeled//*[@pi:original-id = $the-element-id]\"/>\n        <!-- Just for convenience, capture highly sanitized text      -->\n        <!-- version of the XML source within a variable.             -->\n        <!--                                                          -->\n        <!--   (1) Grab the node *just prior* to the element.         -->\n        <!--   (2) This ends with a newline and then some             -->\n        <!--       indentation, we grab this indentation.             -->\n        <!--   (3) Serialize the element, a photocopy machine         -->\n        <!--       which converts XML nodes into text (originally     -->\n        <!--       built to put HTML into JSON for Jupyter).          -->\n        <!--   (4) Run (2)+(3) through \"sanitize-text\" mainly to pull -->\n        <!--       the whole stanza left, since it may have a lot of  -->\n        <!--       common indentation (which is why we caught         -->\n        <!--       the preceding indentation).                        -->\n        <!--   (5) Run that through \"sanitize-text\" to deindent       -->\n        <!-- NB: the $original-element is used *twice* below, in      -->\n        <!-- order to have the right conteaxt for the manipulations   -->\n        <xsl:variable name=\"serialized-html\">\n            <xsl:variable name=\"serialized-html-raw\">\n                <xsl:variable name=\"lead-in\">\n                    <xsl:apply-templates select=\"$original-element/preceding-sibling::node()[1]\" mode=\"xml-to-string\">\n                        <xsl:with-param name=\"depth\" select=\"1\"/>\n                    </xsl:apply-templates>\n                </xsl:variable>\n                <xsl:call-template name=\"substring-after-last\">\n                    <xsl:with-param name=\"input\" select=\"$lead-in\" />\n                    <xsl:with-param name=\"substr\" select=\"'&#xa;'\" />\n                </xsl:call-template>\n                <xsl:apply-templates select=\"$original-element\" mode=\"xml-to-string\">\n                    <xsl:with-param name=\"depth\" select=\"1\"/>\n                </xsl:apply-templates>\n            </xsl:variable>\n            <xsl:call-template name=\"sanitize-text\">\n                <xsl:with-param name=\"text\">\n                    <xsl:value-of select=\"$serialized-html-raw\"/>\n                </xsl:with-param>\n            </xsl:call-template>\n        </xsl:variable>\n\n        <!-- Part 2: drop the source into a details on the page -->\n        <details class=\"source-view\">\n          <summary class=\"source-view__link\" data-reveal-label=\"Open\" data-close-label=\"Close\">\n              <!-- TODO: internationalize me? -->\n              <xsl:text>View Source for </xsl:text><xsl:value-of select=\"name()\"/>\n          </summary>\n          <!-- -->\n          <article class=\"view-source-view__content\" >\n              <pre>\n                  <code class=\"language-xml\">\n                      <xsl:value-of select=\"$serialized-html\"/>\n                  </code>\n              </pre>\n          </article>\n      </details>\n\n    </xsl:if>\n</xsl:template>\n\n</xsl:stylesheet>\n","publisher-variables.xsl":"<?xml version='1.0'?>\n\n<!--********************************************************************\nCopyright (C) 2020-2026  Robert A. Beezer\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<xsl:stylesheet\n    xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\"\n    xmlns:xml=\"http://www.w3.org/XML/1998/namespace\"\n    xmlns:pi=\"http://pretextbook.org/2020/pretext/internal\"\n    xmlns:exsl=\"http://exslt.org/common\"\n    xmlns:str=\"http://exslt.org/strings\"\n    xmlns:dyn=\"http://exslt.org/dynamic\"\n    extension-element-prefixes=\"exsl str dyn\"\n>\n\n<!-- ######################### -->\n<!-- Publisher Options Support -->\n<!-- ######################### -->\n\n<!-- Elements and attributes of a publisher file are meant to          -->\n<!-- influence decisions taken *after* an author is completed writing. -->\n<!-- In limited cases a command-line string parameter may be used to   -->\n<!-- override the settings (especially for testing purposes).          -->\n<!-- In other cases, deprecated string parameters may be consulted     -->\n<!-- secondarily, for a limited time.                                  -->\n\n<!-- A single command-line string parameter points to an XML file that      -->\n<!-- is structured to carry various options that a *publisher* might set.   -->\n<!-- Generally, these affect the *look* of the output, rather than the      -->\n<!-- actual *content* that appears on the page, i.e. the actual characters. -->\n<!-- We initialize with an empty node-set, then if not used, there is no    -->\n<!-- loading of the entire source all over again (which seems to be the     -->\n<!-- case with an empty string).  When set on the command-line, a string    -->\n<!-- value will be interpreted correctly. -->\n<xsl:param name=\"publisher\" select=\"/..\"/>\n\n<!-- NB: the second argument is simply a node, it causes $publisher -->\n<!-- to be interpreted relative to the location of the *current XML -->\n<!-- file* rather than the location of the *stylesheet*. The actual -->\n<!-- node does not seem so critical.                                -->\n<!-- NB A publisher might provide a filename, which when resolved   -->\n<!-- as an absolute path (think \"My Documents\") by some helper      -->\n<!-- program or front-end, will arrive here containing a space,     -->\n<!-- which will cause the  document()  function to fail silently.   -->\n<!-- The location provided in the first argument of document() is   -->\n<!-- a URI, so the proper escape mechanism is percent-encoding.     -->\n<xsl:variable name=\"publication\" select=\"document(str:replace($publisher, '&#x20;', '%20'), .)/publication\"/>\n\n<!-- The \"publisher-variables.xsl\" and \"pretext-assembly.xsl\"      -->\n<!-- stylesheets are symbiotic, and should be imported             -->\n<!-- simultaneously.  Assembly will change the source in various   -->\n<!-- ways, while some defaults for publisher variables will depend -->\n<!-- on source.  The default variables should depend on gross      -->\n<!-- structure and adjustments should be to smaller portions of    -->\n<!-- the source, but we don't take any chances.  So, note in       -->\n<!-- \"assembly\" that an intermediate tree is defined as a          -->\n<!-- variable, which is then used in defining some variables,      -->\n<!-- based on assembled source.  Conversely, certain variables,    -->\n<!-- such as locations of customizations or private solutions,     -->\n<!-- are needed early in assembly, while other variables, such     -->\n<!-- as options for numbering, are needed for later enhancements   -->\n<!-- to the source.  If new code results in undefined, or          -->\n<!-- recursively defined, variables, this discussion may be        -->\n<!-- relevant.  (This is repeated verbatim in the other            -->\n<!-- stylesheet).                                                  -->\n<!--                                                               -->\n<!-- Also, in this stylesheet, we should not be letting \"docinfo\"  -->\n<!-- directly set variables, as \"docinfo\" contains                 -->\n<!-- settings/characteristics that are part of the author's source -->\n<!-- and are not changed/influenced by a publisher.  Some uses are -->\n<!-- historical when we we were not so aware of the distinction,   -->\n<!-- and some uses are tangential (such as the type of \"part\" the  -->\n<!-- author has chosen).                                           -->\n\n<!-- ############## -->\n<!-- Common Options -->\n<!-- ############## -->\n\n<!-- Override chunking publisher variable, for testing -->\n<xsl:param name=\"debug.chunk\" select=\"''\"/>\n\n<xsl:variable name=\"chunks\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/chunking/pi:pub-attribute[@name='level']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- We do not convert this to a number since various   -->\n<!-- conversions will consume this and produce their    -->\n<!-- own defaults, and we need to recognize \"no choice\" -->\n<!-- as an empty string -->\n<xsl:variable name=\"chunk-level-entered\" select=\"string($chunks)\"/>\n\n<!-- ############################# -->\n<!-- Structure of the Version Tree -->\n<!-- ############################# -->\n\n<!-- Some defaults below depend on the document's structure, which     -->\n<!-- can differ by version, so they consult the assembly \"version\"     -->\n<!-- pass via $version-root.  Later assembly passes depend on those    -->\n<!-- variables in turn; the dependencies stay acyclic because the      -->\n<!-- passes up to, and including, \"version\" never consult a            -->\n<!-- structure-dependent variable.  The facts below are the crossing   -->\n<!-- point: the only place a publisher variable consults               -->\n<!-- $version-root, so the structure-dependent population is easy to   -->\n<!-- enumerate.  (Exception: deprecated \"docinfo\" consultations,       -->\n<!-- marked where they occur, which will disappear with them.)         -->\n\n<!-- the document type is the element being converted -->\n<xsl:variable name=\"version-doc-type\" select=\"local-name($version-document-root)\"/>\n\n<!-- An article is \"sectioned\" for every structure-driven default    -->\n<!-- below when it has a \"section\", a \"worksheet\", or a \"handout\":   -->\n<!-- the three are peers at the same level, so a workbook of         -->\n<!-- printouts numbers and chunks as a sectioned article does.       -->\n<xsl:variable name=\"version-has-parts\"           select=\"boolean($version-root/book/part)\"/>\n<xsl:variable name=\"version-book-chapters\"       select=\"boolean($version-root/book/part/chapter|$version-root/book/chapter)\"/>\n<xsl:variable name=\"version-book-sections\"       select=\"boolean($version-root/book/part/chapter/section|$version-root/book/chapter/section)\"/>\n<xsl:variable name=\"version-article-sections\"    select=\"boolean($version-root/article/section)\"/>\n<xsl:variable name=\"version-article-printouts\"   select=\"boolean($version-root/article/worksheet|$version-root/article/handout)\"/>\n<xsl:variable name=\"version-article-subsections\" select=\"boolean($version-root/article/section/subsection)\"/>\n\n<!-- A book must have a chapter              -->\n<!-- An article need not have a section      -->\n<!-- This gets replaced in -latex stylehseet -->\n<xsl:variable name=\"toc-level-entered\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/tableofcontents/pi:pub-attribute[@name='level']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:template match=\"common/tableofcontents/pi:pub-attribute[@name='level']\" mode=\"get-default-pub-variable\">\n    <xsl:choose>\n        <!-- defaults purely by structure, not by output format -->\n        <xsl:when test=\"$version-has-parts and $version-book-sections\">3</xsl:when>\n        <xsl:when test=\"$version-has-parts and $version-book-chapters\">2</xsl:when>\n        <xsl:when test=\"$version-book-sections\">2</xsl:when>\n        <xsl:when test=\"$version-book-chapters\">1</xsl:when>\n        <xsl:when test=\"$version-article-subsections\">2</xsl:when>\n        <xsl:when test=\"$version-article-sections or $version-article-printouts\">1</xsl:when>\n        <xsl:when test=\"$version-doc-type = 'article'\">0</xsl:when>\n        <xsl:when test=\"$version-doc-type = 'slideshow'\">0</xsl:when>\n        <xsl:when test=\"$version-doc-type = 'letter'\">0</xsl:when>\n        <xsl:when test=\"$version-doc-type = 'memo'\">0</xsl:when>\n        <xsl:otherwise>\n            <xsl:message>PTX:BUG:   Table of Contents level not determined</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n<xsl:variable name=\"toc-level\" select=\"number($toc-level-entered)\"/>\n\n<!-- Flag Table of Contents, or not, with boolean variable -->\n<xsl:variable name=\"b-has-toc\" select=\"$toc-level > 0\" />\n\n<!-- Fillin styles (underline, box, shade) -->\n<xsl:variable name=\"fillin-text-style\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/fillin/pi:pub-attribute[@name='textstyle']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"fillin-math-style\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/fillin/pi:pub-attribute[@name='mathstyle']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"mermaid-theme\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/mermaid/pi:pub-attribute[@name='theme']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"mermaid-layout-engine\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/mermaid/pi:pub-attribute[@name='layout-engine']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- QR code image to be placed at center of QR codes -->\n<xsl:variable name=\"qrcode-image\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/qrcode/pi:pub-attribute[@name='image']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- Em dash Width -->\n\n<xsl:variable name=\"emdash-space\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/pi:pub-attribute[@name='emdash-space']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- Watermarking -->\n<!-- Variables for watermark text (simple!), and a scale factor. -->\n<!-- Boolean variables for existence (one is deprecated LaTeX).  -->\n\n<xsl:variable name=\"watermark-text\">\n    <xsl:choose>\n        <!-- via publication file -->\n        <xsl:when test=\"$publication/common/watermark\">\n            <xsl:value-of select=\"$publication/common/watermark\"/>\n        </xsl:when>\n        <!-- string parameter, general -->\n        <xsl:when test=\"($watermark.text != '')\">\n            <xsl:value-of select=\"$watermark.text\"/>\n        </xsl:when>\n        <!-- old LaTeX-specific string parameter -->\n        <xsl:when test=\"($latex.watermark != '')\">\n            <xsl:value-of select=\"$latex.watermark\"/>\n        </xsl:when>\n        <!-- won't get employed if we get here, but... -->\n        <xsl:otherwise/>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- Unedited comment, copied from old code:                            -->\n<!-- watermark uses a 5cm font, which can be scaled                     -->\n<!-- and scaling by 0.5 makes \"CONFIDENTIAL\" fit well in 600 pixel HTML -->\n<!-- and in the default body width for LaTeX                            -->\n\n<xsl:variable name=\"watermark-scale\">\n    <xsl:choose>\n        <!-- via publication file -->\n        <xsl:when test=\"$publication/common/watermark and $publication/common/watermark/@scale\">\n            <xsl:value-of select=\"$publication/common/watermark/@scale\"/>\n        </xsl:when>\n        <!-- string parameter, general -->\n        <xsl:when test=\"($watermark.text != '') and ($watermark.scale != '')\">\n            <xsl:value-of select=\"$watermark.scale\"/>\n        </xsl:when>\n        <!-- old LaTeX-specific string parameter -->\n        <xsl:when test=\"($latex.watermark != '') and ($latex.watermark.scale != '')\">\n            <xsl:value-of select=\"$latex.watermark.scale\"/>\n        </xsl:when>\n        <!-- employ (historical) defaults to accompany provided text-->\n        <xsl:otherwise>\n            <xsl:choose>\n                <!-- via publication file -->\n                <xsl:when test=\"$publication/common/watermark\">\n                    <xsl:text>0.5</xsl:text>\n                </xsl:when>\n                <!-- string parameter, general -->\n                <xsl:when test=\"($watermark.text != '')\">\n                    <xsl:text>0.5</xsl:text>\n                </xsl:when>\n                <!-- old LaTeX-specific string parameter -->\n                <xsl:when test=\"($latex.watermark != '')\">\n                    <xsl:text>2.0</xsl:text>\n                </xsl:when>\n                <!-- won't get employed if we get here, but... -->\n                <xsl:otherwise/>\n            </xsl:choose>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- General watermarking, publication file or deprecated stringparam.  Plus  .-->\n<!-- the option of double-deprecated string parameter (indicating LaTeX only). -->\n<xsl:variable name=\"b-watermark\" select=\"$publication/common/watermark or ($watermark.text != '')\"/>\n<xsl:variable name=\"b-latex-watermark\" select=\"$b-watermark or ($latex.watermark != '')\"/>\n\n<!-- Journal name for bibliography formatting and latex style selection -->\n<xsl:variable name=\"journal-name\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/journal/pi:pub-attribute[@name='name']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- This is the minimum information to locate a     -->\n<!-- Citation Stylesheet Language (CSL) style file   -->\n<!-- in the CSL repository.  It is not expected to   -->\n<!-- have the \".csl\" suffix, but should have partial -->\n<!-- path names, such as \"dependent/\".  Employers    -->\n<!-- should provide \".cls\" and any additional path   -->\n<!-- information.                                    -->\n<xsl:variable name=\"csl-style-file\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/citation-stylesheet-language/pi:pub-attribute[@name='style']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<!-- global indication of if a publisher has opted in -->\n<xsl:variable name=\"b-using-csl-styles\" select=\"not(normalize-space($csl-style-file) = '')\"/>\n<!-- if using styles we form the filename of generated references and citations -->\n<xsl:variable name=\"csl-file\">\n    <xsl:choose>\n        <xsl:when test=\"$b-using-csl-styles\">\n            <xsl:value-of select=\"$generated-directory-source\"/>\n            <xsl:text>references/csl-bibliography.xml</xsl:text>\n        </xsl:when>\n        <!-- explicitly empty/null if not using CSL styles -->\n        <xsl:otherwise/>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- Printout margins.  Applies to both PDF and HTML. -->\n\n<xsl:variable name=\"ws-margin\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/worksheet/pi:pub-attribute[@name='margin']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"ws-margin-top\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/worksheet/pi:pub-attribute[@name='top']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"ws-margin-right\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/worksheet/pi:pub-attribute[@name='right']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"ws-margin-bottom\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/worksheet/pi:pub-attribute[@name='bottom']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"ws-margin-left\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/worksheet/pi:pub-attribute[@name='left']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<!-- Set the default values of each directional margin to be the value of the ws-margin element -->\n<xsl:template match=\"common/worksheet/pi:pub-attribute[@name='top']\" mode=\"get-default-pub-variable\">\n    <xsl:value-of select=\"$ws-margin\"/>\n</xsl:template>\n<xsl:template match=\"common/worksheet/pi:pub-attribute[@name='right']\" mode=\"get-default-pub-variable\">\n    <xsl:value-of select=\"$ws-margin\"/>\n</xsl:template>\n<xsl:template match=\"common/worksheet/pi:pub-attribute[@name='bottom']\" mode=\"get-default-pub-variable\">\n    <xsl:value-of select=\"$ws-margin\"/>\n</xsl:template>\n<xsl:template match=\"common/worksheet/pi:pub-attribute[@name='left']\" mode=\"get-default-pub-variable\">\n    <xsl:value-of select=\"$ws-margin\"/>\n</xsl:template>\n\n<!-- Printout headers and footers.  We have separate variables for \"first-page\" and \"running\" -->\n<!-- Each can take a \"left\", \"center\", and \"right\" value. -->\n<xsl:variable name=\"ws-header-first-left\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/worksheet/first-page-header/pi:pub-attribute[@name='left']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"ws-header-first-center\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/worksheet/first-page-header/pi:pub-attribute[@name='center']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"ws-header-first-right\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/worksheet/first-page-header/pi:pub-attribute[@name='right']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"ws-header-running-left\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/worksheet/running-header/pi:pub-attribute[@name='left']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"ws-header-running-center\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/worksheet/running-header/pi:pub-attribute[@name='center']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"ws-header-running-right\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/worksheet/running-header/pi:pub-attribute[@name='right']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"ws-footer-first-left\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/worksheet/first-page-footer/pi:pub-attribute[@name='left']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"ws-footer-first-center\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/worksheet/first-page-footer/pi:pub-attribute[@name='center']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"ws-footer-first-right\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/worksheet/first-page-footer/pi:pub-attribute[@name='right']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"ws-footer-running-left\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/worksheet/running-footer/pi:pub-attribute[@name='left']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"ws-footer-running-center\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/worksheet/running-footer/pi:pub-attribute[@name='center']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"ws-footer-running-right\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/common/worksheet/running-footer/pi:pub-attribute[@name='right']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- ########################### -->\n<!-- Exercise component switches -->\n<!-- ########################### -->\n\n<!-- We santitize exercise component switches.  These control -->\n<!-- text/narrative appearances *only*, solution lists in the -->\n<!-- backmatter are given in alternate ways.  However, an     -->\n<!-- alternate conversion (such as an Instructor's Guide) may -->\n<!-- use these as well. We only do quality control here.      -->\n<!-- The first \"*.text.*\" forms are deprecated with warnings  -->\n<!-- elsewhere, but we try to preserve their intent here.     -->\n<!-- The second \"exercise.{type}.{component}\" also have       -->\n<!-- deprecation warnings elsewhere, and are honored here.    -->\n<!-- NB: \"-statement\" versions are necessary for the solution -->\n<!-- manual stylesheet, which feeds these into the solutions  -->\n<!-- generator template.                                      -->\n\n<xsl:variable name=\"entered-exercise-inline-statement\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/common/exercise-inline/@statement\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/common/exercise-inline/@statement = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/common/exercise-inline/@statement = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK:   the exercise component visibility setting (common/exercise-inline/@statement in the publisher file) must be \"yes\" or \"no\", not \"<xsl:value-of select=\"$publication/common/exercise-inline/@statement\"/>\".  Proceeding with the default, which is \"yes\".</xsl:message>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- deprecated, but still honored -->\n        <xsl:when test=\"($exercise.inline.statement = 'yes') or\n                        ($exercise.inline.statement = 'no')\">\n            <xsl:value-of select=\"$exercise.inline.statement\" />\n        </xsl:when>\n        <!-- deprecated, but still honored, though with no error-checking, -->\n        <!-- erroneous values will fall into default of replacement switch -->\n        <xsl:when test=\"($exercise.text.statement = 'yes') or ($exercise.text.statement = 'no')\">\n            <xsl:value-of select=\"$exercise.text.statement\" />\n        </xsl:when>\n        <!-- stick with no action by author/publisher -->\n        <xsl:when test=\"$exercise.inline.statement = ''\">\n            <xsl:value-of select=\"$exercise.text.statement\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:FALLBACK: exercise.inline.statement parameter should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$exercise.inline.statement\" />\".  Proceeding with default value.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"entered-exercise-inline-hint\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/common/exercise-inline/@hint\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/common/exercise-inline/@hint = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/common/exercise-inline/@hint = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK:   the exercise component visibility setting (common/exercise-inline/@hint in the publisher file) must be \"yes\" or \"no\", not \"<xsl:value-of select=\"$publication/common/exercise-inline/@hint\"/>\".  Proceeding with the default, which is \"yes\".</xsl:message>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- deprecated, but still honored -->\n        <xsl:when test=\"($exercise.inline.hint = 'yes') or\n                        ($exercise.inline.hint = 'no')\">\n            <xsl:value-of select=\"$exercise.inline.hint\" />\n        </xsl:when>\n        <!-- deprecated, but still honored, though with no error-checking, -->\n        <!-- erroneous values will fall into default of replacement switch -->\n        <xsl:when test=\"($exercise.text.hint = 'yes') or ($exercise.text.hint = 'no')\">\n            <xsl:value-of select=\"$exercise.text.hint\" />\n        </xsl:when>\n        <!-- stick with no action by author/publisher -->\n        <xsl:when test=\"$exercise.inline.hint = ''\">\n            <xsl:value-of select=\"$exercise.text.hint\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:FALLBACK: exercise.inline.hint parameter should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$exercise.inline.hint\" />\".  Proceeding with default value.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"entered-exercise-inline-answer\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/common/exercise-inline/@answer\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/common/exercise-inline/@answer = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/common/exercise-inline/@answer = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK:   the exercise component visibility setting (common/exercise-inline/@answer in the publisher file) must be \"yes\" or \"no\", not \"<xsl:value-of select=\"$publication/common/exercise-inline/@answer\"/>\".  Proceeding with the default, which is \"yes\".</xsl:message>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- deprecated, but still honored -->\n        <xsl:when test=\"($exercise.inline.answer = 'yes') or\n                        ($exercise.inline.answer = 'no')\">\n            <xsl:value-of select=\"$exercise.inline.answer\" />\n        </xsl:when>\n        <!-- deprecated, but still honored, though with no error-checking, -->\n        <!-- erroneous values will fall into default of replacement switch -->\n        <xsl:when test=\"($exercise.text.answer = 'yes') or ($exercise.text.answer = 'no')\">\n            <xsl:value-of select=\"$exercise.text.answer\" />\n        </xsl:when>\n        <!-- stick with no action by author/publisher -->\n        <xsl:when test=\"$exercise.inline.answer = ''\">\n            <xsl:value-of select=\"$exercise.text.answer\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:FALLBACK: exercise.inline.answer parameter should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$exercise.inline.answer\" />\".  Proceeding with default value.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"entered-exercise-inline-solution\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/common/exercise-inline/@solution\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/common/exercise-inline/@solution = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/common/exercise-inline/@solution = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK:   the exercise component visibility setting (common/exercise-inline/@solution in the publisher file) must be \"yes\" or \"no\", not \"<xsl:value-of select=\"$publication/common/exercise-inline/@solution\"/>\".  Proceeding with the default, which is \"yes\".</xsl:message>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- deprecated, but still honored -->\n        <xsl:when test=\"($exercise.inline.solution = 'yes') or\n                        ($exercise.inline.solution = 'no')\">\n            <xsl:value-of select=\"$exercise.inline.solution\" />\n        </xsl:when>\n        <!-- deprecated, but still honored, though with no error-checking, -->\n        <!-- erroneous values will fall into default of replacement switch -->\n        <xsl:when test=\"($exercise.text.solution = 'yes') or ($exercise.text.solution = 'no')\">\n            <xsl:value-of select=\"$exercise.text.solution\" />\n        </xsl:when>\n        <!-- stick with no action by author/publisher -->\n        <xsl:when test=\"$exercise.inline.solution = ''\">\n            <xsl:value-of select=\"$exercise.text.solution\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:FALLBACK: exercise.inline.solution parameter should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$exercise.inline.solution\" />\".  Proceeding with default value.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"entered-exercise-divisional-statement\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/common/exercise-divisional/@statement\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/common/exercise-divisional/@statement = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/common/exercise-divisional/@statement = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK:   the exercise component visibility setting (common/exercise-divisional/@statement in the publisher file) must be \"yes\" or \"no\", not \"<xsl:value-of select=\"$publication/common/exercise-divisional/@statement\"/>\".  Proceeding with the default, which is \"yes\".</xsl:message>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- deprecated, but still honored -->\n        <xsl:when test=\"($exercise.divisional.statement = 'yes') or\n                        ($exercise.divisional.statement = 'no')\">\n            <xsl:value-of select=\"$exercise.divisional.statement\" />\n        </xsl:when>\n        <!-- deprecated, but still honored, though with no error-checking, -->\n        <!-- erroneous values will fall into default of replacement switch -->\n        <xsl:when test=\"($exercise.text.statement = 'yes') or ($exercise.text.statement = 'no')\">\n            <xsl:value-of select=\"$exercise.text.statement\" />\n        </xsl:when>\n        <!-- stick with no action by author/publisher -->\n        <xsl:when test=\"$exercise.divisional.statement = ''\">\n            <xsl:value-of select=\"$exercise.divisional.statement\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:FALLBACK: exercise.divisional.statement parameter should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$exercise.divisional.statement\" />\".  Proceeding with default value.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"entered-exercise-divisional-hint\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/common/exercise-divisional/@hint\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/common/exercise-divisional/@hint = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/common/exercise-divisional/@hint = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK:   the exercise component visibility setting (common/exercise-divisional/@hint in the publisher file) must be \"yes\" or \"no\", not \"<xsl:value-of select=\"$publication/common/exercise-divisional/@hint\"/>\".  Proceeding with the default, which is \"yes\".</xsl:message>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- deprecated, but still honored -->\n        <xsl:when test=\"($exercise.divisional.hint = 'yes') or\n                        ($exercise.divisional.hint = 'no')\">\n            <xsl:value-of select=\"$exercise.divisional.hint\" />\n        </xsl:when>\n        <!-- deprecated, but still honored, though with no error-checking, -->\n        <!-- erroneous values will fall into default of replacement switch -->\n        <xsl:when test=\"($exercise.text.hint = 'yes') or ($exercise.text.hint = 'no')\">\n            <xsl:value-of select=\"$exercise.text.hint\" />\n        </xsl:when>\n        <!-- stick with no action by author/publisher -->\n        <xsl:when test=\"$exercise.divisional.hint = ''\">\n            <xsl:value-of select=\"$exercise.divisional.hint\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:FALLBACK: exercise.divisional.hint parameter should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$exercise.divisional.hint\" />\".  Proceeding with default value.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"entered-exercise-divisional-answer\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/common/exercise-divisional/@answer\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/common/exercise-divisional/@answer = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/common/exercise-divisional/@answer = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK:   the exercise component visibility setting (common/exercise-divisional/@answer in the publisher file) must be \"yes\" or \"no\", not \"<xsl:value-of select=\"$publication/common/exercise-divisional/@answer\"/>\".  Proceeding with the default, which is \"yes\".</xsl:message>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- deprecated, but still honored -->\n        <xsl:when test=\"($exercise.divisional.answer = 'yes') or\n                        ($exercise.divisional.answer = 'no')\">\n            <xsl:value-of select=\"$exercise.divisional.answer\" />\n        </xsl:when>\n        <!-- deprecated, but still honored, though with no error-checking, -->\n        <!-- erroneous values will fall into default of replacement switch -->\n        <xsl:when test=\"($exercise.text.answer = 'yes') or ($exercise.text.answer = 'no')\">\n            <xsl:value-of select=\"$exercise.text.answer\" />\n        </xsl:when>\n        <!-- stick with no action by author/publisher -->\n        <xsl:when test=\"$exercise.divisional.answer = ''\">\n            <xsl:value-of select=\"$exercise.divisional.answer\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:FALLBACK: exercise.divisional.answer parameter should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$exercise.divisional.answer\" />\".  Proceeding with default value.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"entered-exercise-divisional-solution\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/common/exercise-divisional/@solution\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/common/exercise-divisional/@solution = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/common/exercise-divisional/@solution = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK:   the exercise component visibility setting (common/exercise-divisional/@solution in the publisher file) must be \"yes\" or \"no\", not \"<xsl:value-of select=\"$publication/common/exercise-divisional/@solution\"/>\".  Proceeding with the default, which is \"yes\".</xsl:message>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- deprecated, but still honored -->\n        <xsl:when test=\"($exercise.divisional.solution = 'yes') or\n                        ($exercise.divisional.solution = 'no')\">\n            <xsl:value-of select=\"$exercise.divisional.solution\" />\n        </xsl:when>\n        <!-- deprecated, but still honored, though with no error-checking, -->\n        <!-- erroneous values will fall into default of replacement switch -->\n        <xsl:when test=\"($exercise.text.solution = 'yes') or ($exercise.text.solution = 'no')\">\n            <xsl:value-of select=\"$exercise.text.solution\" />\n        </xsl:when>\n        <!-- stick with no action by author/publisher -->\n        <xsl:when test=\"$exercise.divisional.solution = ''\">\n            <xsl:value-of select=\"$exercise.divisional.solution\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:FALLBACK: exercise.divisional.solution parameter should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$exercise.divisional.solution\" />\".  Proceeding with default value.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"entered-exercise-worksheet-statement\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/common/exercise-worksheet/@statement\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/common/exercise-worksheet/@statement = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/common/exercise-worksheet/@statement = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK:   the exercise component visibility setting (common/exercise-worksheet/@statement in the publisher file) must be \"yes\" or \"no\", not \"<xsl:value-of select=\"$publication/common/exercise-worksheet/@statement\"/>\".  Proceeding with the default, which is \"yes\".</xsl:message>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- deprecated, but still honored -->\n        <xsl:when test=\"($exercise.worksheet.statement = 'yes') or\n                        ($exercise.worksheet.statement = 'no')\">\n            <xsl:value-of select=\"$exercise.worksheet.statement\" />\n        </xsl:when>\n        <!-- deprecated, but still honored, though with no error-checking, -->\n        <!-- erroneous values will fall into default of replacement switch -->\n        <xsl:when test=\"($exercise.text.statement = 'yes') or ($exercise.text.statement = 'no')\">\n            <xsl:value-of select=\"$exercise.text.statement\" />\n        </xsl:when>\n        <!-- stick with no action by author/publisher -->\n        <xsl:when test=\"$exercise.worksheet.statement = ''\">\n            <xsl:value-of select=\"$exercise.worksheet.statement\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:FALLBACK: exercise.worksheet.statement parameter should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$exercise.worksheet.statement\" />\".  Proceeding with default value.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"entered-exercise-worksheet-hint\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/common/exercise-worksheet/@hint\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/common/exercise-worksheet/@hint = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/common/exercise-worksheet/@hint = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK:   the exercise component visibility setting (common/exercise-worksheet/@hint in the publisher file) must be \"yes\" or \"no\", not \"<xsl:value-of select=\"$publication/common/exercise-worksheet/@hint\"/>\".  Proceeding with the default, which is \"yes\".</xsl:message>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- deprecated, but still honored -->\n        <xsl:when test=\"($exercise.worksheet.hint = 'yes') or\n                        ($exercise.worksheet.hint = 'no')\">\n            <xsl:value-of select=\"$exercise.worksheet.hint\" />\n        </xsl:when>\n        <!-- deprecated, but still honored, though with no error-checking, -->\n        <!-- erroneous values will fall into default of replacement switch -->\n        <xsl:when test=\"($exercise.text.hint = 'yes') or ($exercise.text.hint = 'no')\">\n            <xsl:value-of select=\"$exercise.text.hint\" />\n        </xsl:when>\n        <!-- stick with no action by author/publisher -->\n        <xsl:when test=\"$exercise.worksheet.hint = ''\">\n            <xsl:value-of select=\"$exercise.worksheet.hint\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:FALLBACK: exercise.worksheet.hint parameter should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$exercise.worksheet.hint\" />\".  Proceeding with default value.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"entered-exercise-worksheet-answer\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/common/exercise-worksheet/@answer\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/common/exercise-worksheet/@answer = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/common/exercise-worksheet/@answer = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK:   the exercise component visibility setting (common/exercise-worksheet/@answer in the publisher file) must be \"yes\" or \"no\", not \"<xsl:value-of select=\"$publication/common/exercise-worksheet/@answer\"/>\".  Proceeding with the default, which is \"yes\".</xsl:message>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- deprecated, but still honored -->\n        <xsl:when test=\"($exercise.worksheet.answer = 'yes') or\n                        ($exercise.worksheet.answer = 'no')\">\n            <xsl:value-of select=\"$exercise.worksheet.answer\" />\n        </xsl:when>\n        <!-- deprecated, but still honored, though with no error-checking, -->\n        <!-- erroneous values will fall into default of replacement switch -->\n        <xsl:when test=\"($exercise.text.answer = 'yes') or ($exercise.text.answer = 'no')\">\n            <xsl:value-of select=\"$exercise.text.answer\" />\n        </xsl:when>\n        <!-- stick with no action by author/publisher -->\n        <xsl:when test=\"$exercise.worksheet.answer = ''\">\n            <xsl:value-of select=\"$exercise.worksheet.answer\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:FALLBACK: exercise.worksheet.answer parameter should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$exercise.worksheet.answer\" />\".  Proceeding with default value.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"entered-exercise-worksheet-solution\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/common/exercise-worksheet/@solution\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/common/exercise-worksheet/@solution = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/common/exercise-worksheet/@solution = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK:   the exercise component visibility setting (common/exercise-worksheet/@solution in the publisher file) must be \"yes\" or \"no\", not \"<xsl:value-of select=\"$publication/common/exercise-worksheet/@solution\"/>\".  Proceeding with the default, which is \"yes\".</xsl:message>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- deprecated, but still honored -->\n        <xsl:when test=\"($exercise.worksheet.solution = 'yes') or\n                        ($exercise.worksheet.solution = 'no')\">\n            <xsl:value-of select=\"$exercise.worksheet.solution\" />\n        </xsl:when>\n        <!-- deprecated, but still honored, though with no error-checking, -->\n        <!-- erroneous values will fall into default of replacement switch -->\n        <xsl:when test=\"($exercise.text.solution = 'yes') or ($exercise.text.solution = 'no')\">\n            <xsl:value-of select=\"$exercise.text.solution\" />\n        </xsl:when>\n        <!-- stick with no action by author/publisher -->\n        <xsl:when test=\"$exercise.worksheet.solution = ''\">\n            <xsl:value-of select=\"$exercise.worksheet.solution\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:FALLBACK: exercise.worksheet.solution parameter should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$exercise.worksheet.solution\" />\".  Proceeding with default value.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"entered-exercise-reading-statement\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/common/exercise-reading/@statement\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/common/exercise-reading/@statement = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/common/exercise-reading/@statement = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK:   the exercise component visibility setting (common/exercise-reading/@statement in the publisher file) must be \"yes\" or \"no\", not \"<xsl:value-of select=\"$publication/common/exercise-reading/@statement\"/>\".  Proceeding with the default, which is \"yes\".</xsl:message>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- deprecated, but still honored -->\n        <xsl:when test=\"($exercise.reading.statement = 'yes') or\n                        ($exercise.reading.statement = 'no')\">\n            <xsl:value-of select=\"$exercise.reading.statement\" />\n        </xsl:when>\n        <!-- deprecated, but still honored, though with no error-checking, -->\n        <!-- erroneous values will fall into default of replacement switch -->\n        <xsl:when test=\"($exercise.text.statement = 'yes') or ($exercise.text.statement = 'no')\">\n            <xsl:value-of select=\"$exercise.text.statement\" />\n        </xsl:when>\n        <!-- stick with no action by author/publisher -->\n        <xsl:when test=\"$exercise.reading.statement = ''\">\n            <xsl:value-of select=\"$exercise.reading.statement\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:FALLBACK: exercise.reading.statement parameter should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$exercise.reading.statement\" />\".  Proceeding with default value.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"entered-exercise-reading-hint\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/common/exercise-reading/@hint\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/common/exercise-reading/@hint = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/common/exercise-reading/@hint = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK:   the exercise component visibility setting (common/exercise-reading/@hint in the publisher file) must be \"yes\" or \"no\", not \"<xsl:value-of select=\"$publication/common/exercise-reading/@hint\"/>\".  Proceeding with the default, which is \"yes\".</xsl:message>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- deprecated, but still honored -->\n        <xsl:when test=\"($exercise.reading.hint = 'yes') or\n                        ($exercise.reading.hint = 'no')\">\n            <xsl:value-of select=\"$exercise.reading.hint\" />\n        </xsl:when>\n        <!-- deprecated, but still honored, though with no error-checking, -->\n        <!-- erroneous values will fall into default of replacement switch -->\n        <xsl:when test=\"($exercise.text.hint = 'yes') or ($exercise.text.hint = 'no')\">\n            <xsl:value-of select=\"$exercise.text.hint\" />\n        </xsl:when>\n        <!-- stick with no action by author/publisher -->\n        <xsl:when test=\"$exercise.reading.hint = ''\">\n            <xsl:value-of select=\"$exercise.reading.hint\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:FALLBACK: exercise.reading.hint parameter should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$exercise.reading.hint\" />\".  Proceeding with default value.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"entered-exercise-reading-answer\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/common/exercise-reading/@answer\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/common/exercise-reading/@answer = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/common/exercise-reading/@answer = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK:   the exercise component visibility setting (common/exercise-reading/@answer in the publisher file) must be \"yes\" or \"no\", not \"<xsl:value-of select=\"$publication/common/exercise-reading/@answer\"/>\".  Proceeding with the default, which is \"yes\".</xsl:message>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- deprecated, but still honored -->\n        <xsl:when test=\"($exercise.reading.answer = 'yes') or\n                        ($exercise.reading.answer = 'no')\">\n            <xsl:value-of select=\"$exercise.reading.answer\" />\n        </xsl:when>\n        <!-- deprecated, but still honored, though with no error-checking, -->\n        <!-- erroneous values will fall into default of replacement switch -->\n        <xsl:when test=\"($exercise.text.answer = 'yes') or ($exercise.text.answer = 'no')\">\n            <xsl:value-of select=\"$exercise.text.answer\" />\n        </xsl:when>\n        <!-- stick with no action by author/publisher -->\n        <xsl:when test=\"$exercise.reading.answer = ''\">\n            <xsl:value-of select=\"$exercise.reading.answer\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:FALLBACK: exercise.reading.answer parameter should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$exercise.reading.answer\" />\".  Proceeding with default value.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"entered-exercise-reading-solution\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/common/exercise-reading/@solution\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/common/exercise-reading/@solution = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/common/exercise-reading/@solution = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK:   the exercise component visibility setting (common/exercise-reading/@solution in the publisher file) must be \"yes\" or \"no\", not \"<xsl:value-of select=\"$publication/common/exercise-reading/@solution\"/>\".  Proceeding with the default, which is \"yes\".</xsl:message>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- deprecated, but still honored -->\n        <xsl:when test=\"($exercise.reading.solution = 'yes') or\n                        ($exercise.reading.solution = 'no')\">\n            <xsl:value-of select=\"$exercise.reading.solution\" />\n        </xsl:when>\n        <!-- deprecated, but still honored, though with no error-checking, -->\n        <!-- erroneous values will fall into default of replacement switch -->\n        <xsl:when test=\"($exercise.text.solution = 'yes') or ($exercise.text.solution = 'no')\">\n            <xsl:value-of select=\"$exercise.text.solution\" />\n        </xsl:when>\n        <!-- stick with no action by author/publisher -->\n        <xsl:when test=\"$exercise.reading.solution = ''\">\n            <xsl:value-of select=\"$exercise.reading.solution\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:FALLBACK: exercise.reading.solution parameter should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$exercise.reading.solution\" />\".  Proceeding with default value.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"entered-project-statement\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/common/exercise-project/@statement\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/common/exercise-project/@statement = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/common/exercise-project/@statement = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK:   the exercise component visibility setting (common/exercise-project/@statement in the publisher file) must be \"yes\" or \"no\", not \"<xsl:value-of select=\"$publication/common/exercise-project/@statement\"/>\".  Proceeding with the default, which is \"yes\".</xsl:message>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- deprecated, but still honored -->\n        <xsl:when test=\"($project.statement = 'yes') or\n                        ($project.statement = 'no')\">\n            <xsl:value-of select=\"$project.statement\" />\n        </xsl:when>\n        <!-- stick with no action by author/publisher -->\n        <xsl:when test=\"$project.statement = ''\">\n            <xsl:value-of select=\"$project.statement\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:FALLBACK: project.statement parameter should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$project.statement\" />\".  Proceeding with default value.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"entered-project-hint\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/common/exercise-project/@hint\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/common/exercise-project/@hint = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/common/exercise-project/@hint = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK:   the exercise component visibility setting (common/exercise-project/@hint in the publisher file) must be \"yes\" or \"no\", not \"<xsl:value-of select=\"$publication/common/exercise-project/@hint\"/>\".  Proceeding with the default, which is \"yes\".</xsl:message>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- deprecated, but still honored -->\n        <xsl:when test=\"($project.hint = 'yes') or\n                        ($project.hint = 'no')\">\n            <xsl:value-of select=\"$project.hint\" />\n        </xsl:when>\n        <!-- deprecated, but still honored, though with no error-checking, -->\n        <!-- erroneous values will fall into default of replacement switch -->\n        <xsl:when test=\"($project.text.hint = 'yes') or ($project.text.hint = 'no')\">\n            <xsl:value-of select=\"$project.text.hint\" />\n        </xsl:when>\n        <!-- stick with no action by author/publisher -->\n        <xsl:when test=\"$project.hint = ''\">\n            <xsl:value-of select=\"$project.hint\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:FALLBACK: project.hint parameter should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$project.hint\" />\".  Proceeding with default value.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"entered-project-answer\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/common/exercise-project/@answer\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/common/exercise-project/@answer = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/common/exercise-project/@answer = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK:   the exercise component visibility setting (common/exercise-project/@answer in the publisher file) must be \"yes\" or \"no\", not \"<xsl:value-of select=\"$publication/common/exercise-project/@answer\"/>\".  Proceeding with the default, which is \"yes\".</xsl:message>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- deprecated, but still honored -->\n        <xsl:when test=\"($project.answer = 'yes') or\n                        ($project.answer = 'no')\">\n            <xsl:value-of select=\"$project.answer\" />\n        </xsl:when>\n        <!-- deprecated, but still honored, though with no error-checking, -->\n        <!-- erroneous values will fall into default of replacement switch -->\n        <xsl:when test=\"($project.text.answer = 'yes') or ($project.text.answer = 'no')\">\n            <xsl:value-of select=\"$project.text.answer\" />\n        </xsl:when>\n        <!-- stick with no action by author/publisher -->\n        <xsl:when test=\"$project.answer = ''\">\n            <xsl:value-of select=\"$project.answer\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:FALLBACK: project.answer parameter should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$project.answer\" />\".  Proceeding with default value.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"entered-project-solution\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/common/exercise-project/@solution\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/common/exercise-project/@solution = 'yes'\">\n                    <xsl:text>yes</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/common/exercise-project/@solution = 'no'\">\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK:   the exercise component visibility setting (common/exercise-project/@solution in the publisher file) must be \"yes\" or \"no\", not \"<xsl:value-of select=\"$publication/common/exercise-project/@solution\"/>\".  Proceeding with the default, which is \"yes\".</xsl:message>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- deprecated, but still honored -->\n        <xsl:when test=\"($project.solution = 'yes') or\n                        ($project.solution = 'no')\">\n            <xsl:value-of select=\"$project.solution\" />\n        </xsl:when>\n        <!-- deprecated, but still honored, though with no error-checking, -->\n        <!-- erroneous values will fall into default of replacement switch -->\n        <xsl:when test=\"($project.text.solution = 'yes') or ($project.text.solution = 'no')\">\n            <xsl:value-of select=\"$project.text.solution\" />\n        </xsl:when>\n        <!-- stick with no action by author/publisher -->\n        <xsl:when test=\"$project.solution = ''\">\n            <xsl:value-of select=\"$project.solution\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message >PTX:FALLBACK: project.solution parameter should be \"yes\" or \"no\", not \"<xsl:value-of select=\"$project.solution\" />\".  Proceeding with default value.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- The \"entered-*\" versions have been sanitized      -->\n<!-- to be \"yes\", \"no\" or \"\".  We make and use boolean -->\n<!-- switches. Unset, or mis-entered is the default,   -->\n<!-- which is to show all components until an author   -->\n<!-- decides to hide them.                             -->\n<!-- These are used in the solution manual conversion  -->\n<xsl:variable name=\"b-has-inline-statement\"\n              select=\"($entered-exercise-inline-statement = 'yes') or ($entered-exercise-inline-statement = '')\" />\n<xsl:variable name=\"b-has-inline-hint\"\n              select=\"($entered-exercise-inline-hint = 'yes') or ($entered-exercise-inline-hint = '')\" />\n<xsl:variable name=\"b-has-inline-answer\"\n              select=\"($entered-exercise-inline-answer = 'yes') or ($entered-exercise-inline-answer = '')\" />\n<xsl:variable name=\"b-has-inline-solution\"\n              select=\"($entered-exercise-inline-solution = 'yes') or ($entered-exercise-inline-solution = '')\" />\n<xsl:variable name=\"b-has-divisional-statement\"\n              select=\"($entered-exercise-divisional-statement = 'yes') or ($entered-exercise-divisional-statement = '')\" />\n<xsl:variable name=\"b-has-divisional-hint\"\n              select=\"($entered-exercise-divisional-hint = 'yes') or ($entered-exercise-divisional-hint = '')\" />\n<xsl:variable name=\"b-has-divisional-answer\"\n              select=\"($entered-exercise-divisional-answer = 'yes') or ($entered-exercise-divisional-answer = '')\" />\n<xsl:variable name=\"b-has-divisional-solution\"\n              select=\"($entered-exercise-divisional-solution = 'yes') or ($entered-exercise-divisional-solution = '')\" />\n<xsl:variable name=\"b-has-worksheet-statement\"\n              select=\"($entered-exercise-worksheet-statement = 'yes') or ($entered-exercise-worksheet-statement = '')\" />\n<xsl:variable name=\"b-has-worksheet-hint\"\n              select=\"($entered-exercise-worksheet-hint = 'yes') or ($entered-exercise-worksheet-hint = '')\" />\n<xsl:variable name=\"b-has-worksheet-answer\"\n              select=\"($entered-exercise-worksheet-answer = 'yes') or ($entered-exercise-worksheet-answer = '')\" />\n<xsl:variable name=\"b-has-worksheet-solution\"\n              select=\"($entered-exercise-worksheet-solution = 'yes') or ($entered-exercise-worksheet-solution = '')\" />\n<xsl:variable name=\"b-has-reading-statement\"\n              select=\"($entered-exercise-reading-statement = 'yes') or ($entered-exercise-reading-statement = '')\" />\n<xsl:variable name=\"b-has-reading-hint\"\n              select=\"($entered-exercise-reading-hint = 'yes') or ($entered-exercise-reading-hint = '')\" />\n<xsl:variable name=\"b-has-reading-answer\"\n              select=\"($entered-exercise-reading-answer = 'yes') or ($entered-exercise-reading-answer = '')\" />\n<xsl:variable name=\"b-has-reading-solution\"\n              select=\"($entered-exercise-reading-solution = 'yes') or ($entered-exercise-reading-solution = '')\" />\n<xsl:variable name=\"b-has-project-statement\"\n              select=\"($entered-project-statement = 'yes') or ($entered-project-statement = '')\" />\n<xsl:variable name=\"b-has-project-hint\"\n              select=\"($entered-project-hint = 'yes') or ($entered-project-hint = '')\" />\n<xsl:variable name=\"b-has-project-answer\"\n              select=\"($entered-project-answer = 'yes') or ($entered-project-answer = '')\" />\n<xsl:variable name=\"b-has-project-solution\"\n              select=\"($entered-project-solution = 'yes') or ($entered-project-solution = '')\" />\n\n\n<!-- ############## -->\n<!-- Source Options -->\n<!-- ############## -->\n\n<!-- A directory of images that *are not* generated, or reproducible,     -->\n<!-- from an author's source.  Canonical example would be a photograph.   -->\n<!-- The directory specified is always a relative path rooted at the      -->\n<!-- author's source file containing the \"pretext\" element (i.e. if       -->\n<!-- source is modularized, the \"master\" or \"top-level\" file).            -->\n<!-- Historically, authors were 100% responsible for this path, so the    -->\n<!-- default is empty.  With this publisher file specification, a         -->\n<!-- redundance in these paths (a common leading path) may be specified   -->\n<!-- once, and source can assume less about the location of these images. -->\n<!-- A leading slash is an error, since that'd be an absolute path,       -->\n<!-- while a trailing slash will be reliably added if                     -->\n<!--     (a) not present in publisher file specification                  -->\n<!--     (b) the path is not empty                                        -->\n<!-- The external directory is a property of the source (a different    -->\n<!-- directory of files is a different document), so its declaration    -->\n<!-- is \"directories/@external\" within \"docinfo\" (2026-07-30).  The     -->\n<!-- publication file \"source/directories/@external\" is deprecated but  -->\n<!-- honored while the \"docinfo\" is silent.  NB: the version tree is    -->\n<!-- consulted, since machinery within the assembly chain consumes      -->\n<!-- directory variables and the tree behind  $docinfo  does not exist  -->\n<!-- yet at that point (referencing it is a circular definition).       -->\n<xsl:variable name=\"external-directory-source\">\n    <!-- an empty declaration is an error, not an election -->\n    <xsl:if test=\"$version-docinfo/directories/@external = ''\">\n        <xsl:message terminate=\"yes\">PTX:FATAL:   the value of \"directories/@external\" within \"docinfo\" must be nonempty</xsl:message>\n    </xsl:if>\n    <xsl:if test=\"$publication/source/directories/@external = ''\">\n        <xsl:message terminate=\"yes\">PTX:FATAL:   the value of source/directories/@external in the publisher file must be nonempty</xsl:message>\n    </xsl:if>\n    <xsl:variable name=\"raw-input\">\n        <xsl:choose>\n            <xsl:when test=\"$version-docinfo/directories/@external\">\n                <xsl:if test=\"$publication/source/directories/@external\">\n                    <xsl:message>PTX:WARNING: the external directory is specified both within \"docinfo\" (\"directories/@external\") and in the publication file (\"source/directories/@external\").  The \"docinfo\" value is used; please remove the publication file entry.</xsl:message>\n                </xsl:if>\n                <xsl:value-of select=\"$version-docinfo/directories/@external\"/>\n            </xsl:when>\n            <xsl:when test=\"$publication/source/directories/@external\">\n                <xsl:message>PTX:DEPRECATE: (2026-07-30) the external directory is a property of your source, and is now declared with a \"directories/@external\" attribute within \"docinfo\".  The publication file entry \"source/directories/@external\" is honored meanwhile, but please relocate it.</xsl:message>\n                <xsl:value-of select=\"$publication/source/directories/@external\"/>\n            </xsl:when>\n            <xsl:otherwise/>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:choose>\n        <!-- leading path separator is an error -->\n        <xsl:when test=\"substring($raw-input, 1, 1) = '/'\">\n            <xsl:message>PTX:FALLBACK:   an external-image directory (\"directories/@external\", within \"docinfo\" or the publication file) must be a relative path and not begin with \"/\" as in \"<xsl:value-of select=\"$raw-input\"/>\".  Proceeding with the default, which is an empty string, and may lead to unexpected results.</xsl:message>\n            <xsl:text/>\n        </xsl:when>\n        <!-- trailing path separator is good and -->\n        <!-- we know it is not due to simply '/' -->\n        <xsl:when test=\"substring($raw-input, string-length($raw-input), 1) = '/'\">\n            <xsl:value-of select=\"$raw-input\"/>\n        </xsl:when>\n        <!-- if there is substance, we need to add a trailing slash -->\n        <xsl:when test=\"string-length($raw-input) > 0\">\n            <xsl:value-of select=\"concat($raw-input, '/')\"/>\n        </xsl:when>\n        <!-- specification must be empty, so we leave it that way -->\n        <xsl:otherwise/>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- The generated directory is machine-owned, so it is defaultable:  -->\n<!-- an undeclared location is the directory \"generated\", beside the  -->\n<!-- source.  (Historically an unmanaged scheme fell back to the      -->\n<!-- \"images\" directory; managed directories are now the only scheme.)-->\n<xsl:variable name=\"generated-directory-source\">\n    <xsl:if test=\"$publication/source/directories/@generated = ''\">\n        <xsl:message terminate=\"yes\">PTX:FATAL:   the value of source/directories/@generated in the publisher file must be nonempty</xsl:message>\n    </xsl:if>\n    <xsl:variable name=\"raw-input\">\n        <xsl:choose>\n            <xsl:when test=\"$publication/source/directories/@generated\">\n                <xsl:value-of select=\"$publication/source/directories/@generated\"/>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>generated</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"substring($raw-input, 1, 1) = '/'\">\n            <xsl:message>PTX:FALLBACK:   a generated-image directory (source/directories/@generated in the publisher file) must be a relative path and not begin with \"/\" as in \"<xsl:value-of select=\"$raw-input\"/>\".  Proceeding with the default, which is an empty string, and may lead to unexpected results.</xsl:message>\n            <xsl:text/>\n        </xsl:when>\n        <!-- trailing path separator is good -->\n        <xsl:when test=\"substring($raw-input, string-length($raw-input), 1) = '/'\">\n            <xsl:value-of select=\"$raw-input\"/>\n        </xsl:when>\n        <!-- add the trailing slash -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"concat($raw-input, '/')\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- Managed directories are the only scheme (2026-08-02).  The two  -->\n<!-- directions are independent facts: an undeclared external means  -->\n<!-- the project has no external assets, and the machine-owned       -->\n<!-- generated directory is defaultable.                             -->\n\n\n<!-- The destination directories within any output are hard-coded -->\n<!-- here, and used in the various conversions.                   -->\n<xsl:variable name=\"external-directory\" select=\"'external/'\"/>\n<xsl:variable name=\"generated-directory\" select=\"'generated/'\"/>\n\n\n<!-- This is a directory that may need to be copied to a      -->\n<!-- scratch location in anticipation of data files necessary -->\n<!-- for compilation of images, such as pie charts or plots   -->\n<!-- The data directory runs with the source, declared as     -->\n<!-- \"directories/@data\" within \"docinfo\" (the version tree,  -->\n<!-- for the same reason as the external directory above).    -->\n<!-- An earlier form of this variable consulted a publication -->\n<!-- file \"source/directories/@data\" which was never in the   -->\n<!-- publication schema, and hard-coded the value \"data\".     -->\n<xsl:variable name=\"data-directory\">\n    <xsl:variable name=\"raw-input\">\n        <xsl:value-of select=\"$version-docinfo/directories/@data\"/>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"substring($raw-input, 1, 1) = '/'\">\n            <xsl:message>PTX:FALLBACK:   a data directory (\"directories/@data\" within \"docinfo\") must be a relative path and not begin with \"/\" as in \"<xsl:value-of select=\"$raw-input\"/>\".  Proceeding with the default, which is an empty string, and may lead to unexpected results.</xsl:message>\n            <xsl:text/>\n        </xsl:when>\n        <!-- trailing path separator is good -->\n        <xsl:when test=\"substring($raw-input, string-length($raw-input), 1) = '/'\">\n            <xsl:value-of select=\"$raw-input\"/>\n        </xsl:when>\n        <!-- if there is substance, we need to add a trailing slash -->\n        <xsl:when test=\"string-length($raw-input) > 0\">\n            <xsl:value-of select=\"concat($raw-input, '/')\"/>\n        </xsl:when>\n        <!-- specification must be empty, so we leave it that way -->\n        <xsl:otherwise/>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- ###################### -->\n<!-- Filenames for Assembly -->\n<!-- ###################### -->\n\n<!-- These are auxiliary files provided by authors and publishers, -->\n<!-- generally for derived versions of a project.  Their use can   -->\n<!-- be found in the  pretext-assembly.xsl  file.                  -->\n<!--                                                               -->\n<!-- NB  Generally these files are given as relative paths to a    -->\n<!-- project's source file and the  document()  function will      -->\n<!-- locate them as such.  So absolute paths gaining \"extra\"       -->\n<!-- directories with spaces is not as much of a concern as with   -->\n<!-- the publisher file (see above).  But an author or publisher   -->\n<!-- can still place these files' names into an attribute of the   -->\n<!-- publisher file using a space.  This will cause the            -->\n<!-- document()  function to fail silently. The location provided  -->\n<!-- in the first argument of document() is a URI, so the proper   -->\n<!-- escape mechanism is percent-encoding.                         -->\n\n\n<!-- A file of hint|answer|solution, with @ref back to \"exercise\" -->\n<!-- so that the solutions can see limited distribution.  No real -->\n<!-- error-checking.  If not set/present, then an empty string.   -->\n<!-- NB: the empty string is checked in pretext-assembly.xsl to   -->\n<!-- prevent unnecessary manipulations of \"exercise\" and \"task\"   -->\n<!-- when no file is indicated.                                   -->\n\n<xsl:variable name=\"private-solutions-file\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/source/@private-solutions\">\n            <xsl:value-of select=\"str:replace($publication/source/@private-solutions, '&#x20;', '%20')\"/>\n        </xsl:when>\n        <!-- sentinel for no private solution manipulation -->\n        <xsl:otherwise/>\n    </xsl:choose>\n</xsl:variable>\n<xsl:variable name=\"b-private-solutions\" select=\"not($private-solutions-file = '')\"/>\n\n\n<!-- ############### -->\n<!-- STACK Options -->\n<!-- ############### -->\n\n<!-- STACK server location -->\n<xsl:variable name=\"stack-server\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/stack/pi:pub-attribute[@name='server']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- ############### -->\n<!-- WeBWorK Options -->\n<!-- ############### -->\n\n<!-- How to process PG for static output -->\n<xsl:variable name=\"webwork-static-processing\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/webwork/pi:pub-attribute[@name='static-processing']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- Location of PG library for local static processing -->\n<xsl:variable name=\"webwork-pg-location\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/webwork/pi:pub-attribute[@name='pg-location']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- WeBWorK server location and credentials for the daemon course -->\n<xsl:variable name=\"webwork-server\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/webwork/pi:pub-attribute[@name='server']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"webwork-course\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/webwork/pi:pub-attribute[@name='course']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"webwork-user\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/webwork/pi:pub-attribute[@name='user']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"webwork-password\">\n    <xsl:choose>\n        <!-- For backwards compatibility -->\n        <xsl:when test=\"$publication/webwork/@coursepassword\">\n            <xsl:value-of select=\"$publication/webwork/@coursepassword\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\"$publisher-attribute-options/webwork/pi:pub-attribute[@name='password']\" mode=\"set-pubfile-variable\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- WeBWorK tasks can be revealed incrementally or all at once -->\n<xsl:variable name=\"webwork-task-reveal\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/webwork/pi:pub-attribute[@name='task-reveal']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n\n<!-- WeBWorK problem representations are formed by Python routines  -->\n<!-- in the   pretext.py  module that communicates with a WeBWorK   -->\n<!-- server.  One file per exercise is written into this directory, -->\n<!-- named by the exercise's @pi:assembly-id.  This variable is only-->\n<!-- relevant for consumption of WW representations into output.    -->\n<!-- Keep this variable silent since it may not be necessary.       -->\n<xsl:variable name=\"webwork-representations-dir\">\n    <!-- Only relevant if there are WW problems present. A version    -->\n    <!-- might remove all WW problems but there is no harm in this    -->\n    <!-- variable since it will not be used, and it is silent.        -->\n    <xsl:if test=\"$original//webwork[node() or @*]\">\n        <xsl:choose>\n            <!-- the deprecated location is honored only when no -->\n            <!-- generated directory is declared                 -->\n            <xsl:when test=\"$publication/source/@webwork-problems and not($publication/source/directories/@generated)\">\n                <xsl:value-of select=\"str:replace($publication/source/@webwork-problems, '&#x20;', '%20')\"/>\n                <xsl:message>PTX:DEPRECATE: the publication file entry  source/@webwork-problems  is</xsl:message>\n                <xsl:message>               deprecated, please move to using managed directories</xsl:message>\n            </xsl:when>\n            <!-- the generated directory, declared or defaulted -->\n            <xsl:otherwise>\n                <xsl:value-of select=\"str:replace(concat($generated-directory-source, 'webwork/'), '&#x20;', '%20')\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:if>\n</xsl:variable>\n\n<!-- Dynamic problem substitutions are formed by Python routines    -->\n<!-- in the   pretext.py  module that opens HTML representations    -->\n<!-- on a local http.server process. The summary of all             -->\n<!-- are recorded in the dynamic-substitutions-file.                -->\n<xsl:variable name=\"dynamic-substitutions-file\">\n    <!-- Only relevant if there are dynamic exercises present.      -->\n    <xsl:if test=\"$original//exercise//setup\">\n        <!-- the generated directory, declared or defaulted -->\n        <xsl:value-of select=\"str:replace(concat($generated-directory-source, 'dynamic_subs/dynamic_substitutions.xml'), '&#x20;', '%20')\"/>\n    </xsl:if>\n</xsl:variable>\n\n<!-- A dynamic exercise may pull in a Javascript library that is not   -->\n<!-- part of the project, via  setup/jsimports/jslibrary/@url .  In    -->\n<!-- HTML that code runs in the reader's browser, sandboxed as any     -->\n<!-- other page script.  But a *static* build (LaTeX, PDF, EPUB) must  -->\n<!-- execute the same library under Node, on the machine doing the     -->\n<!-- build, with no sandbox at all.  So a static build refuses to run  -->\n<!-- a remote library unless the publisher has named it here:          -->\n<!--                                                                   -->\n<!--   <dynamics>                                                      -->\n<!--       <remote-libraries>                                          -->\n<!--           <library url=\"https://example.org/matrix.mjs\"/>         -->\n<!--       </remote-libraries>                                         -->\n<!--   </dynamics>                                                     -->\n<!--                                                                   -->\n<!-- This is deliberately a per-URL list and not a blanket switch, so  -->\n<!-- that approval granted today cannot silently extend to a library   -->\n<!-- some exercise starts importing tomorrow.  HTML builds are not     -->\n<!-- gated, since the risk being managed is Node running unvetted      -->\n<!-- code as the author, which is strictly greater than the in-browser -->\n<!-- case.  The list is consumed by  extract-dynamic.xsl , which       -->\n<!-- passes it to the substitution script.                             -->\n<xsl:variable name=\"remote-library-allowlist\" select=\"$publication/dynamics/remote-libraries/library\"/>\n\n<!-- File of  custom/@name  elements, whose content is a custom -->\n<!-- replacement for a corresponding  custom/@ref  element in   -->\n<!-- the source.                                                -->\n<xsl:variable name=\"customizations-file\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/source/@customizations\">\n            <xsl:value-of select=\"str:replace($publication/source/@customizations, '&#x20;', '%20')\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- ################## -->\n<!-- Version Components -->\n<!-- ################## -->\n\n\n<!-- A version may be specified as a list of components.  We \"fence\" -->\n<!-- the list so as to make matching a single component in the list  -->\n<!-- more reliable (don't match substrings).  A totally empty string -->\n<!-- means it has not been set, while  @include=\"\"  yields \"||\".     -->\n<xsl:variable name=\"components-fenced\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/source/version/@include\">\n            <xsl:value-of select=\"concat('|', translate(normalize-space($publication/source/version/@include), ' ', '|'), '|')\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n\n<!-- ######### -->\n<!-- Numbering -->\n<!-- ######### -->\n\n<!-- NB: the \"$assembly-*\" trees are a bit dangerous, being formed  -->\n<!-- partway through the pre-processing phase.  Their purpose, when -->\n<!-- used to query the structure of the document was to be certain  -->\n<!-- that the pre-processing was done building versions, and/or     -->\n<!-- done adding/deleting material.  We want to build numbers as    -->\n<!-- part of pre-processing, and various defaults are a function    -->\n<!-- of structure, hence the intermediate trees. (We are being very -->\n<!-- cautious here, likely the $original trees would suffice for    -->\n<!-- determining gross sructure.                                    -->\n\n<!-- User-supplied Numbering for Maximum Level     -->\n<!-- Respect switch, or provide sensible defaults  -->\n<!-- NB: level number counts the number of         -->\n<!-- separators (periods) present once qualified   -->\n<!-- with a numbered item contained within         -->\n<!-- NB: If we were to allow multiple (hence       -->\n<!-- numbered) specialized divisions of a          -->\n<!-- \"subsubsection\", then the non-zero maximums   -->\n<!-- below would go up by 1                        -->\n<!--   article/section: s.ss.sss => 3              -->\n<!--   book:            c.s.ss.sss => 4            -->\n<!--   book/part:       p.c.s.ss.sss => 5          -->\n<xsl:variable name=\"numbering-maxlevel-entered\">\n    <!-- these are the maximum possible for a given document type -->\n    <!-- the default, and also an error-check upper-limit         -->\n    <xsl:variable name=\"max-feasible\">\n        <xsl:choose>\n            <xsl:when test=\"$version-has-parts\">5</xsl:when>\n            <xsl:when test=\"$version-doc-type = 'book'\">4</xsl:when>\n            <xsl:when test=\"$version-article-sections or $version-article-printouts\">3</xsl:when>\n            <xsl:when test=\"$version-doc-type = 'article'\">0</xsl:when>\n            <xsl:when test=\"$version-doc-type = 'letter'\">0</xsl:when>\n            <xsl:when test=\"$version-doc-type = 'slideshow'\">0</xsl:when>\n            <xsl:when test=\"$version-doc-type = 'memo'\">0</xsl:when>\n            <xsl:otherwise>\n                <xsl:message>PTX:BUG: a document type needs a maximum division level defined</xsl:message>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"candidate-maxlevel\">\n        <xsl:choose>\n            <!-- go with publisher file, check for numerical value -->\n            <xsl:when test=\"$publication/numbering/divisions/@level\">\n                <xsl:variable name=\"the-number\" select=\"$publication/numbering/divisions/@level\"/>\n                <xsl:choose>\n                    <!-- NaN does not equal *anything*, so tests if a number -->\n                    <xsl:when test=\"not(number($the-number) = number($the-number)) or ($the-number &lt; 0)\">\n                        <xsl:message>PTX:FALLBACK:   numbering level for divisions given in the publisher file (\"<xsl:value-of select=\"$the-number\"/>\") is not a number or is negative.  The default value will be used instead</xsl:message>\n                        <xsl:value-of select=\"$max-feasible\"/>\n                        </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:value-of select=\"$publication/numbering/divisions/@level\"/>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:when>\n            <!-- respect deprecated analog -->\n            <xsl:when test=\"not($numbering.maximum.level = '')\">\n                <xsl:value-of select=\"$numbering.maximum.level\" />\n            </xsl:when>\n            <!-- various defaults are the maximum possible -->\n            <xsl:otherwise>\n                <xsl:value-of select=\"$max-feasible\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- check $candidate against upper bound, $max-feasible -->\n    <xsl:choose>\n        <xsl:when test=\"$candidate-maxlevel > $max-feasible\">\n            <xsl:message>PTX:FALLBACK:   numbering level set for divisions (\"<xsl:value-of select=\"$candidate-maxlevel\"/>\") is greater than the maximum possible (\"<xsl:value-of select=\"$max-feasible\"/>\") for this document type.  The default value will be used instead</xsl:message>\n            <xsl:value-of select=\"$max-feasible\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"$candidate-maxlevel\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n<xsl:variable name=\"numbering-maxlevel\" select=\"number($numbering-maxlevel-entered)\"/>\n\n<!-- TODO: next five variables have wildly similar structure,  -->\n<!-- and could best be created/defined with a single template, -->\n<!-- parameterized by (a) publisher file entry, (b) old        -->\n<!-- deprecated stringparam (or docinfo coming soon),          -->\n<!-- (c) string for messages (e.g. \"footnotes\").               -->\n<!-- The numbered-object families (blocks, projects, equations,   -->\n<!-- footnotes, figures, inline exercises, open problems) share   -->\n<!-- one default numbering level: set by the document type, and   -->\n<!-- never more than the division depth the publisher elected     -->\n<!-- ($numbering-maxlevel), so an unconfigured document always    -->\n<!-- has a conforming value.                                      -->\n<xsl:variable name=\"default-numbering-level\">\n    <xsl:variable name=\"document-type-level\">\n        <xsl:choose>\n            <xsl:when test=\"$version-has-parts\">3</xsl:when>\n            <xsl:when test=\"$version-doc-type = 'book'\">2</xsl:when>\n            <xsl:when test=\"$version-article-sections or $version-article-printouts\">1</xsl:when>\n            <xsl:when test=\"$version-doc-type = 'article'\">0</xsl:when>\n            <xsl:when test=\"$version-doc-type = 'slideshow'\">0</xsl:when>\n            <xsl:when test=\"$version-doc-type = 'letter'\">0</xsl:when>\n            <xsl:when test=\"$version-doc-type = 'memo'\">0</xsl:when>\n            <xsl:otherwise>\n                <xsl:message>PTX:BUG: a document type needs a default numbering level defined</xsl:message>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$document-type-level > $numbering-maxlevel\">\n            <xsl:value-of select=\"$numbering-maxlevel\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"$document-type-level\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- Resolve one family's numbering level: the publisher file's  -->\n<!-- entry, else a legacy analog (a string parameter, or in some -->\n<!-- cases a \"docinfo\" attribute), else the shared default.  An  -->\n<!-- authored value must be numeric, non-negative, and no more   -->\n<!-- than $numbering-maxlevel; the default conforms by           -->\n<!-- construction, so only an authored value can provoke a       -->\n<!-- message.                                                    -->\n<xsl:template name=\"numbering-level\">\n    <xsl:param name=\"family\"/>\n    <xsl:param name=\"entered\"/>\n    <xsl:param name=\"legacy\" select=\"''\"/>\n    <xsl:variable name=\"candidate\">\n        <xsl:choose>\n            <!-- go with publisher file, check for numerical value -->\n            <xsl:when test=\"$entered\">\n                <xsl:choose>\n                    <!-- NaN does not equal *anything*, so tests if a number -->\n                    <xsl:when test=\"not(number($entered) = number($entered)) or ($entered &lt; 0)\">\n                        <xsl:message>PTX:FALLBACK:   numbering level for <xsl:value-of select=\"$family\"/> given in the publisher file (\"<xsl:value-of select=\"$entered\"/>\") is not a number or is negative.  The default value (\"<xsl:value-of select=\"$default-numbering-level\"/>\") will be used instead</xsl:message>\n                        <xsl:value-of select=\"$default-numbering-level\"/>\n                    </xsl:when>\n                    <xsl:otherwise>\n                        <xsl:value-of select=\"$entered\"/>\n                    </xsl:otherwise>\n                </xsl:choose>\n            </xsl:when>\n            <!-- respect a legacy analog -->\n            <xsl:when test=\"$legacy != ''\">\n                <xsl:value-of select=\"$legacy\"/>\n            </xsl:when>\n            <!-- use the conforming default, no message possible -->\n            <xsl:otherwise>\n                <xsl:value-of select=\"$default-numbering-level\"/>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <!-- an authored candidate may exceed the upper bound, $numbering-maxlevel -->\n    <xsl:choose>\n        <xsl:when test=\"$candidate > $numbering-maxlevel\">\n            <xsl:message>PTX:FALLBACK:   numbering level set for <xsl:value-of select=\"$family\"/> (\"<xsl:value-of select=\"$candidate\"/>\") is greater than the maximum possible levels (\"<xsl:value-of select=\"$numbering-maxlevel\"/>\") configured.  The default value (\"<xsl:value-of select=\"$default-numbering-level\"/>\") will be used instead</xsl:message>\n            <xsl:value-of select=\"$default-numbering-level\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"$candidate\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<xsl:variable name=\"numbering-blocks-entered\">\n    <xsl:call-template name=\"numbering-level\">\n        <xsl:with-param name=\"family\" select=\"'blocks'\"/>\n        <xsl:with-param name=\"entered\" select=\"$publication/numbering/blocks/@level\"/>\n        <xsl:with-param name=\"legacy\" select=\"$numbering.theorems.level\"/>\n    </xsl:call-template>\n</xsl:variable>\n<xsl:variable name=\"numbering-blocks\" select=\"number($numbering-blocks-entered)\"/>\n\n<xsl:variable name=\"numbering-projects-entered\">\n    <xsl:call-template name=\"numbering-level\">\n        <xsl:with-param name=\"family\" select=\"'projects'\"/>\n        <xsl:with-param name=\"entered\" select=\"$publication/numbering/projects/@level\"/>\n        <xsl:with-param name=\"legacy\" select=\"$numbering.projects.level\"/>\n    </xsl:call-template>\n</xsl:variable>\n<xsl:variable name=\"numbering-projects\" select=\"number($numbering-projects-entered)\"/>\n\n<xsl:variable name=\"numbering-equations-entered\">\n    <xsl:call-template name=\"numbering-level\">\n        <xsl:with-param name=\"family\" select=\"'equations'\"/>\n        <xsl:with-param name=\"entered\" select=\"$publication/numbering/equations/@level\"/>\n        <xsl:with-param name=\"legacy\" select=\"$numbering.equations.level\"/>\n    </xsl:call-template>\n</xsl:variable>\n<xsl:variable name=\"numbering-equations\" select=\"number($numbering-equations-entered)\"/>\n\n<xsl:variable name=\"numbering-footnotes-entered\">\n    <xsl:call-template name=\"numbering-level\">\n        <xsl:with-param name=\"family\" select=\"'footnotes'\"/>\n        <xsl:with-param name=\"entered\" select=\"$publication/numbering/footnotes/@level\"/>\n        <xsl:with-param name=\"legacy\" select=\"$numbering.footnotes.level\"/>\n    </xsl:call-template>\n</xsl:variable>\n<xsl:variable name=\"numbering-footnotes\" select=\"number($numbering-footnotes-entered)\"/>\n\n<xsl:variable name=\"numbering-figures-entered\">\n    <xsl:call-template name=\"numbering-level\">\n        <xsl:with-param name=\"family\" select=\"'figures'\"/>\n        <xsl:with-param name=\"entered\" select=\"$publication/numbering/figures/@level\"/>\n    </xsl:call-template>\n</xsl:variable>\n<xsl:variable name=\"numbering-figures\" select=\"number($numbering-figures-entered)\"/>\n\n<xsl:variable name=\"numbering-exercises-entered\">\n    <xsl:call-template name=\"numbering-level\">\n        <xsl:with-param name=\"family\" select=\"'inline exercises'\"/>\n        <xsl:with-param name=\"entered\" select=\"$publication/numbering/exercises/@level\"/>\n    </xsl:call-template>\n</xsl:variable>\n<xsl:variable name=\"numbering-exercises\" select=\"number($numbering-exercises-entered)\"/>\n\n<xsl:variable name=\"numbering-openproblems-entered\">\n    <xsl:call-template name=\"numbering-level\">\n        <xsl:with-param name=\"family\" select=\"'open problems'\"/>\n        <xsl:with-param name=\"entered\" select=\"$publication/numbering/openproblems/@level\"/>\n    </xsl:call-template>\n</xsl:variable>\n<xsl:variable name=\"numbering-openproblems\" select=\"number($numbering-openproblems-entered)\"/>\n\n<!-- A block group may run on its own counter, elected by the      -->\n<!-- publisher switch.  The deprecated \"docinfo\" analogs for       -->\n<!-- figures and inline exercises, and the deprecated              -->\n<!-- debug.project.number parameter, are ignored; warnings live    -->\n<!-- with the other deprecations.                                  -->\n<xsl:variable name=\"b-number-figure-distinct\"      select=\"$publication/numbering/figures/@distinct = 'yes'\"/>\n<xsl:variable name=\"b-number-project-distinct\"     select=\"$publication/numbering/projects/@distinct = 'yes'\"/>\n<xsl:variable name=\"b-number-exercise-distinct\"    select=\"$publication/numbering/exercises/@distinct = 'yes'\"/>\n<xsl:variable name=\"b-number-openproblem-distinct\" select=\"$publication/numbering/openproblems/@distinct = 'yes'\"/>\n\n<xsl:variable name=\"chapter-start-entered\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/numbering/divisions/@chapter-start\">\n            <xsl:variable name=\"the-number\" select=\"$publication/numbering/divisions/@chapter-start\"/>\n            <xsl:choose>\n                <!-- NaN does not equal *anything*, so tests if a number -->\n                <xsl:when test=\"not(number($the-number) = number($the-number)) or ($the-number &lt; 0)\">\n                    <xsl:message>PTX:FALLBACK:   starting number for chapters given in the publisher file (\"<xsl:value-of select=\"$the-number\"/>\") is not a number or is negative.  The default value will be used instead</xsl:message>\n                    <xsl:value-of select=\"1\"/>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:value-of select=\"$publication/numbering/divisions/@chapter-start\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- default if not specified -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"1\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n<xsl:variable name=\"chapter-start\" select=\"number($chapter-start-entered)\"/>\n\n<!-- Status quo, for no-part books and articles is \"absent\".     -->\n<!-- The \"structural\" option will change numbers and numbering   -->\n<!-- substantially.  The \"decorative\" option is the default for  -->\n<!-- books with parts, and it looks just like the LaTeX default. -->\n<xsl:variable name=\"parts\">\n    <xsl:choose>\n        <!-- no parts, just record as absent,  -->\n        <!-- but warn of ill-advised attempts  -->\n        <xsl:when test=\"not($version-has-parts)\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/numbering/divisions/@part-structure\">\n                    <xsl:message>PTX:FALLBACK: your document is not a book with parts, so the publisher file  numbering/divisions/@part-structure  entry is being ignored</xsl:message>\n                </xsl:when>\n            </xsl:choose>\n            <!-- flag this situation -->\n            <xsl:text>absent</xsl:text>\n        </xsl:when>\n        <!-- now we have parts to deal with -->\n        <!-- first via publisher file       -->\n        <xsl:when test=\"$publication/numbering/divisions/@part-structure\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/numbering/divisions/@part-structure = 'structural'\">\n                    <xsl:text>structural</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"$publication/numbering/divisions/@part-structure = 'decorative'\">\n                    <xsl:text>decorative</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK: the publisher file  numbering/divisions/@part-structure  entry should be \"decorative\" or \"structural\", not \"<xsl:value-of select=\"$publication/numbering/divisions/@part-structure\" />\".  The default will be used instead.</xsl:message>\n                    <xsl:text>decorative</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- no specification, use default; the deprecated         -->\n        <!-- docinfo/numbering/division/@part is ignored (warnings -->\n        <!-- live with the other deprecations)                     -->\n        <xsl:otherwise>\n            <xsl:text>decorative</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- ##################### -->\n<!-- HTML-Specific Options -->\n<!-- ##################### -->\n\n<!-- Various components need to be built with pixel widths from % based widths -->\n<!-- design-width serves as the value that percent is based on                 -->\n<xsl:variable name=\"html-design-width\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/html[@design-width != '']\">\n            <xsl:apply-templates select=\"$publisher-attribute-options/html/pi:pub-attribute[@name='design-width']\" mode=\"set-pubfile-variable\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"'600'\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- Calculator -->\n<!-- Possible values are geogebra-classic, geogebra-graphing -->\n<!-- geogebra-geometry, geogebra-3d                          -->\n<!-- Default is empty, meaning the calculator is not wanted. -->\n<xsl:variable name=\"html-calculator\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/calculator/pi:pub-attribute[@name='model']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"b-has-calculator\" select=\"not($html-calculator = 'none')\" />\n\n<!-- Third-party annotation of the HTML output.  Default is \"none\".  -->\n<!-- Only \"hypothesis\" (Hypothes.is) is supported at present.        -->\n<xsl:variable name=\"html-annotation\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/annotation/pi:pub-attribute[@name='platform']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"b-activate-hypothesis\" select=\"$html-annotation = 'hypothesis'\" />\n\n<!-- Scratch ActiveCode Window -->\n<!-- Pop-up a window for testing program code.  So \"calculator-like\" but we      -->\n<!-- reserve the word \"calculator\" for the hand-held type (even if more modern). -->\n<xsl:variable name=\"html-scratch-activecode-language\">\n    <!-- Builds for a Runestone server default to having this   -->\n    <!-- available via a button, and a \"generic\" build defaults -->\n    <!-- to not having a button (or teh feature in any event).  -->\n    <xsl:variable name=\"activecode-default\">\n        <xsl:choose>\n            <xsl:when test=\"$b-host-runestone\">\n                <xsl:text>python</xsl:text>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>none</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:variable>\n    <xsl:variable name=\"entered-lang\" select=\"$publication/html/calculator/@activecode\"/>\n    <xsl:choose>\n        <!-- languages *always* supported, including \"none\" -->\n        <xsl:when test=\"($entered-lang = 'none') or\n                        ($entered-lang = 'python') or\n                        ($entered-lang = 'gdscript') or\n                        ($entered-lang = 'javascript') or\n                        ($entered-lang = 'html') or\n                        ($entered-lang = 'sql')\">\n            <!-- HTML has odd identifier, due to CodeMirror API, we  -->\n            <!-- use a simple one for our authors and translate here -->\n            <xsl:choose>\n                <xsl:when test=\"$entered-lang = 'html'\">\n                    <xsl:text>htmlmixed</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:value-of select=\"$entered-lang\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- languages only available on a Runestone server -->\n        <xsl:when test=\"($entered-lang = 'c') or\n                        ($entered-lang = 'cpp') or\n                        ($entered-lang = 'java') or\n                        ($entered-lang = 'kotlin') or\n                        ($entered-lang = 'python3') or\n                        ($entered-lang = 'octave')\">\n            <xsl:choose>\n                <!-- good when hosting on a server -->\n                <xsl:when test=\"$b-host-runestone\">\n                    <xsl:value-of select=\"$entered-lang\"/>\n                </xsl:when>\n                <!-- sounds good, but no, not the right build -->\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK: HTML calculator/@activecode in publisher file requests \"<xsl:value-of select=\"$entered-lang\"/>\", but this language is not supported unless the publisher file also indicates the build is meant to be hosted on a Runestone server. Proceeding with the default value for current build: \"<xsl:value-of select=\"$activecode-default\"/>\"</xsl:message>\n                    <xsl:value-of select=\"$activecode-default\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- an attempt was made, but failed to be any sort of language -->\n        <xsl:when test=\"$publication/html/calculator/@activecode\">\n            <xsl:message>PTX:FALLBACK: HTML calculator/@activecode in publisher file should be a programming language or \"none\", not \"<xsl:value-of select=\"$publication/html/calculator/@activecode\"/>\". Proceeding with the default value for current build: \"<xsl:value-of select=\"$activecode-default\"/>\"</xsl:message>\n            <xsl:value-of select=\"$activecode-default\"/>\n        </xsl:when>\n        <!-- no attempt to specify build-dependent default value -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$activecode-default\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"b-has-scratch-activecode\" select=\"not($html-scratch-activecode-language = 'none')\"/>\n\n<!--                                      -->\n<!-- HTML Reading Question Response Boxes -->\n<!--                                      -->\n\n<xsl:variable name=\"short-answer-responses\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/pi:pub-attribute[@name='short-answer-responses']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!--                          -->\n<!-- HTML Index Page Redirect -->\n<!--                          -->\n\n<!-- A generic \"index.html\" page will be built to redirect to an        -->\n<!-- existing page from the HTML build/chunking.  Here we simply        -->\n<!-- record the @xml:id present in the publication file and error-check -->\n<!-- the ref.  The processing and decisions about defaults, etc. are    -->\n<!-- delegated to the HTML conversion since it relies on chunk level    -->\n<!-- and associated routines (which may not be available in some other  -->\n<!-- conversion which imports this stylesheet).                         -->\n\n<xsl:variable name=\"html-index-page-entered-ref\">\n    <!-- needs to be realized as a *string*, not a node -->\n    <xsl:variable name=\"entered-ref\" select=\"string($publication/html/index-page/@ref)\"/>\n    <xsl:choose>\n        <!-- signal no choice with empty string-->\n        <xsl:when test=\"$entered-ref = ''\">\n            <xsl:text/>\n        </xsl:when>\n        <!-- bad choice, set to empty string -->\n        <xsl:when test=\"not(id($entered-ref))\">\n            <xsl:message>PTX:FALLBACK:   the requested HTML index page cannot be constructed since \"<xsl:value-of select=\"$entered-ref\"/>\" is not an @xml:id anywhere in the document.  Defaults will be used instead</xsl:message>\n            <xsl:text/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"$entered-ref\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!--                      -->\n<!-- HTML Feedback Button -->\n<!--                      -->\n\n<xsl:variable name=\"feedback-button-href\">\n    <!-- internal variable, just for error-checking -->\n    <xsl:variable name=\"attempted-href\">\n        <xsl:if test=\"$publication/html/feedback/@href\">\n            <xsl:value-of select=\"$publication/html/feedback/@href\"/>\n        </xsl:if>\n        <!-- default to empty, as a signal of failure -->\n    </xsl:variable>\n    <!-- we error-check a bad @href *only* as a publisher -->\n    <!-- variable, and not in the deprecated situation    -->\n    <xsl:if test=\"$publication/html/feedback and ($attempted-href = '')\">\n        <xsl:message>PTX:ERROR:  an HTML \"feedback\" button with an empty, or missing, @href will be ineffective, or worse, non-existent</xsl:message>\n    </xsl:if>\n    <!-- now capture the internal variable -->\n    <xsl:value-of select=\"$attempted-href\"/>\n</xsl:variable>\n\n<!-- Pure text, no markup, no math, etc. -->\n<!-- Empty is a meaningful value         -->\n<xsl:variable name=\"feedback-button-text\">\n    <xsl:variable name=\"provided-button-text\">\n        <xsl:if test=\"$publication/html/feedback\">\n            <xsl:value-of select=\"$publication/html/feedback\"/>\n        </xsl:if>\n    </xsl:variable>\n    <!-- Clean-up *and* utilize emptieness as a signal to use -->\n    <!-- default text. If empty, provide default text in      -->\n    <!-- language of the page at implementation time          -->\n    <xsl:value-of select=\"normalize-space($provided-button-text)\"/>\n</xsl:variable>\n\n<!-- Since we capture alternate text easily, and   -->\n<!-- we *need* an @href, we use this as the signal -->\n<!-- for the election of a feedback button         -->\n<xsl:variable name=\"b-has-feedback-button\" select=\"not($feedback-button-href = '')\"/>\n\n<!--                       -->\n<!-- HTML WeBWorK Dynamism -->\n<!--                       -->\n\n<!-- In HTML output a WeBWorK problem may be static or dynamic.  This  -->\n<!-- is a dichotomy, so we make (historical) boolean variables, where  -->\n<!-- static = True, which get used in the HTML conversion.  But as a   -->\n<!-- publisher setting, we have allowed for possibilities beyond just  -->\n<!-- two.  Inline and project-like default to \"dynamic\" since they may -->\n<!-- be formative, while the others are \"static\" since they may be     -->\n<!-- summative.                                                        -->\n\n<xsl:variable name=\"webwork-inline-capability\">\n    <xsl:variable name=\"ww-default\" select=\"'dynamic'\"/>\n    <xsl:choose>\n        <xsl:when test=\"$publication/html/webwork/@inline = 'dynamic'\">\n            <xsl:text>dynamic</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$publication/html/webwork/@inline = 'static'\">\n            <xsl:text>static</xsl:text>\n        </xsl:when>\n        <!-- attempted to set, but wrong -->\n        <xsl:when test=\"$publication/html/webwork/@inline\">\n            <xsl:message>PTX:FALLBACK: HTML WeBWorK @inline setting in publisher file should be \"static\" or \"dynamic\", not \"<xsl:value-of select=\"$publication/html/webwork/@inline\"/>\". Proceeding with default value: \"<xsl:value-of select=\"$ww-default\"/>\"</xsl:message>\n            <xsl:value-of select=\"$ww-default\"/>\n        </xsl:when>\n        <!-- backwards compatibility: 'yes' indicated static,     -->\n        <!-- anything else would be interpreted as if it was 'no' -->\n        <xsl:when test=\"$webwork.inline.static = 'yes'\">\n            <xsl:text>static</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$webwork.inline.static != ''\">\n            <xsl:text>dynamic</xsl:text>\n        </xsl:when>\n        <!-- no effort to set this switch, so use default -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$ww-default\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n<!-- the variable is now either 'static' or 'dynamic' -->\n<xsl:variable name=\"b-webwork-inline-static\" select=\"$webwork-inline-capability = 'static'\" />\n\n<xsl:variable name=\"webwork-divisional-capability\">\n    <xsl:variable name=\"ww-default\" select=\"'static'\"/>\n    <xsl:choose>\n        <xsl:when test=\"$publication/html/webwork/@divisional = 'dynamic'\">\n            <xsl:text>dynamic</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$publication/html/webwork/@divisional = 'static'\">\n            <xsl:text>static</xsl:text>\n        </xsl:when>\n        <!-- attempted to set, but wrong -->\n        <xsl:when test=\"$publication/html/webwork/@divisional\">\n            <xsl:message>PTX:FALLBACK: HTML WeBWorK @divisional setting in publisher file should be \"static\" or \"dynamic\", not \"<xsl:value-of select=\"$publication/html/webwork/@divisional\"/>\". Proceeding with default value: \"<xsl:value-of select=\"$ww-default\"/>\"</xsl:message>\n            <xsl:value-of select=\"$ww-default\"/>\n        </xsl:when>\n        <!-- backwards compatibility: 'yes' indicated static,     -->\n        <!-- anything else would be interpreted as if it was 'no' -->\n        <xsl:when test=\"$webwork.divisional.static = 'yes'\">\n            <xsl:text>static</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$webwork.divisional.static != ''\">\n            <xsl:text>dynamic</xsl:text>\n        </xsl:when>\n        <!-- no effort to set this switch, so use default -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$ww-default\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n<!-- the variable is now either 'static' or 'dynamic' -->\n<xsl:variable name=\"b-webwork-divisional-static\" select=\"$webwork-divisional-capability = 'static'\" />\n\n<xsl:variable name=\"webwork-reading-capability\">\n    <xsl:variable name=\"ww-default\" select=\"'static'\"/>\n    <xsl:choose>\n        <xsl:when test=\"$publication/html/webwork/@reading = 'dynamic'\">\n            <xsl:text>dynamic</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$publication/html/webwork/@reading = 'static'\">\n            <xsl:text>static</xsl:text>\n        </xsl:when>\n        <!-- attempted to set, but wrong -->\n        <xsl:when test=\"$publication/html/webwork/@reading\">\n            <xsl:message>PTX:FALLBACK: HTML WeBWorK @reading setting in publisher file should be \"static\" or \"dynamic\", not \"<xsl:value-of select=\"$publication/html/webwork/@reading\"/>\". Proceeding with default value: \"<xsl:value-of select=\"$ww-default\"/>\"</xsl:message>\n            <xsl:value-of select=\"$ww-default\"/>\n        </xsl:when>\n        <!-- backwards compatibility: 'yes' indicated static,     -->\n        <!-- anything else would be interpreted as if it was 'no' -->\n        <xsl:when test=\"$webwork.reading.static = 'yes'\">\n            <xsl:text>static</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$webwork.reading.static != ''\">\n            <xsl:text>dynamic</xsl:text>\n        </xsl:when>\n        <!-- no effort to set this switch, so use default -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$ww-default\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n<!-- the variable is now either 'static' or 'dynamic' -->\n<xsl:variable name=\"b-webwork-reading-static\" select=\"$webwork-reading-capability = 'static'\" />\n\n<xsl:variable name=\"webwork-worksheet-capability\">\n    <xsl:variable name=\"ww-default\" select=\"'static'\"/>\n    <xsl:choose>\n        <xsl:when test=\"$publication/html/webwork/@worksheet = 'dynamic'\">\n            <xsl:text>dynamic</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$publication/html/webwork/@worksheet = 'static'\">\n            <xsl:text>static</xsl:text>\n        </xsl:when>\n        <!-- attempted to set, but wrong -->\n        <xsl:when test=\"$publication/html/webwork/@worksheet\">\n            <xsl:message>PTX:FALLBACK: HTML WeBWorK @worksheet setting in publisher file should be \"static\" or \"dynamic\", not \"<xsl:value-of select=\"$publication/html/webwork/@worksheet\"/>\". Proceeding with default value: \"<xsl:value-of select=\"$ww-default\"/>\"</xsl:message>\n            <xsl:value-of select=\"$ww-default\"/>\n        </xsl:when>\n        <!-- backwards compatibility: 'yes' indicated static,     -->\n        <!-- anything else would be interpreted as if it was 'no' -->\n        <xsl:when test=\"$webwork.worksheet.static = 'yes'\">\n            <xsl:text>static</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$webwork.worksheet.static != ''\">\n            <xsl:text>dynamic</xsl:text>\n        </xsl:when>\n        <!-- no effort to set this switch, so use default -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$ww-default\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n<!-- the variable is now either 'static' or 'dynamic' -->\n<xsl:variable name=\"b-webwork-worksheet-static\" select=\"$webwork-worksheet-capability = 'static'\" />\n\n<xsl:variable name=\"webwork-project-capability\">\n    <xsl:variable name=\"ww-default\" select=\"'dynamic'\"/>\n    <xsl:choose>\n        <xsl:when test=\"$publication/html/webwork/@project = 'dynamic'\">\n            <xsl:text>dynamic</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$publication/html/webwork/@project = 'static'\">\n            <xsl:text>static</xsl:text>\n        </xsl:when>\n        <!-- attempted to set, but wrong -->\n        <xsl:when test=\"$publication/html/webwork/@project\">\n            <xsl:message>PTX:FALLBACK: HTML WeBWorK @project setting in publisher file should be \"static\" or \"dynamic\", not \"<xsl:value-of select=\"$publication/html/webwork/@project\"/>\". Proceeding with default value: \"<xsl:value-of select=\"$ww-default\"/>\"</xsl:message>\n            <xsl:value-of select=\"$ww-default\"/>\n        </xsl:when>\n        <!-- backwards compatibility: 'yes' indicated static,     -->\n        <!-- anything else would be interpreted as if it was 'no' -->\n        <xsl:when test=\"$webwork.project.static = 'yes'\">\n            <xsl:text>static</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$webwork.project.static != ''\">\n            <xsl:text>dynamic</xsl:text>\n        </xsl:when>\n        <!-- no effort to set this switch, so use default -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$ww-default\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n<!-- the variable is now either 'static' or 'dynamic' -->\n<xsl:variable name=\"b-webwork-project-static\" select=\"$webwork-project-capability = 'static'\" />\n\n\n<!--                   -->\n<!-- HTML Knowlization -->\n<!--                   -->\n\n<!-- A multitude of switches to control whether various HTML \"blocks\"      -->\n<!-- are born hidden as knowls.  Most names of resulting variables are     -->\n<!-- self-explanatory, the ones for exercises come in different varities.  -->\n<!-- Each template here ALWAYS produces \"yes\" or \"no\".  We do not make     -->\n<!-- boolean variables, since these are consumed (exclusively) in modal    -->\n<!-- \"is-hidden\" templates that produce string \"true\" or \"false\"           -->\n<!-- (respectively).  Some HTML-based conversions cannot accomodate knowls -->\n<!-- (EPUB, braille) so we turn off the \"is-hidden\" templates rather       -->\n<!-- than override these variables.                                        -->\n\n<xsl:variable name=\"knowl-theorem\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/knowl/pi:pub-attribute[@name='theorem']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"knowl-proof\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/knowl/pi:pub-attribute[@name='proof']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"knowl-definition\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/knowl/pi:pub-attribute[@name='definition']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"knowl-example\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/knowl/pi:pub-attribute[@name='example']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"knowl-example-solution\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/knowl/pi:pub-attribute[@name='example-solution']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"knowl-project\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/knowl/pi:pub-attribute[@name='project']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"knowl-task\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/knowl/pi:pub-attribute[@name='task']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"knowl-list\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/knowl/pi:pub-attribute[@name='list']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"knowl-remark\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/knowl/pi:pub-attribute[@name='remark']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"knowl-objectives\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/knowl/pi:pub-attribute[@name='objectives']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"knowl-outcomes\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/knowl/pi:pub-attribute[@name='outcomes']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"knowl-figure\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/knowl/pi:pub-attribute[@name='figure']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"knowl-table\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/knowl/pi:pub-attribute[@name='table']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"knowl-listing\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/knowl/pi:pub-attribute[@name='listing']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"knowl-exercise-inline\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/knowl/pi:pub-attribute[@name='exercise-inline']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"knowl-exercise-divisional\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/knowl/pi:pub-attribute[@name='exercise-divisional']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"knowl-exercise-worksheet\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/knowl/pi:pub-attribute[@name='exercise-worksheet']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"knowl-exercise-readingquestion\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/knowl/pi:pub-attribute[@name='exercise-readingquestion']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!--                   -->\n<!-- HTML Tabbed Tasks -->\n<!--                   -->\n\n<!-- Presentational choice for exercises and projects that are  -->\n<!-- structured by task.  Value is a list of possible types,    -->\n<!-- seen in creation of four boolean variables.  Never for the -->\n<!-- fifth type: \"exercise\" inside a \"worksheet\".               -->\n\n<xsl:variable name=\"html-tabbed-tasks\" select=\"str:tokenize($publication/html/exercises/@tabbed-tasks, ' ,')\"/>\n\n<!-- A string is equal to a node-set (the result of tokenize()) -->\n<!-- if it is equal to *one* child's text value.                -->\n<xsl:variable name=\"b-html-tabbed-tasks-divisional\" select=\"'divisional' = $html-tabbed-tasks\"/>\n<xsl:variable name=\"b-html-tabbed-tasks-inline\" select=\"'inline' = $html-tabbed-tasks\"/>\n<xsl:variable name=\"b-html-tabbed-tasks-reading\" select=\"'reading' = $html-tabbed-tasks\"/>\n<xsl:variable name=\"b-html-tabbed-tasks-project\" select=\"'project' = $html-tabbed-tasks\"/>\n\n<!--               -->\n<!-- HTML Base URL -->\n<!--               -->\n\n<!-- This is used to build/reference standalone pages.    -->\n<!-- Specified as a property of the HTML conversion, it   -->\n<!-- actually gets used in the LaTeX conversion to form   -->\n<!-- QR codes and make links to HTML versions of          -->\n<!-- Asymptote figures.                                   -->\n<!-- NB: We add a trailing slash, if not authored already -->\n<xsl:variable name=\"baseurl\">\n    <xsl:variable name=\"raw-input\">\n        <!-- if publisher file has a base url, use it -->\n        <xsl:if test=\"$publication/html/baseurl/@href\">\n            <xsl:value-of select=\"$publication/html/baseurl/@href\"/>\n        </xsl:if>\n        <!-- otherwise use the default, is empty as sentinel -->\n    </xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$raw-input =''\"/>\n        <xsl:otherwise>\n            <xsl:value-of select=\"$raw-input\"/>\n            <xsl:if test=\"not(substring($raw-input, string-length($raw-input), 1) = '/')\">\n                <xsl:text>/</xsl:text>\n            </xsl:if>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n<!-- For determining use in places such as static interactives -->\n<xsl:variable name=\"b-has-baseurl\" select=\"not($baseurl = '')\"/>\n\n<!--                 -->\n<!-- HTML Navigation -->\n<!--                 -->\n\n<!-- Navigation may follow two different logical models:                     -->\n<!--   (a) Linear, Prev/Next - depth-first search, linear layout like a book -->\n<!--       Previous and Next take you to the adjacent \"page\"                 -->\n<!--   (b) Tree, Prev/Up/Next - explicitly traverse the document tree        -->\n<!--       Prev and Next remain at same depth/level in tree                  -->\n<!--       Must follow a summary link to descend to finer subdivisions       -->\n<!--   'linear' is the default, 'tree' is an option                          -->\n<xsl:variable name=\"nav-logic\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/navigation/pi:pub-attribute[@name='logic']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- The \"up\" button is optional given the contents sidebar, default is to have it -->\n<!-- An up button is very desirable if you use the tree-like logic                 -->\n<xsl:variable name=\"nav-upbutton\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/navigation/pi:pub-attribute[@name='upbutton']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!--                 -->\n<!-- HTML TOC        -->\n<!--                 -->\n\n<!-- Whether or not to tag TOC as focused -->\n<xsl:variable name=\"html-toc-focused_value\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/html/tableofcontents/@focused != ''\">\n            <xsl:apply-templates select=\"$publisher-attribute-options/html/tableofcontents/pi:pub-attribute[@name='focused']\" mode=\"set-pubfile-variable\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <!-- check the theme for a default  -->\n            <xsl:if test=\"$html-theme/@focused-toc\">\n                <xsl:value-of select=\"$html-theme/@focused-toc\"/>\n            </xsl:if>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n<xsl:variable name=\"b-html-toc-focused\" select=\"$html-toc-focused_value='yes'\"/>\n\n<!-- How many levels from root to pre-expand in focused view -->\n<xsl:variable name=\"html-toc-preexpanded-levels\">\n    <xsl:variable name=\"preexpanded-value\" >\n        <xsl:apply-templates select=\"$publisher-attribute-options/html/tableofcontents/pi:pub-attribute[@name='preexpanded-levels']\" mode=\"set-pubfile-variable\"/>\n    </xsl:variable>\n    <xsl:if test=\"not($b-html-toc-focused) and $preexpanded-value > 0\">\n        <xsl:message>PTX:FALLBACK:   the preexpanded-levels setting (html/tableofcontents/@preexpanded-levels in the publisher file) has no effect if the table of contents is not set to focused mode (/html/tableofcontents/@focused is \"yes\").\"</xsl:message>\n    </xsl:if>\n    <xsl:value-of select=\"$preexpanded-value\"/>\n</xsl:variable>\n\n<!--                 -->\n<!-- HTML XREFS      -->\n<!--                 -->\n\n<!-- How to render xrefs. Default is \"maximum\" which renders xrefs to divisions as -->\n<!-- links and other xrefs as knowls. \"never\" renders all xrefs as links.          -->\n<!-- \"cross-page\" renders like \"never\" within a page and \"maximum\" otherwise.       -->\n<xsl:variable name=\"html-xref-knowled\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/cross-references/pi:pub-attribute[@name='knowled']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!--                              -->\n<!-- HTML CSS Style Specification -->\n<!--                              -->\n\n<!-- A temporary variable for testing -->\n<xsl:param name=\"debug.colors\" select=\"''\"/>\n<!-- A space-separated list of CSS URLs (points to servers or local files) -->\n<xsl:param name=\"html.css.extra\"  select=\"''\" />\n<!-- A single JS file for development purposes -->\n<xsl:param name=\"html.js.extra\" select=\"''\" />\n\n<!-- Name of color file possibly used in legacy styling -->\n<xsl:variable name=\"html.css.colors\">\n    <xsl:value-of select=\"$publication/html/css/@colors\"/>\n</xsl:variable>\n\n<!--                              -->\n<!-- HTML Theme Specification     -->\n<!--                              -->\n\n<!-- Stringparam to override theme. For testing and website build. -->\n<xsl:param name=\"debug.html.theme-name\"  select=\"''\" />\n\n<xsl:variable name=\"html-theme-name\">\n    <xsl:variable name=\"warning-message\">PTX:DEPRECATE: The \"FROMSTYLE\" style requested in publication/html/css is deprecated. Your book will be built with theme=\"TOSTYLE\". See the PreTeXt Guide for options for the newer HTML themes and their specification .</xsl:variable>\n    <xsl:choose>\n        <xsl:when test=\"$debug.html.theme-name != ''\">\n            <xsl:value-of select=\"$debug.html.theme-name\"/>\n        </xsl:when>\n        <xsl:when test=\"$publication/html/css/@theme\">\n            <xsl:value-of select=\"$publication/html/css/@theme\"/>\n        </xsl:when>\n        <xsl:when test=\"$publication/html/css/@style or $publication/html/css/@shell\">\n            <!-- legacy style detection and overriding -->\n            <xsl:choose>\n                <!-- crc and min are best detected via @shell -->\n                <xsl:when test=\"contains($publication/html/css/@shell, 'crc')\">\n                    <xsl:message><xsl:value-of select=\"str:replace(str:replace($warning-message, 'FROMSTYLE', 'crc'), 'TOSTYLE', 'denver')\"/></xsl:message>\n                    <xsl:text>denver</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"contains($publication/html/css/@shell, 'min')\">\n                    <xsl:message><xsl:value-of select=\"str:replace(str:replace($warning-message, 'FROMSTYLE', 'min'), 'TOSTYLE', 'tacoma')\"/></xsl:message>\n                    <xsl:text>tacoma</xsl:text>\n                </xsl:when>\n                <!-- others by @style                         -->\n                <xsl:when test=\"contains($publication/html/css/@style, 'wide')\">\n                    <xsl:message><xsl:value-of select=\"str:replace(str:replace($warning-message, 'FROMSTYLE', 'wide'), 'TOSTYLE', 'salem')\"/></xsl:message>\n                    <xsl:text>salem</xsl:text>\n                </xsl:when>\n                <xsl:when test=\"contains($publication/html/css/@style, 'oscarlevin')\">\n                    <xsl:message><xsl:value-of select=\"str:replace(str:replace($warning-message, 'FROMSTYLE', 'oscarlevin'), 'TOSTYLE', 'denver')\"/></xsl:message>\n                    <xsl:text>denver</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                  <xsl:variable name=\"legacy-style\">\n                    <xsl:value-of select=\"$publication/html/css/@style\"/>\n                  </xsl:variable>\n                  <xsl:message><xsl:value-of select=\"str:replace(str:replace($warning-message, 'FROMSTYLE', $legacy-style), 'TOSTYLE', 'default-modern')\"/></xsl:message>\n                  <xsl:text>default-modern</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>default-modern</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"b-html-theme-legacy\" select=\"contains($html-theme-name, '-legacy')\"/>\n\n<xsl:variable name=\"html-palette-name\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/css/pi:pub-attribute[@name='palette']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n\n<!-- lookup dict for known theme options -->\n<xsl:variable name=\"html-theme-option-list\">\n    <theme name=\"default-modern\" focused-toc=\"yes\">\n        <option name=\"provide-dark-mode\" default=\"yes\"/>\n        <option name=\"palette\" default=\"default\"/>\n        <option name=\"primary-color\" check-contrast=\"#fff\"/>\n        <option name=\"secondary-color\" check-contrast=\"#fff\"/>\n        <option name=\"primary-color-dark\" check-contrast=\"#23241f\"/>\n    </theme>\n    <theme name=\"denver\" focused-toc=\"yes\">\n        <option name=\"provide-dark-mode\" default=\"yes\"/>\n        <option name=\"palette\" default=\"default\"/>\n        <option name=\"color-main\" check-contrast=\"#fff\"/>\n        <option name=\"color-do\" check-contrast=\"#fff\"/>\n        <option name=\"color-fact\" check-contrast=\"#fff\"/>\n        <option name=\"color-meta\" check-contrast=\"#fff\"/>\n        <option name=\"primary-color-dark\" check-contrast=\"#23241f\"/>\n    </theme>\n    <theme name=\"tacoma\"  focused-toc=\"yes\">\n        <option name=\"provide-dark-mode\" default=\"yes\"/>\n        <option name=\"primary-color\" check-contrast=\"#fff\"/>\n        <option name=\"primary-color-dark\" check-contrast=\"#23241f\"/>\n    </theme>\n    <theme name=\"salem\" focused-toc=\"yes\">\n        <option name=\"provide-dark-mode\" default=\"yes\"/>\n        <option name=\"palette\" default=\"default\"/>\n        <option name=\"color-main\" check-contrast=\"#fff\"/>\n        <option name=\"color-do\" check-contrast=\"#fff\"/>\n        <option name=\"color-fact\" check-contrast=\"#fff\"/>\n        <option name=\"color-meta\" check-contrast=\"#fff\"/>\n        <option name=\"primary-color-dark\" check-contrast=\"#23241f\"/>\n    </theme>\n    <theme name=\"greeley\">\n        <option name=\"provide-dark-mode\" default=\"yes\"/>\n        <option name=\"primary-color\" check-contrast=\"#fff\"/>\n        <option name=\"primary-color-dark\" check-contrast=\"#23241f\"/>\n    </theme>\n    <theme name=\"boulder\">\n        <option name=\"provide-dark-mode\" default=\"yes\"/>\n        <option name=\"primary-color\" check-contrast=\"#fff\"/>\n        <option name=\"primary-color-dark\" check-contrast=\"#23241f\"/>\n    </theme>\n    <theme name=\"custom\">\n        <option name=\"provide-dark-mode\" default=\"yes\"/>\n        <option name=\"entry-point\" default=\"custom-theme.scss\"/>\n    </theme>\n</xsl:variable>\n\n<!-- Setup and use key to get the active theme                          -->\n<xsl:key name=\"html-theme-option-key\" match=\"theme\" use=\"@name\"/>\n<xsl:variable name=\"html-theme-rtf\">\n    <xsl:for-each select=\"exsl:node-set($html-theme-option-list)\">\n        <xsl:copy-of select=\"key('html-theme-option-key', $html-theme-name)\"/>\n    </xsl:for-each>\n</xsl:variable>\n\n<!-- Turn tree fragment into a node-set containing the selected theme   -->\n<xsl:variable name=\"html-theme\" select=\"exsl:node-set($html-theme-rtf)/theme\"/>\n\n<!-- Get an option (attr) from pub file css/theme. Available options    -->\n<!-- are constrained by html-theme-option-list above.                   -->\n<xsl:template name=\"get-theme-option\">\n    <xsl:param name=\"optname\"/>\n    <xsl:choose>\n        <!-- Must be an option in the theme or a custom theme -->\n        <xsl:when test=\"$html-theme/option[@name = $optname] or $html-theme[@name = 'custom']\">\n            <xsl:choose>\n                <xsl:when test=\"$publication/html/css/@*[name() = $optname]\">\n                    <!-- Exists in pub file, use that -->\n                    <xsl:value-of select=\"$publication/html/css/@*[name() = $optname]\"/>\n                </xsl:when>\n                <xsl:otherwise>\n                    <!-- Use default from theme def -->\n                    <xsl:value-of select=\"$html-theme/option[@name = $optname]/@default\"/>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- <xsl:otherwise>\n            <xsl:message>PTX:WARNING: HTML theme \"<xsl:value-of select=\"$html-theme-name\"/>\" does not support option \"<xsl:value-of select=\"$optname\"/>\".</xsl:message>\n        </xsl:otherwise> -->\n    </xsl:choose>\n</xsl:template>\n\n<!-- Test if current theme supports dark mode                           -->\n<xsl:variable name=\"theme-has-darkmode\">\n    <xsl:call-template name=\"get-theme-option\">\n        <xsl:with-param name=\"optname\" select=\"'provide-dark-mode'\"/>\n    </xsl:call-template>\n</xsl:variable>\n\n<xsl:variable name=\"b-theme-has-darkmode\" select=\"$theme-has-darkmode = 'yes'\"/>\n\n<!-- Grabs the html theme options element and returns its attr/values   -->\n<!-- in JSON format for use by theme build tools.                       -->\n<xsl:variable name=\"html-theme-options\">\n    <xsl:text>{</xsl:text>\n        <xsl:text>&quot;options&quot;:{</xsl:text>\n        <!-- if inside for-each, so can't use position to selectively add -->\n        <!-- commas. So build a string with a , after each item           -->\n        <xsl:variable name=\"options-string\">\n            <xsl:for-each select=\"$publication/html/css/@*\">\n                <xsl:variable name=\"optname\" select=\"name(.)\"/>\n                <!-- only pass on values that match theme options unless custom -->\n                <xsl:if test=\"$html-theme/option[@name = $optname] or $html-theme[@name = 'custom']\">\n                    <xsl:value-of select=\"concat('&quot;', name(.), '&quot;:')\"/>\n                    <xsl:value-of select=\"concat('&quot;', ., '&quot;')\"/>\n                    <xsl:text>,</xsl:text>\n                </xsl:if>\n            </xsl:for-each>\n        </xsl:variable>\n        <!-- then trim the trailing ,                                     -->\n        <xsl:value-of select=\"substring($options-string, 1, string-length($options-string) - 1)\"/>\n        <xsl:text>}</xsl:text>\n        <xsl:text>,&quot;contrast-checks&quot;:{</xsl:text>\n        <xsl:for-each select=\"$html-theme/*[@check-contrast]\">\n            <xsl:if test=\"position() > 1\"><xsl:text>,</xsl:text></xsl:if>\n            <xsl:value-of select=\"concat('&quot;', @name, '&quot;:')\"/>\n            <xsl:value-of select=\"concat('&quot;', @check-contrast, '&quot;')\"/>\n        </xsl:for-each>\n        <xsl:text>}</xsl:text>\n    <xsl:text>}</xsl:text>\n</xsl:variable>\n\n<!--                              -->\n<!-- HTML Analytics Configuration -->\n<!--                              -->\n\n<!-- String parameters are deprecated, so in -common -->\n<!-- file, and are only consulted secondarily here   -->\n\n<!-- NB: the \"$assembly-*\" trees are a bit dangerous, being formed  -->\n<!-- partway through the pre-processing phase.  Their previous      -->\n<!-- purpose, when used to query the \"docinfo\" was to be certain    -->\n<!-- that the pre-processing was done building versions, and/or     -->\n<!-- done adding/deleting material.  They could probably be         -->\n<!-- changed to \"$original/docinfo\".  The risk is that a project    -->\n<!-- might have multiple \"docinfo\" for multiple versions (the       -->\n<!-- supported scheme for this) and would be relying on only one    -->\n<!-- \"docinfo\" surviving.  However, uses below are for deprecated   -->\n<!-- situations, so we can warn about multiple \"docinfo\" in the     -->\n<!-- deprecation messages (as has been done for html/baseurl/@href. -->\n\n<xsl:variable name=\"statcounter-project\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/html/analytics/@statcounter-project\">\n            <xsl:value-of select=\"$publication/html/analytics/@statcounter-project\"/>\n        </xsl:when>\n        <!-- obsolete, to deprecate -->\n        <xsl:when test=\"not($html.statcounter.project = '')\">\n            <xsl:value-of select=\"$html.statcounter.project\"/>\n        </xsl:when>\n        <xsl:otherwise/>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"statcounter-security\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/html/analytics/@statcounter-security\">\n            <xsl:value-of select=\"$publication/html/analytics/@statcounter-security\"/>\n        </xsl:when>\n        <!-- obsolete, to deprecate -->\n        <xsl:when test=\"not($html.statcounter.security = '')\">\n            <xsl:value-of select=\"$html.statcounter.security\"/>\n        </xsl:when>\n        <xsl:otherwise/>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- 2019-11-28 all settings used here are deprecated -->\n<xsl:variable name=\"google-classic-tracking\">\n    <xsl:choose>\n        <xsl:when test=\"not($html.google-classic = '')\">\n            <xsl:value-of select=\"$html.google-classic\"/>\n        </xsl:when>\n        <xsl:otherwise/>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- 2019-11-28 all settings used here are deprecated -->\n<xsl:variable name=\"google-universal-tracking\">\n    <xsl:if test=\"not($html.google-universal = '')\">\n        <xsl:value-of select=\"$html.google-universal\"/>\n    </xsl:if>\n</xsl:variable>\n\n<!-- This is the preferred Google method as of 2019-11-28 -->\n<xsl:variable name=\"google-gst-tracking\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/analytics/pi:pub-attribute[@name='google-gst']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- And boolean variables for the presence of these services -->\n<!-- 2019-11-28 Two old Google services are deprecated        -->\n<xsl:variable name=\"b-statcounter\" select=\"not($statcounter-project = '') and not($statcounter-security = '')\" />\n<xsl:variable name=\"b-google-classic\" select=\"not($google-classic-tracking = '')\" />\n<xsl:variable name=\"b-google-universal\" select=\"not($google-universal-tracking = '')\" />\n<xsl:variable name=\"b-google-gst\" select=\"not($google-gst-tracking = '')\" />\n\n<!--                           -->\n<!-- HTML Search Configuration -->\n<!--                           -->\n\n<!-- String parameters are deprecated, so in -common     -->\n<!-- file, and are only consulted secondarily here       -->\n<xsl:variable name=\"google-search-cx\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/html/search/@google-cx\">\n            <xsl:value-of select=\"$publication/html/search/@google-cx\"/>\n        </xsl:when>\n        <xsl:when test=\"not($html.google-search = '')\">\n            <xsl:value-of select=\"$html.google-search\"/>\n        </xsl:when>\n        <xsl:otherwise/>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- And a boolean variable for the presence of this service -->\n<xsl:variable name=\"b-google-cse\" select=\"not($google-search-cx = '')\" />\n\n<!-- Possible values for search/@variant are:                      -->\n<!--                                                               -->\n<!--   \"none\" - self-explanatory, no computation, no interface     -->\n<!--   \"textbook\" - pages, divisions on pages, blocks, p[term],    -->\n<!--                chronological and indented presentation        -->\n<!--   \"reference\" - pages, divisions, all children of a division  -->\n<!--                 (blocks, first-class \"p\")                     -->\n<!--   \"default\" - historical, equal to \"textbook\"                 -->\n<!--                                                               -->\n<!-- Resulting variable values are \"none\", \"textbook\", \"reference\" -->\n<!-- and *not* \"default\", it was an historical fudge.              -->\n<!-- Note the boolean variable for the no-search case              -->\n<xsl:variable name=\"native-search-variant\">\n    <xsl:variable name=\"default-native-search\" select=\"'textbook'\"/>\n    <xsl:choose>\n        <xsl:when test=\"$publication/html/search/@variant = 'none'\">\n            <xsl:text>none</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$publication/html/search/@variant = 'textbook'\">\n            <xsl:text>textbook</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$publication/html/search/@variant = 'reference'\">\n            <xsl:text>reference</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$publication/html/search/@variant = 'default'\">\n            <!-- change to default variable once this becomes opt-out -->\n            <xsl:text>textbook</xsl:text>\n        </xsl:when>\n        <!-- set, but not correct, so inform and use default -->\n        <xsl:when test=\"$publication/html/search/@variant\">\n            <xsl:message>PTX:FALLBACK: HTML search/@variant in publisher file should be \"none\", \"textbook\", \"reference\" or \"default\", not \"<xsl:value-of select=\"$publication/html/search/@variant\"/>\". Proceeding with default value: \"<xsl:value-of select=\"$default-native-search\"/>\"</xsl:message>\n            <xsl:value-of select=\"$default-native-search\"/>\n        </xsl:when>\n        <!-- unset, so use default -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$default-native-search\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n    <!-- warn if Google search is also set               -->\n    <!-- TODO: implementation might prefer native search -->\n    <xsl:if test=\"$b-google-cse and $publication/html/search/@variant and not($publication/html/search/@variant = 'none')\">\n        <xsl:message>PTX:WARNING: specifying HTML search/@variant AND search/@google-cx in publisher file is not possible and will lead to unpredictable results</xsl:message>\n    </xsl:if>\n</xsl:variable>\n\n<xsl:variable name=\"has-native-search\" select=\"not($native-search-variant = 'none')\"/>\n\n<!-- Add a boolean variable to toggle \"enhanced privacy mode\" -->\n<!-- This is an option for embedded YouTube videos            -->\n<!-- and possibly other platforms at a later date.            -->\n<!-- The default is for privacy (fewer tracking cookies)      -->\n<xsl:variable name=\"embedded-video-privacy\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/video/pi:pub-attribute[@name='privacy']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"b-video-privacy\" select=\"$embedded-video-privacy = 'yes'\"/>\n\n<!--                       -->\n<!-- HTML Platform Options -->\n<!--                       -->\n\n<!-- 2019-12-17:  Under development, not documented -->\n\n<!-- 2024-01-18: the value of this option is queried by the Python -->\n<!-- routines, so keep their features and documentation in sync.   -->\n\n<xsl:variable name=\"host-platform\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/platform/pi:pub-attribute[@name='host']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- Intent is for exactly one of these boolean to be true -->\n<!-- 'web' is the default, so we may not condition with it -->\n<!-- 2019-12-19: only 'web' vs. 'runestone' implemented    -->\n<xsl:variable name=\"b-host-web\"       select=\"$host-platform = 'web'\"/>\n<xsl:variable name=\"b-host-runestone\" select=\"$host-platform = 'runestone'\"/>\n\n<!-- To create a standalone html document with all css and js served by CDN -->\n<!-- we can select platform/@portable to \"yes\"                              -->\n<xsl:variable name=\"portable-html\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/platform/pi:pub-attribute[@name='portable']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"b-portable-html\" select=\"$portable-html = 'yes'\"/>\n\n<!-- The css and js can be served locally (default) or by CDN -->\n<xsl:variable name=\"resources-host\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/resources/pi:pub-attribute[@name='host']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<!-- Always use cdn when \"b-portable-html\" is true or \"resources-host\" is \"cdn\" -->\n<xsl:variable name=\"b-cdn-resources\" select=\"$b-portable-html or $resources-host = 'cdn'\"/>\n\n<!-- The chunk level a document's structure implies, with no publisher -->\n<!-- or command-line choice consulted.  A conversion that accepts such -->\n<!-- a choice layers it over this; one that does not, such as EPUB,    -->\n<!-- uses this as-is, so the two can never drift apart.                -->\n<!-- Uses $version-root rather than $root because this is computed     -->\n<!-- before later assembly passes.  The contract (documented at the    -->\n<!-- definition of $version-root in pretext-assembly.xsl) is that no   -->\n<!-- assembly pass alters the gross document structure (book/article   -->\n<!-- type, part/chapter/section hierarchy), so $version-root is        -->\n<!-- reliable for these top-level queries.  Same contract relied upon  -->\n<!-- by $toc-level.                                                    -->\n<xsl:variable name=\"chunk-level-default\">\n    <xsl:choose>\n        <xsl:when test=\"$version-has-parts\">3</xsl:when>\n        <xsl:when test=\"$version-doc-type = 'book'\">2</xsl:when>\n        <xsl:when test=\"$version-article-sections or $version-article-printouts\">1</xsl:when>\n        <xsl:when test=\"$version-doc-type = 'article'\">0</xsl:when>\n        <xsl:when test=\"$version-doc-type = 'slideshow'\">0</xsl:when>\n        <xsl:when test=\"$version-doc-type = 'letter'\">0</xsl:when>\n        <xsl:when test=\"$version-doc-type = 'memo'\">0</xsl:when>\n        <xsl:otherwise>\n            <xsl:message>PTX:BUG:   chunk level not determined</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- The chunk level for HTML, available to any stylesheet that needs  -->\n<!-- to compute HTML filenames via the \"containing-filename\" template  -->\n<!-- (pretext-common.xsl) without importing the full pretext-html.xsl. -->\n<xsl:variable name=\"html-chunk-level\">\n    <xsl:choose>\n        <!-- portable html always gets chunk level 0 -->\n        <xsl:when test=\"$b-portable-html\">0</xsl:when>\n        <xsl:when test=\"$chunk-level-entered != ''\">\n            <xsl:value-of select=\"$chunk-level-entered\" />\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:value-of select=\"$chunk-level-default\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!--                            -->\n<!-- HTML Favicon Specification -->\n<!--                            -->\n\n<xsl:variable name=\"favicon-scheme\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/pi:pub-attribute[@name='favicon']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!--                            -->\n<!-- HTML Image Archive Links   -->\n<!--                            -->\n\n<!-- Requests for archive (download) versions of images: repeatable  -->\n<!-- \"archive\" elements within an \"images\" element.  The publication -->\n<!-- file form is preferred, and wins wholesale when present; the    -->\n<!-- \"images\" element within \"docinfo\" is deprecated (2026-07-30)    -->\n<!-- but honored while the publication file is silent.               -->\n<xsl:variable name=\"image-archives\" select=\"$publication/html/images/archive | $docinfo/images/archive[not($publication/html/images/archive)]\"/>\n\n<!--                            -->\n<!-- HTML Brand Logo            -->\n<!--                            -->\n\n<!-- An image for the masthead, optionally linking to a landing   -->\n<!-- page.  The publication file form is preferred, and elects    -->\n<!-- the logo wholesale (both attributes); the \"brandlogo\" within -->\n<!-- \"docinfo\" is deprecated (2026-07-30) but honored while the   -->\n<!-- publication file is silent.                                  -->\n<xsl:variable name=\"brandlogo-elected\" select=\"$publication/html/brandlogo | $docinfo/brandlogo[not($publication/html/brandlogo)]\"/>\n<xsl:variable name=\"brandlogo-source\" select=\"string($brandlogo-elected/@source)\"/>\n<xsl:variable name=\"brandlogo-url\" select=\"string($brandlogo-elected/@url)\"/>\n<xsl:variable name=\"b-brandlogo\" select=\"not($brandlogo-source = '')\"/>\n\n<!--                            -->\n<!-- HTML Embed Page button     -->\n<!--                            -->\n\n<xsl:variable name=\"embed-button\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/pi:pub-attribute[@name='embed-button']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"b-has-embed-button\" select=\"$embed-button = 'yes'\"/>\n\n<!--                           -->\n<!-- HTML Read-aloud control   -->\n<!--                           -->\n\n<xsl:variable name=\"read-aloud\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/pi:pub-attribute[@name='read-aloud']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"b-read-aloud\" select=\"not($read-aloud = 'no')\"/>\n\n<!--                            -->\n<!-- HTML Banner options        -->\n<!--                            -->\n<xsl:variable name=\"html-banner-subtitle\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/banner/pi:pub-attribute[@name='subtitle']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"b-html-banner-subtitle\" select=\"$html-banner-subtitle = 'yes'\"/>\n\n<xsl:variable name=\"html-banner-byline\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/html/banner/pi:pub-attribute[@name='byline']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"b-html-banner-byline\" select=\"$html-banner-byline = 'yes'\"/>\n\n\n<!-- ##################### -->\n<!-- EPUB-Specific Options -->\n<!-- ##################### -->\n\n<!-- Cover image specification -->\n\n<!-- Author-specified relative to source external directory -->\n<xsl:variable name=\"epub-cover-base-filename\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/epub/cover/pi:pub-attribute[@name='front']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- If the author does not say, eventually we will try to build a cover -->\n<xsl:variable name=\"b-authored-cover\" select=\"not(normalize-space($epub-cover-base-filename)) = ''\"/>\n\n<!-- This is where the file lives within the author's version of -->\n<!-- the external files, so eventually Python will pick this up  -->\n<xsl:variable name=\"epub-cover-source\">\n    <xsl:value-of select=\"$external-directory-source\"/>\n    <xsl:value-of select=\"$epub-cover-base-filename\"/>\n</xsl:variable>\n\n<!-- This is where the image file lands in the final XHTML directory. -->\n<!-- So this gets written into several constituents of the EPUB files -->\n<!-- as the (special) cover image.  When an author does not provide   -->\n<!-- the file, the Python makes one and it is always placed in the    -->\n<!-- top-level of the EPUB package.                                   -->\n<xsl:variable name=\"epub-cover-dest\">\n    <xsl:choose>\n        <xsl:when test=\"$b-authored-cover\">\n            <xsl:value-of select=\"$external-directory\"/>\n            <xsl:value-of select=\"$epub-cover-base-filename\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>cover.png</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- The kernel a Jupyter notebook opens with; \"sagemath\" -->\n<!-- names the latest kernel of the Sage distribution's   -->\n<!-- Jupyter, and of CoCalc                               -->\n<xsl:variable name=\"jupyter-kernel\">\n    <xsl:choose>\n        <!-- The stringparam (deprecated 2026-07-10) once accepted many  -->\n        <!-- spellings of the Python kernel's name; each normalizes to   -->\n        <!-- \"python3\", with a warning.  The canonical values continue   -->\n        <!-- through the generic machinery, which has its own warning.   -->\n        <xsl:when test=\"not($jupyter.kernel = '') and not($jupyter.kernel = 'python3') and not($jupyter.kernel = 'sagemath') and contains('|Python3|python 3|Python 3|py|Py|python|Python|', concat('|', $jupyter.kernel, '|'))\">\n            <xsl:text>python3</xsl:text>\n            <xsl:message>PTX:DEPRECATE: the stringparam \"jupyter.kernel\" is deprecated (2026-07-10), and your value \"<xsl:value-of select=\"$jupyter.kernel\"/>\" has been interpreted as \"python3\".  Move to the publication file entry, jupyter/@kernel, with the value \"python3\".</xsl:message>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:apply-templates select=\"$publisher-attribute-options/jupyter/pi:pub-attribute[@name='kernel']\" mode=\"set-pubfile-variable\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n\n<!-- ##################### -->\n<!-- Text-Specific Options -->\n<!-- ##################### -->\n\n<!-- The character repertoire of the plain text and markdown        -->\n<!-- conversions: genuine Unicode characters (dashes, quotation     -->\n<!-- marks, ...) or 7-bit ASCII stand-ins.                          -->\n<xsl:variable name=\"text-characters\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/text/pi:pub-attribute[@name='characters']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"b-text-unicode\" select=\"$text-characters = 'unicode'\"/>\n\n\n<!-- ######################## -->\n<!-- Braille-Specific Options -->\n<!-- ######################## -->\n\n<!-- Page geometry of embossed output: cells in a line, lines on a  -->\n<!-- page.  Freeform entries, validated here to positive integers,  -->\n<!-- with the common North American embosser page as the default.   -->\n\n<xsl:variable name=\"braille-page-width-entered\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/braille/page/pi:pub-attribute[@name='width']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"braille-page-width\">\n    <xsl:choose>\n        <xsl:when test=\"(number($braille-page-width-entered) = round(number($braille-page-width-entered))) and (number($braille-page-width-entered) &gt; 0)\">\n            <xsl:value-of select=\"round(number($braille-page-width-entered))\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message>PTX:FALLBACK: the braille page width in the publication file (\"<xsl:value-of select=\"$braille-page-width-entered\"/>\") must be a positive whole number of cells, using the default, 40</xsl:message>\n            <xsl:text>40</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<xsl:variable name=\"braille-page-height-entered\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/braille/page/pi:pub-attribute[@name='height']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"braille-page-height\">\n    <xsl:choose>\n        <xsl:when test=\"(number($braille-page-height-entered) = round(number($braille-page-height-entered))) and (number($braille-page-height-entered) &gt; 0)\">\n            <xsl:value-of select=\"round(number($braille-page-height-entered))\"/>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:message>PTX:FALLBACK: the braille page height in the publication file (\"<xsl:value-of select=\"$braille-page-height-entered\"/>\") must be a positive whole number of lines, using the default, 25</xsl:message>\n            <xsl:text>25</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n\n<!-- ###################### -->\n<!-- LaTeX-Specific Options -->\n<!-- ###################### -->\n\n<!-- Sides are given as \"one\" or \"two\".  And we cannot think of    -->\n<!-- any other options.  So we build, and use, a boolean variable.   -->\n<!-- But if a third option aries, we can use it, and switch away  -->\n<!-- from the boolean variable without the author knowing. -->\n<xsl:variable name=\"latex-sides\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/latex/pi:pub-attribute[@name='sides']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:template match=\"latex/pi:pub-attribute[@name='sides']\" mode=\"get-default-pub-variable\">\n    <xsl:choose>\n        <xsl:when test=\"$b-latex-print\">\n            <xsl:text>two</xsl:text>\n        </xsl:when>\n        <xsl:otherwise> <!-- electronic -->\n            <xsl:text>one</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n<!-- We have \"one\" or \"two\", or junk from the deprecated string parameter -->\n<xsl:variable name=\"b-latex-two-sides\" select=\"$latex-sides = 'two'\"/>\n\n<!-- Print versus electronic.  Historically \"yes\" versus \"no\" -->\n<!-- and that seems stable enough, as in, we don't need to    -->\n<!-- contemplate some third variant of LaTeX output.          -->\n<xsl:variable name=\"latex-print\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/latex/pi:pub-attribute[@name='print']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- We have \"yes\" or \"no\", or possibly junk from the deprecated string    -->\n<!-- parameter, so we want the default (false) to be more likely than not. -->\n<xsl:variable name=\"b-latex-print\" select=\"not($latex-print = 'no')\"/>\n\n<!-- Always open on odd page in one-sided version, to        -->\n<!-- to faciltate matching page-for-page with two-sided      -->\n<!-- version.                                                -->\n<!-- \"add-blanks\" means make a blank page on the even page   -->\n<!--              preceding open odd page, when necessary    -->\n<!-- \"skip-pages\" means skip over an even page number in the -->\n<!--              pagination to open on an odd page number,  -->\n<!--              when necessary                             -->\n<!-- \"no\"         continuous pagination, parts/chapters/etc  -->\n<!--              can open on either even or odd pages       -->\n<xsl:variable name=\"latex-open-odd\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/latex/pi:pub-attribute[@name='open-odd']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- Used to determine which xsl file to processess with.  Current options are based on what is present in xsl/latex.   -->\n<!-- To build with `pretext-latex-styleName.xsl` variable should have valuse `stylename`. Default of empty string means -->\n<!-- build with the default `pretext-latex.xsl` -->\n<xsl:variable name=\"latex-style\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/latex/pi:pub-attribute[@name='latex-style']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- \"none\" (default) or \"underline\": whether hyperlinks (xref, url) -->\n<!-- receive visual highlighting in the LaTeX/PDF output.            -->\n<xsl:variable name=\"latex-link-highlight\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/latex/pi:pub-attribute[@name='link-highlight']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- LaTeX/Page -->\n\n<!-- Right Alignment -->\n<!-- guaranteed to be 'flush' or 'ragged'   -->\n<!-- N.B. let HTML be different/independent -->\n<xsl:variable name=\"latex-right-alignment\">\n    <xsl:variable name=\"default-align\" select=\"'flush'\"/>\n    <xsl:choose>\n        <xsl:when test=\"$publication/latex/page/@right-alignment = 'flush'\">\n            <xsl:text>flush</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$publication/latex/page/@right-alignment = 'ragged'\">\n            <xsl:text>ragged</xsl:text>\n        </xsl:when>\n        <!-- attempted to set, but wrong -->\n        <xsl:when test=\"$publication/latex/page/@right-alignment\">\n            <xsl:message>PTX:FALLBACK: LaTeX right-alignment setting in publisher file should be \"flush\" or \"ragged\", not \"<xsl:value-of select=\"$publication/latex/page/@right-alignment\"/>\". Proceeding with default value: \"<xsl:value-of select=\"$default-align\"/>\"</xsl:message>\n            <xsl:value-of select=\"$default-align\"/>\n        </xsl:when>\n        <!-- or respect deprecated stringparam in use, text.alignment -->\n        <xsl:when test=\"$text.alignment = 'justify'\">\n            <xsl:text>flush</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$text.alignment = 'raggedright'\">\n            <xsl:text>ragged</xsl:text>\n        </xsl:when>\n        <!-- no attempt at all, so default -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$default-align\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- Bottom Alignment -->\n<!-- guaranteed to be 'flush' or 'ragged'            -->\n<!-- LaTeX varies this according to oneside, twoside -->\n<!-- https://www.sascha-frank.com/page-break.html    -->\n<!-- N.B. makes no sense for HTML                    -->\n<xsl:variable name=\"latex-bottom-alignment\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/latex/page/pi:pub-attribute[@name='bottom-alignment']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- LaTeX worksheet formatting -->\n<!-- By default, worksheets in LaTeX will be formatted -->\n<!-- with specified margins, pages, and workspace.     -->\n<!-- Publisher switch to format continuously with      -->\n<!-- other divisions here                              -->\n<xsl:variable name=\"latex-worksheet-formatted\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/latex/worksheet/pi:pub-attribute[@name='formatted']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"b-latex-worksheet-formatted\" select=\"$latex-worksheet-formatted = 'yes'\"/>\n\n<!-- LaTeX insertions -->\n<!-- Pagebreaks-->\n<xsl:variable name=\"latex-pagebreaks-string\">\n    <xsl:variable name=\"join-latex-pagebreaks\">\n        <xsl:for-each select=\"$publication/latex/insertions/@pagebreaks\">\n            <xsl:text> </xsl:text>\n            <xsl:value-of select=\"normalize-space(.)\"/>\n        </xsl:for-each>\n    </xsl:variable>\n    <xsl:value-of select=\"substring-after($join-latex-pagebreaks, ' ')\"/>\n</xsl:variable>\n\n<!-- For historical reasons, this variable has \"pt\" as part -->\n<!-- of its value.  A change would need to be coordinated   -->\n<!-- with every application in the -latex conversion.       -->\n<xsl:variable name=\"font-size\">\n    <xsl:choose>\n        <!-- via publication file -->\n        <xsl:when test=\"$publication/latex/@font-size\">\n            <!-- provisional, convenience -->\n            <xsl:variable name=\"fs\" select=\"$publication/latex/@font-size\"/>\n            <xsl:choose>\n                <xsl:when test=\"($fs =  '8') or\n                                ($fs =  '9') or\n                                ($fs = '10') or\n                                ($fs = '11') or\n                                ($fs = '12') or\n                                ($fs = '14') or\n                                ($fs = '17') or\n                                ($fs = '20')\">\n                    <xsl:value-of select=\"$fs\"/>\n                    <xsl:text>pt</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:message>PTX:FALLBACK: LaTeX @font-size in publication file should be 8, 9, 10, 11, 12, 14, 17 or 20 points, not \"<xsl:value-of select=\"$publication/latex/@font-size\"/>\".  Proceeding with default value: \"10\"</xsl:message>\n                    <xsl:text>10pt</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- via deprecated stringparam: assumes \"pt\" as the unit of measure   -->\n        <!-- (this is recycled code, so no real attempt to do better)          -->\n        <xsl:when test=\"not($latex.font.size = '')\">\n            <xsl:choose>\n                <xsl:when test=\"$latex.font.size='10pt'\"><xsl:value-of select=\"$latex.font.size\" /></xsl:when>\n                <xsl:when test=\"$latex.font.size='12pt'\"><xsl:value-of select=\"$latex.font.size\" /></xsl:when>\n                <xsl:when test=\"$latex.font.size='11pt'\"><xsl:value-of select=\"$latex.font.size\" /></xsl:when>\n                <xsl:when test=\"$latex.font.size='8pt'\"><xsl:value-of select=\"$latex.font.size\" /></xsl:when>\n                <xsl:when test=\"$latex.font.size='9pt'\"><xsl:value-of select=\"$latex.font.size\" /></xsl:when>\n                <xsl:when test=\"$latex.font.size='14pt'\"><xsl:value-of select=\"$latex.font.size\" /></xsl:when>\n                <xsl:when test=\"$latex.font.size='17pt'\"><xsl:value-of select=\"$latex.font.size\" /></xsl:when>\n                <xsl:when test=\"$latex.font.size='20pt'\"><xsl:value-of select=\"$latex.font.size\" /></xsl:when>\n                <xsl:otherwise>\n                    <xsl:text>10pt</xsl:text>\n                    <xsl:message>PTX:FALLBACK:  the *deprecated* latex.font.size parameter must be 8pt, 9pt, 10pt, 11pt, 12pt, 14pt, 17pt, or 20pt, not \"<xsl:value-of select=\"$latex.font.size\" />\".  Using the default (\"10pt\")</xsl:message>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <!-- no publication file entry, no deprecated  -->\n        <!-- string parameter, so use the default value -->\n        <xsl:otherwise>\n            <xsl:text>10pt</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- Font selection for the XSL-FO PDF route (\"pdf-fo\").  A key names a -->\n<!-- tested font set; the FO conversion maps the key to concrete font  -->\n<!-- family names, which  pretext/fop.xconf  embeds.  Guaranteed to be  -->\n<!-- currently only 'latin-modern' (default, matches the LaTeX route).  -->\n<xsl:variable name=\"pdf-font\">\n    <xsl:variable name=\"default-pdf-font\" select=\"'latin-modern'\"/>\n    <xsl:choose>\n        <xsl:when test=\"$publication/pdf/@font = 'latin-modern'\">\n            <xsl:text>latin-modern</xsl:text>\n        </xsl:when>\n        <!-- attempted to set, but not a recognized key -->\n        <xsl:when test=\"$publication/pdf/@font\">\n            <xsl:message>PTX:FALLBACK: PDF (XSL-FO) font setting in publisher file should be \"latin-modern\", not \"<xsl:value-of select=\"$publication/pdf/@font\"/>\". Proceeding with default value: \"<xsl:value-of select=\"$default-pdf-font\"/>\"</xsl:message>\n            <xsl:value-of select=\"$default-pdf-font\"/>\n        </xsl:when>\n        <!-- no attempt at all, so default -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$default-pdf-font\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- Simple - just feeds into a LaTeX \\geometry{} -->\n<xsl:variable name=\"latex-page-geometry\">\n    <xsl:choose>\n        <!-- prefer publication file entry -->\n        <xsl:when test=\"$publication/latex/page/geometry\">\n            <xsl:value-of select=\"$publication/latex/page/geometry\"/>\n        </xsl:when>\n        <!-- deprecated string parameter in use-->\n        <xsl:when test=\"($latex.geometry != '')\">\n            <xsl:value-of select=\"$latex.geometry\"/>\n        </xsl:when>\n        <!-- empty is the signal to not use -->\n        <xsl:otherwise/>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- For crop marks to make sense, a paper size must be known -->\n<!-- There is no error-checking here, any non-empty value     -->\n<!-- initiates the crop marks and becomes the paper size.     -->\n<!-- Values from the  crop  package, 2023-05-19 are:          -->\n<!--     a0, a1, a2, a3, a4, a5, a6,                          -->\n<!--     b0, b1, b2, b3, b4, b5, b6,                          -->\n<!--     letter, legal, executive                             -->\n<xsl:variable name=\"latex-crop-papersize\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/latex/page/@crop-marks = 'none'\"/>\n        <xsl:when test=\"not($publication/latex/page/@crop-marks)\"/>\n        <xsl:otherwise>\n            <xsl:value-of select=\"$publication/latex/page/@crop-marks\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n<!-- empty implies feature not selected -->\n<xsl:variable name=\"b-latex-crop-marks\" select=\"not($latex-crop-papersize = '')\"/>\n\n<!-- The default for the use of page references varies, so that  -->\n<!-- particular logic is in the -latex conversion.  Here we just -->\n<!-- sanitize to \"yes\", \"no\" or empty (i.e. ignored)             -->\n<xsl:variable name=\"latex-pageref\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/latex/pi:pub-attribute[@name='pageref']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- Draft Copies                                              -->\n<!-- Various options for working copies for authors            -->\n<!-- (1) LaTeX's draft mode                                    -->\n<!-- (2) Crop marks on letter paper, centered                  -->\n<!--     presuming geometry sets smaller page size             -->\n<!--     with paperheight, paperwidth                          -->\n<xsl:variable name=\"latex-draft-mode\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/latex/pi:pub-attribute[@name='draft']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"b-latex-draft-mode\" select=\"$latex-draft-mode = 'yes'\"/>\n\n<!-- LaTeX/Asymptote -->\n\n<!-- Add a boolean variable to toggle links for Asymptote images in PDF.    -->\n<!-- If a baseurl is set, and an HTML version is available with interactive -->\n<!-- WebGL images the publisher may want static images in the PDF to link   -->\n<!-- to the interactive images online.                                      -->\n<xsl:variable name=\"asymptote-links\">\n    <xsl:choose>\n        <!-- fail automatically and silently for print -->\n        <xsl:when test=\"$b-latex-print\">\n            <xsl:text>no</xsl:text>\n        </xsl:when>\n        <!-- proceed when requested, so long as there is a base URL -->\n        <xsl:when test=\"$publication/latex/asymptote/@links = 'yes'\">\n            <xsl:choose>\n                <!-- fail when no base URL is given -->\n                <xsl:when test=\"not($b-has-baseurl)\">\n                    <xsl:message>PTX:WARNING: baseurl must be set in publisher file to enable links from Asymptote images</xsl:message>\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <xsl:when test=\"$publication/latex/asymptote/@links = 'no'\">\n            <xsl:text>no</xsl:text>\n        </xsl:when>\n        <!-- set, but not correct, so inform and use default -->\n        <xsl:when test=\"$publication/latex/asymptote/@links\">\n            <xsl:message>PTX:FALLBACK: LaTeX links to Asymptote publisher file should be \"yes\" (links to HTML) or \"no\" (no links), not \"<xsl:value-of select=\"$publication/latex/asymptote/@links\"/>\". Proceeding with default value: \"no\" (no links)</xsl:message>\n            <xsl:text>no</xsl:text>\n        </xsl:when>\n        <!-- unset, use the default, which is \"no\" since -->\n        <!-- it also needs action to set base URL        -->\n        <xsl:otherwise>\n            <xsl:text>no</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n<xsl:variable name=\"b-asymptote-links\" select=\"$asymptote-links = 'yes'\"/>\n\n<!-- Add another boolean to turn on links in html -->\n<!-- so reader can click to open a larger version -->\n\n<xsl:variable name=\"asymptote-html-links\">\n    <xsl:choose>\n        <!-- proceed when requested, so long as there is a base URL -->\n        <xsl:when test=\"$publication/html/asymptote/@links = 'yes'\">\n            <xsl:choose>\n                <!-- fail when no base URL is given -->\n                <xsl:when test=\"not($b-has-baseurl)\">\n                    <xsl:message>PTX:WARNING: baseurl must be set in publisher file to enable links from Asymptote images</xsl:message>\n                    <xsl:text>no</xsl:text>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:text>yes</xsl:text>\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:when>\n        <xsl:when test=\"$publication/html/asymptote/@links = 'no'\">\n            <xsl:text>no</xsl:text>\n        </xsl:when>\n        <!-- set, but not correct, so inform and use default -->\n        <xsl:when test=\"$publication/html/asymptote/@links\">\n            <xsl:message>PTX:FALLBACK: HTML links to Asymptote publisher file should be \"yes\" (adds link below image) or \"no\" (no links), not \"<xsl:value-of select=\"$publication/latex/asymptote/@links\"/>\". Proceeding with default value: \"no\" (no links)</xsl:message>\n            <xsl:text>no</xsl:text>\n        </xsl:when>\n        <!-- unset, use the default, which is \"no\" since -->\n        <!-- it also needs action to set base URL        -->\n        <xsl:otherwise>\n            <xsl:text>no</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n<xsl:variable name=\"b-asymptote-html-links\" select=\"$asymptote-html-links = 'yes'\"/>\n\n<xsl:variable name=\"latex-snapshot\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/latex/pi:pub-attribute[@name='snapshot']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"b-latex-snapshot\" select=\"$latex-snapshot = 'yes'\"/>\n\n<!-- LaTeX Cover Pages -->\n\n<!-- Front and back, a filename and a flag -->\n\n<xsl:variable name=\"latex-front-cover-filename\">\n    <xsl:choose>\n        <!-- post-managed directories, but $external-directory -->\n        <!-- should preserve backward-compatibilty             -->\n        <xsl:when test=\"$publication/latex/cover/@front\">\n            <xsl:value-of select=\"$external-directory\"/>\n            <xsl:value-of select=\"$publication/latex/cover/@front\"/>\n        </xsl:when>\n        <otherwise/>\n    </xsl:choose>\n</xsl:variable>\n<xsl:variable name=\"b-has-latex-front-cover\" select=\"not($latex-front-cover-filename = '')\"/>\n\n<xsl:variable name=\"latex-back-cover-filename\">\n    <xsl:choose>\n        <!-- post-managed directories, but $external-directory -->\n        <!-- should preserve backward-compatibilty             -->\n        <xsl:when test=\"$publication/latex/cover/@back\">\n            <xsl:value-of select=\"$external-directory\"/>\n            <xsl:value-of select=\"$publication/latex/cover/@back\"/>\n        </xsl:when>\n        <otherwise/>\n    </xsl:choose>\n</xsl:variable>\n<xsl:variable name=\"b-has-latex-back-cover\" select=\"not($latex-back-cover-filename = '')\"/>\n\n\n<!-- ########### -->\n<!-- LaTeX Fonts -->\n<!-- ########### -->\n\n<xsl:variable name=\"latex-font-main-regular\">\n    <!-- having a main font specification *requires* a @regular -->\n    <xsl:apply-templates select=\"$publisher-attribute-options/latex/fonts/main/pi:pub-attribute[@name='regular']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<!-- A convenience boolean variable for indication of alternate main font -->\n<xsl:variable name=\"b-alternate-main-font\" select=\"not($latex-font-main-regular = '')\"/>\n\n<xsl:variable name=\"latex-font-main-options\">\n    <!-- having a main font specification *requires* a @regular -->\n    <xsl:apply-templates select=\"$publisher-attribute-options/latex/fonts/main/pi:pub-attribute[@name='options']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<xsl:variable name=\"latex-font-math-regular\">\n    <!-- having a math font specification *requires* a @regular -->\n    <xsl:apply-templates select=\"$publisher-attribute-options/latex/fonts/math/pi:pub-attribute[@name='regular']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<!-- A convenience boolean variable for indication of alternate math font -->\n<xsl:variable name=\"b-alternate-math-font\" select=\"not($latex-font-math-regular = '')\"/>\n\n<xsl:variable name=\"latex-font-math-options\">\n    <!-- having a math font specification *requires* a @regular -->\n    <xsl:apply-templates select=\"$publisher-attribute-options/latex/fonts/math/pi:pub-attribute[@name='options']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- ########################### -->\n<!-- Reveal.js Slideshow Options -->\n<!-- ########################### -->\n\n<!-- Reveal.js Theme -->\n\n<xsl:variable name=\"reveal-theme\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/revealjs/appearance/pi:pub-attribute[@name='theme']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- A space-separated list of CSS URLs (points to servers or local files) -->\n<xsl:variable name=\"reveal-custom-css\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/revealjs/appearance/pi:pub-attribute[@name='custom-css']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- Reveal.js Controls Back Arrows -->\n\n<xsl:variable name=\"reveal-control-backarrow\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/revealjs/controls/pi:pub-attribute[@name='backarrows']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- Reveal.js Controls (on-screen navigation) -->\n\n<xsl:variable name=\"reveal-control-display\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/revealjs/controls/pi:pub-attribute[@name='display']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<!-- Convert \"yes\"/\"no\" to a boolean variable -->\n<xsl:variable name=\"b-reveal-control-display\" select=\"$reveal-control-display= 'yes'\"/>\n\n<!-- Reveal.js Controls Layout -->\n\n<xsl:variable name=\"reveal-control-layout\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/revealjs/controls/pi:pub-attribute[@name='layout']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- Reveal.js Controls Tutorial (animated arrows) -->\n\n<xsl:variable name=\"reveal-control-tutorial\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/revealjs/controls/pi:pub-attribute[@name='tutorial']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<!-- Convert \"yes\"/\"no\" to a boolean variable -->\n<xsl:variable name=\"b-reveal-control-tutorial\" select=\"$reveal-control-tutorial= 'yes'\"/>\n\n<!-- Reveal.js Navigation Mode -->\n\n<xsl:variable name=\"reveal-navigation-mode\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/revealjs/navigation/pi:pub-attribute[@name='mode']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n<!-- \"online\" (default) loads MathJax in the browser; \"embedded\"   -->\n<!-- replaces each piece of mathematics with an SVG image, with a  -->\n<!-- speech string, both manufactured at build time, so the        -->\n<!-- slideshow performs no typesetting at all.  The default flips  -->\n<!-- to \"embedded\" when the resources are embedded (a custom       -->\n<!-- default template below), since a network-detached slideshow   -->\n<!-- cannot load MathJax.                                          -->\n<xsl:variable name=\"reveal-math-source\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/revealjs/resources/pi:pub-attribute[@name='math']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n<xsl:variable name=\"b-reveal-embedded-math\" select=\"$reveal-math-source = 'embedded'\"/>\n\n<xsl:template match=\"revealjs/resources/pi:pub-attribute[@name='math']\" mode=\"get-default-pub-variable\">\n    <xsl:choose>\n        <xsl:when test=\"$publication/revealjs/resources/@host = 'embedded'\">\n            <xsl:text>embedded</xsl:text>\n        </xsl:when>\n        <xsl:otherwise>\n            <xsl:text>online</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- Reveal.js Resources file location -->\n\n<!-- The *effective* host.  Embedded resources require embedded      -->\n<!-- mathematics: an authored \"math\" left unspecified defaults to    -->\n<!-- \"embedded\" (above), but an explicit online election contradicts -->\n<!-- the request for a network-detached file, so the whole slideshow -->\n<!-- falls back to fully online, with an error.                      -->\n<xsl:variable name=\"reveal-resources-host\">\n    <xsl:choose>\n        <xsl:when test=\"($publication/revealjs/resources/@host = 'embedded') and not($b-reveal-embedded-math)\">\n            <xsl:message>PTX:ERROR:   the publisher file elects embedded reveal.js resources (revealjs/resources/@host) but online mathematics (revealjs/resources/@math).  A network-detached slideshow cannot load MathJax, so both entries will be treated as online.  Remove the \"math\" entry, or set it to \"embedded\", to embed the resources.</xsl:message>\n            <xsl:text>cdn</xsl:text>\n        </xsl:when>\n        <xsl:when test=\"$publication/revealjs/resources/@host\">\n            <xsl:value-of select=\"$publication/revealjs/resources/@host\"/>\n        </xsl:when>\n        <!-- default to the CDN if no specification -->\n        <xsl:otherwise>\n            <xsl:text>cdn</xsl:text>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n<xsl:variable name=\"b-reveal-embedded-resources\" select=\"$reveal-resources-host = 'embedded'\"/>\n\n<!-- String to prefix  reveal.js  resources -->\n<xsl:variable name=\"reveal-root\">\n    <!-- CDN is used twice, so just edit here -->\n    <!-- NB: deprecation is frozen -->\n    <!-- The \"@6\" is a semantic-version range: jsdelivr serves the    -->\n    <!-- newest 6.x release, so fixes arrive automatically while a    -->\n    <!-- breaking 7.0 cannot.  Same pattern as the MathJax \"@4\" URLs. -->\n    <xsl:variable name=\"cdn-url\">\n        <xsl:text>https://cdn.jsdelivr.net/npm/reveal.js@6/dist</xsl:text>\n    </xsl:variable>\n\n    <xsl:choose>\n        <!-- if publisher.xml file has CDN option specified, use it       -->\n        <!-- keep this URL updated, but not for the deprecation situation -->\n        <!-- Embedded resources emit the same CDN references: the         -->\n        <!-- pretext/pretext script replaces them with the file contents, -->\n        <!-- and any other processing degrades gracefully to the CDN.     -->\n        <xsl:when test=\"($reveal-resources-host = 'cdn') or ($reveal-resources-host = 'embedded')\">\n            <xsl:value-of select=\"$cdn-url\"/>\n        </xsl:when>\n        <!-- if publisher.xml file has the local option specified, use it -->\n        <xsl:when test=\"$reveal-resources-host = 'local'\">\n            <xsl:text>.</xsl:text>\n        </xsl:when>\n        <!-- Experimental - just some file path/url -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$reveal-resources-host\"/>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:variable>\n\n<!-- ######################## -->\n<!-- Beamer Slideshow Options -->\n<!-- ######################## -->\n\n<!-- Beamer Theme -->\n\n<xsl:variable name=\"beamer-theme\">\n    <xsl:apply-templates select=\"$publisher-attribute-options/beamer/appearance/pi:pub-attribute[@name='theme']\" mode=\"set-pubfile-variable\"/>\n</xsl:variable>\n\n\n<!-- ########################################### -->\n<!-- Set Values/Defaults for Publisher Variables -->\n<!-- ########################################### -->\n\n<!-- The pi:publisher tree should mirror the official list of options   -->\n<!-- for publisher file attributes. Each pi:pub-attribute has a name.   -->\n<!-- The following attributes are optional.                             -->\n<!-- default: default string to use (should not contain spaces)         -->\n<!-- options: space-separated lits of options aside from the default    -->\n<!-- freeform: if 'yes' then pub attributee can be anything             -->\n<!-- stringparam: a stringparam that can override the pubfile entry     -->\n<!-- legacy-stringparam: a deprecated stringparam, last in chain        -->\n<!-- legacy-options: space separated list of retired options            -->\n\n<pi:publisher>\n    <common>\n        <pi:pub-attribute name=\"emdash-space\" default=\"none\" options=\"thin\" legacy-stringparam=\"emdash.space\"/>\n        <chunking>\n            <pi:pub-attribute name=\"level\" default=\"\" options=\"0 1 2 3 4 5 6\" stringparam=\"debug.chunk\" legacy-stringparam=\"chunk.level\"/>\n        </chunking>\n        <tableofcontents>\n            <pi:pub-attribute name=\"level\" options=\"0 1 2 3 4 5 6\" legacy-stringparam=\"toc.level\"/>\n        </tableofcontents>\n        <fillin>\n            <pi:pub-attribute name=\"textstyle\" default=\"underline\" options=\"box shade\"/>\n            <pi:pub-attribute name=\"mathstyle\" default=\"shade\" options=\"underline box\"/>\n        </fillin>\n        <qrcode>\n            <pi:pub-attribute name=\"image\" default=\"\" freeform=\"yes\"/>\n        </qrcode>\n        <mermaid>\n            <pi:pub-attribute name=\"theme\" default=\"default\" options=\"dark forest light\"/>\n            <pi:pub-attribute name=\"layout-engine\" default=\"dagre\" options=\"elk\"/>\n        </mermaid>\n        <journal>\n            <pi:pub-attribute name=\"name\" default=\"\" freeform=\"yes\"/>\n        </journal>\n        <!-- The default CSL style file is empty so that this  -->\n        <!-- feature can be \"opt in\", initially, and perhaps   -->\n        <!-- forever.  A good first choice for a CSL style is  -->\n        <!-- the \"harvard1\" style since it is copied into the  -->\n        <!-- right place in the citeproc-py distribution and   -->\n        <!-- should be present out-of-the-box.                 -->\n        <citation-stylesheet-language>\n            <pi:pub-attribute name=\"style\" default=\"\" freeform=\"yes\"/>\n        </citation-stylesheet-language>\n        <worksheet>\n            <pi:pub-attribute name=\"margin\" default=\"0.75in\" freeform=\"yes\"/>\n            <pi:pub-attribute name=\"top\" freeform=\"yes\"/>\n            <pi:pub-attribute name=\"right\" freeform=\"yes\"/>\n            <pi:pub-attribute name=\"bottom\" freeform=\"yes\"/>\n            <pi:pub-attribute name=\"left\" freeform=\"yes\"/>\n            <first-page-header>\n                <pi:pub-attribute name=\"left\" default=\"\" freeform=\"yes\"/>\n                <pi:pub-attribute name=\"center\" default=\"\" freeform=\"yes\"/>\n                <pi:pub-attribute name=\"right\" default=\"\" freeform=\"yes\"/>\n            </first-page-header>\n            <first-page-footer>\n                <pi:pub-attribute name=\"left\" default=\"\" freeform=\"yes\"/>\n                <pi:pub-attribute name=\"center\" default=\"\" freeform=\"yes\"/>\n                <pi:pub-attribute name=\"right\" default=\"\" freeform=\"yes\"/>\n            </first-page-footer>\n            <running-header>\n                <pi:pub-attribute name=\"left\" default=\"\" freeform=\"yes\"/>\n                <pi:pub-attribute name=\"center\" default=\"\" freeform=\"yes\"/>\n                <pi:pub-attribute name=\"right\" default=\"\" freeform=\"yes\"/>\n            </running-header>\n            <running-footer>\n                <pi:pub-attribute name=\"left\" default=\"\" freeform=\"yes\"/>\n                <pi:pub-attribute name=\"center\" default=\"\" freeform=\"yes\"/>\n                <pi:pub-attribute name=\"right\" default=\"\" freeform=\"yes\"/>\n            </running-footer>\n        </worksheet>\n    </common>\n    <html>\n        <pi:pub-attribute name=\"short-answer-responses\" default=\"graded\" options=\"always\"/>\n        <pi:pub-attribute name=\"read-aloud\" default=\"yes\" options=\"no\"/>\n        <pi:pub-attribute name=\"favicon\" default=\"none\" options=\"simple\"/>\n        <pi:pub-attribute name=\"embed-button\" default=\"no\" options=\"yes\"/>\n        <pi:pub-attribute name=\"design-width\" freeform=\"yes\"/>\n        <calculator>\n            <pi:pub-attribute name=\"model\" default=\"none\" options=\"geogebra-classic geogebra-graphing geogebra-geometry geogebra-3d\" legacy-stringparam=\"html.calculator\"/>\n        </calculator>\n        <annotation>\n            <pi:pub-attribute name=\"platform\" default=\"none\" options=\"hypothesis\" legacy-stringparam=\"html.annotation\"/>\n        </annotation>\n        <css>\n            <pi:pub-attribute name=\"palette\" freeform=\"yes\"/>\n        </css>\n        <resources>\n            <pi:pub-attribute name=\"host\" default=\"local\" options=\"cdn\"/>\n        </resources>\n        <knowl>\n            <pi:pub-attribute name=\"theorem\" default=\"no\" options=\"yes\" legacy-stringparam=\"html.knowl.theorem\"/>\n            <pi:pub-attribute name=\"proof\" default=\"yes\" options=\"no\" legacy-stringparam=\"html.knowl.proof\"/>\n            <pi:pub-attribute name=\"definition\" default=\"no\" options=\"yes\" legacy-stringparam=\"html.knowl.definition\"/>\n            <pi:pub-attribute name=\"example\" default=\"yes\" options=\"no\" legacy-stringparam=\"html.knowl.example\"/>\n            <pi:pub-attribute name=\"example-solution\" default=\"yes\" options=\"no\"/>\n            <pi:pub-attribute name=\"project\" default=\"no\" options=\"yes\" legacy-stringparam=\"html.knowl.project\"/>\n            <pi:pub-attribute name=\"task\" default=\"no\" options=\"yes\" legacy-stringparam=\"html.knowl.task\"/>\n            <pi:pub-attribute name=\"list\" default=\"no\" options=\"yes\" legacy-stringparam=\"html.knowl.list\"/>\n            <pi:pub-attribute name=\"remark\" default=\"no\" options=\"yes\" legacy-stringparam=\"html.knowl.remark\"/>\n            <pi:pub-attribute name=\"objectives\" default=\"no\" options=\"yes\" legacy-stringparam=\"html.knowl.objectives\"/>\n            <pi:pub-attribute name=\"outcomes\" default=\"no\" options=\"yes\" legacy-stringparam=\"html.knowl.outcomes\"/>\n            <pi:pub-attribute name=\"figure\" default=\"no\" options=\"yes\" legacy-stringparam=\"html.knowl.figure\"/>\n            <pi:pub-attribute name=\"table\" default=\"no\" options=\"yes\" legacy-stringparam=\"html.knowl.table\"/>\n            <pi:pub-attribute name=\"listing\" default=\"no\" options=\"yes\" legacy-stringparam=\"html.knowl.listing\"/>\n            <pi:pub-attribute name=\"exercise-inline\" default=\"yes\" options=\"no\" legacy-stringparam=\"html.knowl.exercise.inline\"/>\n            <pi:pub-attribute name=\"exercise-divisional\" default=\"no\" options=\"yes\" legacy-stringparam=\"html.knowl.exercise.sectional\"/>\n            <pi:pub-attribute name=\"exercise-worksheet\" default=\"no\" options=\"yes\" legacy-stringparam=\"html.knowl.exercise.worksheet\"/>\n            <pi:pub-attribute name=\"exercise-readingquestion\" default=\"no\" options=\"yes\" legacy-stringparam=\"html.knowl.exercise.readingquestion\"/>\n        </knowl>\n        <cross-references>\n            <pi:pub-attribute name=\"knowled\" default=\"maximum\" options=\"never cross-page\"/>\n        </cross-references>\n        <navigation>\n            <pi:pub-attribute name=\"logic\" default=\"linear\" options=\"tree\" legacy-stringparam=\"html.navigation.logic\"/>\n            <pi:pub-attribute name=\"upbutton\" default=\"yes\" options=\"no\" legacy-stringparam=\"html.navigation.logic\"/>\n        </navigation>\n        <tableofcontents>\n            <pi:pub-attribute name=\"focused\" default=\"no\" options=\"yes\"/>\n            <pi:pub-attribute name=\"preexpanded-levels\" default=\"0\" options=\"1 2 3 4 5 6\"/>\n        </tableofcontents>\n        <analytics>\n            <pi:pub-attribute name=\"google-gst\" freeform=\"yes\"/>\n        </analytics>\n        <banner>\n            <pi:pub-attribute name=\"byline\" default=\"yes\" options=\"no\"/>\n            <pi:pub-attribute name=\"subtitle\" default=\"yes\" options=\"no\"/>\n        </banner>\n        <video>\n            <pi:pub-attribute name=\"privacy\" default=\"yes\" options=\"no\"/>\n        </video>\n        <platform>\n            <pi:pub-attribute name=\"host\" default=\"web\" options=\"runestone\" legacy-options=\"aim\"/>\n            <pi:pub-attribute name=\"portable\" default=\"no\" options=\"yes\"/>\n        </platform>\n        <interactives>\n            <pi:pub-attribute name=\"resize-behavior\" default=\"fixed-height\" options=\"responsive\"/>\n            <calcplot3d>\n                <pi:pub-attribute name=\"resize-behavior\" default=\"fixed-height\" options=\"responsive\"/>\n            </calcplot3d>\n            <circuitjs>\n                <pi:pub-attribute name=\"resize-behavior\" default=\"fixed-height\" options=\"responsive\"/>\n            </circuitjs>\n            <d3>\n                <pi:pub-attribute name=\"resize-behavior\" default=\"fixed-height\" options=\"responsive\"/>\n            </d3>\n            <desmos>\n                <pi:pub-attribute name=\"resize-behavior\" default=\"fixed-height\" options=\"responsive\"/>\n            </desmos>\n            <doenetml>\n                <pi:pub-attribute name=\"resize-behavior\" default=\"fixed-height\" options=\"responsive\"/>\n            </doenetml>\n            <geogebra>\n                <pi:pub-attribute name=\"resize-behavior\" default=\"fixed-height\" options=\"responsive\"/>\n            </geogebra>\n            <iframe>\n                <pi:pub-attribute name=\"resize-behavior\" default=\"fixed-height\" options=\"responsive\"/>\n            </iframe>\n            <javascript>\n                <pi:pub-attribute name=\"resize-behavior\" default=\"fixed-height\" options=\"responsive\"/>\n            </javascript>\n            <jsxgraph>\n                <pi:pub-attribute name=\"resize-behavior\" default=\"fixed-height\" options=\"responsive\"/>\n            </jsxgraph>\n            <sage>\n                <pi:pub-attribute name=\"resize-behavior\" default=\"fixed-height\" options=\"responsive\"/>\n            </sage>\n        </interactives>\n    </html>\n    <epub>\n        <cover>\n            <pi:pub-attribute name=\"front\" freeform=\"yes\"/>\n        </cover>\n    </epub>\n    <jupyter>\n        <pi:pub-attribute name=\"kernel\" default=\"sagemath\" options=\"python3\" legacy-stringparam=\"jupyter.kernel\"/>\n    </jupyter>\n    <latex>\n        <pi:pub-attribute name=\"sides\" options=\"one two\" legacy-stringparam=\"latex.sides\"/>\n        <pi:pub-attribute name=\"print\" default=\"no\" options=\"yes\" legacy-stringparam=\"latex.print\"/>\n        <pi:pub-attribute name=\"snapshot\" default=\"no\" options=\"yes\"/>\n        <pi:pub-attribute name=\"pageref\" options=\"yes no\" legacy-stringparam=\"latex.pageref\"/>\n        <pi:pub-attribute name=\"draft\" default=\"no\" options=\"yes\" legacy-stringparam=\"latex.draft\"/>\n        <pi:pub-attribute name=\"open-odd\" default=\"no\" options=\"add-blanks skip-pages\"/>\n        <pi:pub-attribute name=\"latex-style\" default=\"\" options=\"AIM chaos CLP dyslexic-font guide texstyle\"/>\n        <pi:pub-attribute name=\"link-highlight\" default=\"none\" options=\"underline\"/>\n        <page>\n            <pi:pub-attribute name=\"bottom-alignment\" default=\"ragged\" options=\"flush\"/>\n        </page>\n        <worksheet>\n            <pi:pub-attribute name=\"formatted\" default=\"yes\" options=\"no\"/>\n        </worksheet>\n        <fonts>\n            <main>\n                <pi:pub-attribute name=\"regular\" default=\"\" freeform=\"yes\"/>\n                <pi:pub-attribute name=\"options\" default=\"\" freeform=\"yes\"/>\n            </main>\n            <math>\n                <pi:pub-attribute name=\"regular\" default=\"\" freeform=\"yes\"/>\n                <pi:pub-attribute name=\"options\" default=\"\" freeform=\"yes\"/>\n            </math>\n        </fonts>\n    </latex>\n    <webwork>\n        <pi:pub-attribute name=\"static-processing\" default=\"webwork2\" options=\"local\"/>\n        <pi:pub-attribute name=\"pg-location\" default=\"/opt/webwork/pg\" freeform=\"yes\"/>\n        <pi:pub-attribute name=\"server\" default=\"https://webwork-ptx.aimath.org\" freeform=\"yes\"/>\n        <pi:pub-attribute name=\"course\" default=\"anonymous\" freeform=\"yes\"/>\n        <pi:pub-attribute name=\"user\" default=\"anonymous\" freeform=\"yes\"/>\n        <pi:pub-attribute name=\"password\" default=\"anonymous\" freeform=\"yes\"/>\n        <pi:pub-attribute name=\"task-reveal\" default=\"all\" options=\"preceding-correct\"/>\n    </webwork>\n    <stack>\n        <pi:pub-attribute name=\"server\" default=\"https://stack-api.maths.ed.ac.uk\" freeform=\"yes\"/>\n    </stack>\n    <braille>\n        <page>\n            <pi:pub-attribute name=\"width\" default=\"40\" freeform=\"yes\"/>\n            <pi:pub-attribute name=\"height\" default=\"25\" freeform=\"yes\"/>\n        </page>\n    </braille>\n    <text>\n        <pi:pub-attribute name=\"characters\" default=\"unicode\" options=\"ascii\"/>\n    </text>\n    <revealjs>\n        <appearance>\n            <pi:pub-attribute name=\"theme\" default=\"simple\" freeform=\"yes\"/>\n            <pi:pub-attribute name=\"custom-css\" default=\"\" freeform=\"yes\"/>\n        </appearance>\n        <controls>\n            <pi:pub-attribute name=\"backarrows\" default=\"faded\" options=\"hidden visible\"/>\n            <pi:pub-attribute name=\"display\" default=\"yes\" options=\"no\"/>\n            <pi:pub-attribute name=\"layout\" default=\"bottom-right\" options=\"edges\"/>\n            <pi:pub-attribute name=\"tutorial\" default=\"yes\" options=\"no\"/>\n        </controls>\n        <navigation>\n            <pi:pub-attribute name=\"mode\" default=\"default\" options=\"linear grid\"/>\n        </navigation>\n        <!-- \"@host\" is also authored on \"resources\", but its values -->\n        <!-- are not an enumeration (an arbitrary path is legal), so -->\n        <!-- it is consulted directly by the \"reveal-root\" variable  -->\n        <resources>\n            <pi:pub-attribute name=\"math\" default=\"online\" options=\"embedded\"/>\n        </resources>\n    </revealjs>\n    <beamer>\n        <appearance>\n            <pi:pub-attribute name=\"theme\" default=\"Boadilla\" freeform=\"yes\"/>\n        </appearance>\n    </beamer>\n</pi:publisher>\n\n<!-- global variable for pi:publisher tree above -->\n<xsl:variable name=\"publisher-attribute-options\" select=\"document('')/xsl:stylesheet/pi:publisher\"/>\n\n<!-- context for a match below will be an attribute from the pi:publisher tree -->\n<xsl:template match=\"pi:pub-attribute\" mode=\"set-pubfile-variable\">\n    <xsl:variable name=\"all-options\" select=\"str:tokenize(concat(@default, ' ', @options), ' ')\"/>\n    <xsl:variable name=\"legacy-options\" select=\"str:tokenize(@legacy-options, ' ')\"/>\n    <!-- get the path to this attribute in the actual publisher file-->\n    <xsl:variable name=\"path\">\n        <xsl:apply-templates select=\".\" mode=\"pub-entry-path\"/>\n    </xsl:variable>\n    <!-- get the corresponding attribute from the publisher file -->\n    <!-- which may not exist                                     -->\n    <xsl:variable name=\"full-path\" select=\"concat('$publication/', $path)\"/>\n    <xsl:variable name=\"pubfile-attribute\" select=\"dyn:evaluate($full-path)\"/>\n    <!-- The default value, which may be specified or may vary conditionally -->\n    <!-- (via a custom template) appears frequently as the provided value    -->\n    <!-- when there is an error condition of some type, and is also echo'ed  -->\n    <!-- back to the publisher in those cases.  So we grab it once..         -->\n    <xsl:variable name=\"the-default\">\n        <xsl:apply-templates select=\".\" mode=\"get-default-pub-variable\"/>\n    </xsl:variable>\n    <xsl:choose>\n        <!-- if we respect a stringparam override and it is provided, use it -->\n        <xsl:when test=\"@stringparam and dyn:evaluate(concat('$', @stringparam)) != ''\">\n            <xsl:value-of select=\"dyn:evaluate(concat('$', @stringparam))\"/>\n        </xsl:when>\n        <!-- if nothing is declared in the publisher file, not even as null  -->\n        <!-- and if there is an old stringparam that we still honor, and if  -->\n        <!-- it is among the legal options, use it and issue warning         -->\n        <xsl:when test=\"not($pubfile-attribute) and @legacy-stringparam and (@freeform = 'yes' or dyn:evaluate(concat('$', @legacy-stringparam)) = $all-options)\">\n            <xsl:value-of select=\"dyn:evaluate(concat('$', @legacy-stringparam))\"/>\n            <xsl:message>PTX:DEPRECATE: the stringparam \"<xsl:value-of select=\"@legacy-stringparam\"/>\" is deprecated. Your value, \"<xsl:value-of select=\"dyn:evaluate(concat('$', @legacy-stringparam))\"/>\" will be used. However you should move to using a publisher file entry for  <xsl:value-of select=\"$full-path\"/>  instead.</xsl:message>\n        </xsl:when>\n        <!-- if nothing is declared in the publisher file, not even as null  -->\n        <!-- and if there is an old stringparam that we still honor, and if  -->\n        <!-- it is among the legacy options, use default and issue warning   -->\n        <xsl:when test=\"not($pubfile-attribute) and @legacy-stringparam and dyn:evaluate(concat('$', @legacy-stringparam)) = $legacy-options\">\n            <xsl:value-of select=\"$the-default\"/>\n            <xsl:message>PTX:DEPRECATE: the stringparam \"<xsl:value-of select=\"@legacy-stringparam\"/>\" is deprecated. Also your value, \"<xsl:value-of select=\"dyn:evaluate(concat('$', @legacy-stringparam))\"/>\" has been retired. You should move to using a publisher file entry  <xsl:value-of select=\"$full-path\"/>  with possible values: <xsl:apply-templates select=\"$all-options\" mode=\"quoted-list\"/>.  The default, \"<xsl:value-of select=\"$the-default\"/>\", will be used instead.</xsl:message>\n        </xsl:when>\n        <!-- if nothing is declared in the publisher file, not even as null  -->\n        <!-- and if there is an old stringparam that we still honor, but its -->\n        <!-- value isn't legal, legacy, or the default strinigparam '',      -->\n        <!-- then use default and issue warning                              -->\n        <xsl:when test=\"not($pubfile-attribute) and @legacy-stringparam and dyn:evaluate(concat('$', @legacy-stringparam)) != ''\">\n            <xsl:value-of select=\"$the-default\"/>\n            <xsl:message>PTX:DEPRECATE: the stringparam \"<xsl:value-of select=\"@legacy-stringparam\"/>\" is deprecated. Also your value, \"<xsl:value-of select=\"dyn:evaluate(concat('$', @legacy-stringparam))\"/>\" is not a legal option. You should move to using a publisher file entry  <xsl:value-of select=\"$full-path\"/>  with possible values: <xsl:apply-templates select=\"$all-options\" mode=\"quoted-list\"/>.  The default, \"<xsl:value-of select=\"$the-default\"/>\", will be used instead.</xsl:message>\n        </xsl:when>\n        <!-- if nothing is declared in the publisher file or it is declared  -->\n        <!-- as null, use the default, which might be null                   -->\n        <xsl:when test=\"string($pubfile-attribute) = ''\">\n            <xsl:value-of select=\"$the-default\"/>\n        </xsl:when>\n        <!-- if a non-empty string declared in the pubfile and if freeform   -->\n        <!-- is permitted, use whatever the pubfile entry was                -->\n        <xsl:when test=\"@freeform = 'yes'\">\n            <xsl:value-of select=\"$pubfile-attribute\"/>\n        </xsl:when>\n        <!-- now freeform not permittted; check if entry is among the legal  -->\n        <!-- options and if so, use it                                       -->\n        <xsl:when test=\"$pubfile-attribute = $all-options\">\n            <xsl:value-of select=\"$pubfile-attribute\"/>\n        </xsl:when>\n        <!-- if it's among the legacy options, use default and issue warning  -->\n        <xsl:when test=\"$pubfile-attribute = $legacy-options\">\n            <xsl:value-of select=\"$the-default\"/>\n            <xsl:message>PTX:FALLBACK: your value \"<xsl:value-of select=\"$pubfile-attribute\"/>\"  for the publisher file entry  <xsl:value-of select=\"$path\"/>  has been retired; possible values are <xsl:apply-templates select=\"$all-options\" mode=\"quoted-list\"/>. The default, \"<xsl:value-of select=\"$the-default\"/>\", will be used instead.</xsl:message>\n        </xsl:when>\n        <!-- pubfile has some string that is not among legal options, and    -->\n        <!-- freeform is disallowed, so give a warning and use default       -->\n        <xsl:otherwise>\n            <xsl:value-of select=\"$the-default\"/>\n            <xsl:message>PTX:FALLBACK: the publisher file  <xsl:value-of select=\"$path\"/>  entry should not have value \"<xsl:value-of select=\"$pubfile-attribute\"/>\".  Possible values are: <xsl:apply-templates select=\"$all-options\" mode=\"quoted-list\"/>.  The default, \"<xsl:value-of select=\"$the-default\"/>\", will be used instead.</xsl:message>\n        </xsl:otherwise>\n    </xsl:choose>\n</xsl:template>\n\n<!-- can be overrided when the default is dynamic -->\n<xsl:template match=\"pi:pub-attribute\" mode=\"get-default-pub-variable\">\n    <xsl:value-of select=\"@default\"/>\n</xsl:template>\n\n<!-- Recurse back up the tree to get the path to an attribute -->\n<xsl:template match=\"pi:pub-attribute\" mode=\"pub-entry-path\">\n    <xsl:apply-templates select=\"..\" mode=\"pub-entry-path\"/>\n    <xsl:value-of select=\"concat('@', @name)\"/>\n</xsl:template>\n\n<xsl:template match=\"*\" mode=\"pub-entry-path\">\n    <xsl:apply-templates select=\"..\" mode=\"pub-entry-path\"/>\n    <xsl:value-of select=\"concat(local-name(), '/')\"/>\n</xsl:template>\n\n<xsl:template match=\"pi:publisher\" mode=\"pub-entry-path\"/>\n\n<!-- Expects a node set from tokenize()                       -->\n<!-- Produces a string where each token is wrapped in quotes  -->\n<!-- When there are multiple options, separates with a comma  -->\n<!-- Last options preceded by \"or\" with Oxford comma if 3+    -->\n<xsl:template match=\"token\" mode=\"quoted-list\">\n    <xsl:text>\"</xsl:text>\n    <xsl:value-of select=\".\"/>\n    <xsl:text>\"</xsl:text>\n    <xsl:choose>\n        <!-- if there are at least two more coming -->\n        <xsl:when test=\"count(following-sibling::token) &gt;= 2\">\n            <xsl:text>, </xsl:text>\n        </xsl:when>\n        <!-- if there is exactly one more coming and we have a list of at least three -->\n        <xsl:when test=\"preceding-sibling::token and following-sibling::token\">\n            <xsl:text>, or </xsl:text>\n        </xsl:when>\n        <!-- if there is exactly one more coming and we have a list of two -->\n        <xsl:when test=\"following-sibling::token\">\n            <xsl:text> or </xsl:text>\n        </xsl:when>\n    </xsl:choose>\n</xsl:template>\n\n\n<!-- ######################### -->\n<!-- String Parameter Bad Bank -->\n<!-- ######################### -->\n\n<!-- 2022-12-26: this list of deprecated, retired, obsolete (string)  -->\n<!-- parameters has evolved over time and the comments are a bit      -->\n<!-- haphazard.  The primary motivation for keeping (most of) these   -->\n<!-- is to allow deprecation warnings to flag (and often react        -->\n<!-- favorably) to attempted uses. Dated, and in chronological        -->\n<!-- order.  Grep, or the git pickaxe (log -S) using the date strings -->\n <!-- is often effective in locating all the pieces of a deprecation. -->\n\n<!-- Conversion specific parameters that die will   -->\n<!-- live on in warnings, which are isolated in the -->\n<!-- pretext-common stylesheet.  So we need to      -->\n<!-- declare them here for use in the warnings      -->\n\n<!-- Some string parameters have been deprecated without any      -->\n<!-- sort of replacement, fallback, or upgrade.  But for a        -->\n<!-- deprecation message to be effective, they need to exist.     -->\n<!-- If you add something here, make a note by the deprecation    -->\n<!-- message.  These definitions expain why it is *always* best   -->\n<!-- to define a user variable as empty, and then supply defaults -->\n<!-- to an internal variable.                                     -->\n\n<!-- HTML-specific deprecated 2015-06, but still functional -->\n<xsl:param name=\"html.chunk.level\" select=\"''\" />\n\n<!-- DEPRECATED: 2017-12-18, do not use, any value -->\n<!-- besides an empty string will raise a warning  -->\n<xsl:param name=\"latex.console.macro-char\" select=\"''\" />\n<xsl:param name=\"latex.console.begin-char\" select=\"''\" />\n<xsl:param name=\"latex.console.end-char\" select=\"''\" />\n\n<!-- html.knowl.sidebyside is deprecated 2017-07  -->\n<!-- null value necessary for deprecation message -->\n<xsl:param name=\"html.knowl.sidebyside\" select=\"''\" />\n\n<!-- Analytics deprecated 2019-11-28               -->\n<!-- null values necessary for deprecation message -->\n<xsl:param name=\"html.statcounter.project\" select=\"''\"/>\n<xsl:param name=\"html.statcounter.security\" select=\"''\"/>\n<xsl:param name=\"html.google-classic\" select=\"''\"/>\n<xsl:param name=\"html.google-universal\" select=\"''\"/>\n\n<!-- Google search via string parameter deprecated 2019-11-29 -->\n<xsl:param name=\"html.google-search\" select=\"''\"/>\n\n<!-- DEPRECATED: 2020-05-29  In favor of       -->\n<!-- html/calculator/@model  in publisher file -->\n<xsl:param name=\"html.calculator\" select=\"''\" />\n\n<!-- The old (incomplete) methods for duplicating components of -->\n<!-- exercises have been deprecated as of 2018-11-07.  We keep  -->\n<!-- these here as we have tried to preserve their intent, and  -->\n<!-- we are generating warnings if they are ever set.           -->\n<!-- 2020-08-31 exercise.backmatter.* only remain for warnings  -->\n<xsl:param name=\"exercise.text.statement\" select=\"''\" />\n<xsl:param name=\"exercise.text.hint\" select=\"''\" />\n<xsl:param name=\"exercise.text.answer\" select=\"''\" />\n<xsl:param name=\"exercise.text.solution\" select=\"''\" />\n<xsl:param name=\"project.text.hint\" select=\"''\" />\n<xsl:param name=\"project.text.answer\" select=\"''\" />\n<xsl:param name=\"project.text.solution\" select=\"''\" />\n<xsl:param name=\"task.text.hint\" select=\"''\" />\n<xsl:param name=\"task.text.answer\" select=\"''\" />\n<xsl:param name=\"task.text.solution\" select=\"''\" />\n<xsl:param name=\"exercise.backmatter.statement\" select=\"''\" />\n<xsl:param name=\"exercise.backmatter.hint\" select=\"''\" />\n<xsl:param name=\"exercise.backmatter.answer\" select=\"''\" />\n<xsl:param name=\"exercise.backmatter.solution\" select=\"''\" />\n\n<!-- The dashed version is deprecated 2019-02-10,      -->\n<!-- but we still recognize it.  Move to variable bad  -->\n<!-- bank once killed.                                 -->\n<xsl:param name=\"author-tools\" select=\"''\" />\n\n<!-- The autoname parameter is deprecated (2017-07-25) -->\n<!-- Replace with docinfo/defaults/xrefs/@text         -->\n<xsl:param name=\"autoname\" select=\"''\" />\n\n<!-- 2020-11-22: latex.print to publisher file -->\n<xsl:param name=\"latex.print\" select=\"''\"/>\n<!-- 2020-11-22 sidedness to publisher file -->\n<xsl:param name=\"latex.sides\" select=\"''\"/>\n\n<!-- Replaced by more specific versions, 2019-02-10     -->\n<!-- These are variables, but still react when supplied -->\n<!-- to xsltproc/lxml as command-line arguments         -->\n<xsl:variable name=\"html.css.file\" select=\"''\"/>\n<xsl:variable name=\"html.permalink\" select=\"''\"/>\n\n<!-- RETIRED: 2020-11-22 Not a deprecation, this is a string parameter that             -->\n<!-- was never used at all.  Probably no real harm in parking it here for now.          -->\n<!-- N.B. This has no effect, and may never.  xelatex and lualatex support is automatic -->\n<xsl:param name=\"latex.engine\" select=\"'pdflatex'\" />\n\n<!-- RETIRED: 2020-11-23 this parameter was never used, now    -->\n<!-- silently moved here, which should make no real difference -->\n<xsl:param name=\"directory.media\"  select=\"''\" />\n\n<!-- RETIRED: 2020-11-23 this parameter was never used, now    -->\n<!-- silently moved here, which should make no real difference -->\n<xsl:param name=\"directory.knowls\"  select=\"''\" />\n\n<!-- Deprecated 2020-11-23 in favor of publisher file  -->\n<!-- specification; as of 2026-08-02 managed           -->\n<!-- directories are the only scheme, so this is dead: -->\n<!-- it survives only to power a deprecation warning.  -->\n<xsl:param name=\"directory.images\" select=\"''\" />\n\n<!-- 2021-01-03 chunk.level to publisher file -->\n<xsl:param name=\"chunk.level\" select=\"''\" />\n<!-- 2021-01-03 toc.level to publisher file -->\n<xsl:param name=\"toc.level\" select=\"''\" />\n<!-- 2026-07-10 jupyter.kernel to publisher file -->\n<xsl:param name=\"jupyter.kernel\" select=\"''\" />\n\n<!-- Deprecated 2021-01-23, but still respected -->\n<xsl:param name=\"html.knowl.theorem\" select=\"''\" />\n<xsl:param name=\"html.knowl.proof\" select=\"''\" />\n<xsl:param name=\"html.knowl.definition\" select=\"''\" />\n<xsl:param name=\"html.knowl.example\" select=\"''\" />\n<xsl:param name=\"html.knowl.project\" select=\"''\" />\n<xsl:param name=\"html.knowl.task\" select=\"''\" />\n<xsl:param name=\"html.knowl.list\" select=\"''\" />\n<xsl:param name=\"html.knowl.remark\" select=\"''\" />\n<xsl:param name=\"html.knowl.objectives\" select=\"''\" />\n<xsl:param name=\"html.knowl.outcomes\" select=\"''\" />\n<xsl:param name=\"html.knowl.figure\" select=\"''\" />\n<xsl:param name=\"html.knowl.table\" select=\"''\" />\n<xsl:param name=\"html.knowl.listing\" select=\"''\" />\n<xsl:param name=\"html.knowl.exercise.inline\" select=\"''\" />\n<xsl:param name=\"html.knowl.exercise.sectional\" select=\"''\" />\n<xsl:param name=\"html.knowl.exercise.worksheet\" select=\"''\" />\n<xsl:param name=\"html.knowl.exercise.readingquestion\" select=\"''\" />\n\n<!-- Deprecated 2021-02-14 but still respected -->\n<!-- maxlevel -> divisions.level, theorems.level -> blocks.level -->\n<xsl:param name=\"numbering.theorems.level\" select=\"''\" />\n<xsl:param name=\"numbering.projects.level\" select=\"''\" />\n<xsl:param name=\"numbering.equations.level\" select=\"''\" />\n<xsl:param name=\"numbering.footnotes.level\" select=\"''\" />\n<xsl:param name=\"numbering.maximum.level\" select=\"''\" />\n\n<!-- Deprecated 2021-02-14, now ignored, but warning exists -->\n<xsl:param name=\"debug.chapter.start\" select=\"''\" />\n\n<!-- Deprecated 2021-11-04, but respected by LaTeX publisher -->\n<!-- switch for right alignment of page's text               -->\n<xsl:param name=\"text.alignment\" select=\"''\" />\n\n<!-- String parameters were the *second* wave of these        -->\n<!-- switches, see variables below.  Deprecated on 2022-01-31 -->\n<!-- when they migrated to the publication file.              -->\n\n<xsl:param name=\"exercise.inline.statement\" select=\"''\" />\n<xsl:param name=\"exercise.inline.hint\" select=\"''\" />\n<xsl:param name=\"exercise.inline.answer\" select=\"''\" />\n<xsl:param name=\"exercise.inline.solution\" select=\"''\" />\n<xsl:param name=\"exercise.divisional.statement\" select=\"''\" />\n<xsl:param name=\"exercise.divisional.hint\" select=\"''\" />\n<xsl:param name=\"exercise.divisional.answer\" select=\"''\" />\n<xsl:param name=\"exercise.divisional.solution\" select=\"''\" />\n<xsl:param name=\"exercise.worksheet.statement\" select=\"''\" />\n<xsl:param name=\"exercise.worksheet.hint\" select=\"''\" />\n<xsl:param name=\"exercise.worksheet.answer\" select=\"''\" />\n<xsl:param name=\"exercise.worksheet.solution\" select=\"''\" />\n<xsl:param name=\"exercise.reading.statement\" select=\"''\" />\n<xsl:param name=\"exercise.reading.hint\" select=\"''\" />\n<xsl:param name=\"exercise.reading.answer\" select=\"''\" />\n<xsl:param name=\"exercise.reading.solution\" select=\"''\" />\n<xsl:param name=\"project.statement\" select=\"''\" />\n<xsl:param name=\"project.hint\" select=\"''\" />\n<xsl:param name=\"project.answer\" select=\"''\" />\n<xsl:param name=\"project.solution\" select=\"''\" />\n\n<!-- On 2021-03-03 abandoned a \"fast-id\" scheme that was never -->\n<!-- really used since it was in-effect a developer testing    -->\n<!-- option. Then on 2022-05-23 removed code, strengthened     -->\n<!-- deprecation message, and moved parameter here.            -->\n<xsl:param name=\"oldids\" select=\"''\"/>\n\n<!-- Deprecated on 2022-10-24.  Definition has changed from  -->\n<!-- a default value of \"10pt\" to an empty string, so we can -->\n<!-- detect use for a deprecation warning.  Default value is -->\n<!-- preserved in other ways as part of the deprecation.     -->\n<xsl:param name=\"latex.font.size\" select=\"''\" />\n\n<!-- Geometry: page shape, margins, etc. Deprecated    -->\n<!--2022-10-24, non-empty triggers deprecation warning -->\n<xsl:param name=\"latex.geometry\" select=\"''\"/>\n\n<!-- Page Numbers in cross-references, deprecated 2022-10-24 -->\n<xsl:param name=\"latex.pageref\" select=\"''\"/>\n\n<!-- Electing LaTeX draft mode, deprecated 2022-10-24 -->\n<xsl:param name=\"latex.draft\" select=\"''\"/>\n\n<!-- These first two are deprecated in favor of watermark.text  -->\n<!-- and watermark.scale, which in turn are deprecated in favor -->\n<!-- of publication file entry.  Double deprecation, second one -->\n<!-- on 2022-10-24.                                             -->\n<xsl:param name=\"latex.watermark\" select=\"''\"/>\n<xsl:param name=\"latex.watermark.scale\" select=\"''\"/>\n<xsl:param name=\"watermark.text\" select=\"''\" />\n<xsl:param name=\"watermark.scale\" select=\"''\" />\n\n<!-- These were yes/no string parameters.  We converted to values -->\n<!-- of \"static\" or \"dynamic\" as publisher entries on 2022-11-19. -->\n<xsl:param name=\"webwork.inline.static\" select=\"''\" />\n<xsl:param name=\"webwork.divisional.static\" select=\"''\" />\n<xsl:param name=\"webwork.reading.static\" select=\"''\" />\n<xsl:param name=\"webwork.worksheet.static\" select=\"''\" />\n<xsl:param name=\"webwork.project.static\" select=\"''\" />\n\n<!-- Navigation options move to the publisher file on 2022-11-20. -->\n<xsl:param name=\"html.navigation.logic\"  select=\"''\"/>\n<xsl:param name=\"html.navigation.upbutton\"  select=\"''\"/>\n<xsl:param name=\"html.navigation.style\"  select=\"''\"/>\n\n<!-- Publisher option to surround emdash, deprecated 2022-11-20 -->\n<xsl:param name=\"emdash.space\" select=\"''\" />\n\n<!-- \"commentary\" element relegated to version support, so string    -->\n<!-- parameter is deprecated and ineffective, deprecated 2024-02-16. -->\n<xsl:param name=\"commentary\" select=\"''\" />\n\n<!-- Deprecated 2026-06-07, and now ignored -->\n<xsl:param name=\"debug.project.number\" select=\"''\" />\n\n<!-- DEPRECATED: 2026-07-25  In favor of          -->\n<!-- html/annotation/@platform  in publisher file -->\n<xsl:param name=\"html.annotation\" select=\"''\" />\n\n<!-- ###################################### -->\n<!-- Parameter Deprecation Warning Messages -->\n<!-- ###################################### -->\n\n<!-- Pass in a condition, true is a problem.       -->\n<!-- A message string like \"'foo'\" cannot contain  -->\n<!-- a single quote, even if entered as &apos;.    -->\n<!-- If despearate, concatentate with $apos.       -->\n<!-- A &#xa; can be used if necessary, but only    -->\n<!-- rarely do we bother.                          -->\n<xsl:template name=\"parameter-deprecation-message\">\n    <xsl:param name=\"incorrect-use\" select=\"false()\" />\n    <xsl:param name=\"date-string\" />\n    <xsl:param name=\"message\" />\n    <xsl:if test=\"$incorrect-use\">\n        <xsl:message>\n            <xsl:text>PTX:DEPRECATE: (</xsl:text>\n            <xsl:value-of select=\"$date-string\" />\n            <xsl:text>) </xsl:text>\n            <xsl:value-of select=\"$message\" />\n            <!-- once verbosity is implemented -->\n            <!-- <xsl:text>, set log.level to see more details</xsl:text> -->\n        </xsl:message>\n        <xsl:message>\n            <xsl:text>--------------</xsl:text>\n        </xsl:message>\n    </xsl:if>\n</xsl:template>\n\n<!-- 2023-01-11: These warnings are originally about string parameters -->\n<!-- moving to the publisher file.  But they seem to work just as well -->\n<!-- when an option in the publisher file changes.  So \"parameter\" is  -->\n<!-- the nomenclature, but usage is a bit more broad.                  -->\n\n<xsl:template match=\"mathbook|pretext\" mode=\"parameter-deprecation-warnings\">\n    <!-- These apparent re-definitions are local to this template -->\n    <!-- Reasons are historical, so to be a convenience           -->\n    <xsl:variable name=\"docinfo\" select=\"./docinfo\"/>\n    <xsl:variable name=\"document-root\" select=\"./*[not(self::docinfo)]\"/>\n\n\n    <!-- 2017-07-05  sidebyside cannot be cross-referenced anymore, so not knowlizable -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2017-07-05'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.knowl.sidebyside  parameter is now obsolete and will be ignored'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.knowl.sidebyside != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2015-06-26  chunking became a general thing -->\n    <!-- 2021-01-03  rendered ineffective            -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2015-06-26'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.chunk.level  parameter has been replaced by the common/chunking/@level  entry in the publisher file.  It will be ignored.  Please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.chunk.level != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2017-07-25  deprecate intentional autoname without new setting -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2017-07-25'\" />\n        <xsl:with-param name=\"message\" select=\"'the  autoname  parameter is deprecated, but is still effective since  &quot;docinfo/defaults/xrefs/@text&quot;  has not been set.  The following parameter values equate to the attribute values: &quot;no&quot; is &quot;global&quot;, &quot;yes&quot; is &quot;type-global&quot;, &quot;title&quot; is &quot;title&quot;'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"not($autoname = '') and not(//docinfo/cross-references | //docinfo/defaults/xrefs)\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2017-07-25  deprecate intentional autoname also with new setting -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2017-07-25'\" />\n        <xsl:with-param name=\"message\" select=\"'the  autoname  parameter is deprecated, and is being overidden by a  &quot;docinfo/defaults/xrefs/@text&quot;  and so is totally ineffective and can be removed'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"not($autoname = '') and (//docinfo/cross-references | //docinfo/defaults/xrefs)\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2017-12-18  deprecate three console macro characters -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2017-12-18'\" />\n        <xsl:with-param name=\"message\" select=\"'the  latex.console.macro-char  parameter is deprecated, and there is no longer a need to be careful about the backslash (\\) character in a console'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"not($latex.console.macro-char = '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2017-12-18'\" />\n        <xsl:with-param name=\"message\" select=\"'the  latex.console.begin-char  parameter is deprecated, and there is no longer a need to be careful about the begin group ({) character in a console'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"not($latex.console.begin-char = '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2017-12-18'\" />\n        <xsl:with-param name=\"message\" select=\"'the  latex.console.end-char  parameter is deprecated, and there is no longer a need to be careful about the end group (}) character in a console'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"not($latex.console.end-char = '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2018-11-07  obsolete exercise component switches          -->\n    <!-- Still exists in \"String Parameter Bad Bank\" for use here  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2018-11-07'\" />\n        <xsl:with-param name=\"message\" select=\"'the  *.text.*  parameters that control the visibility of components of exercises and projects have been removed and replaced by a greater variety of  exercise.*.*  and  project.*  parameters'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"not(($exercise.text.statement = '') and ($exercise.text.hint = '') and ($exercise.text.answer = '') and ($exercise.text.solution = '') and ($project.text.hint = '') and ($project.text.answer = '') and ($project.text.solution = '') and ($task.text.hint = '') and ($task.text.answer = '') and ($task.text.solution = ''))\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2018-11-07  obsolete backmatter exercise component switches -->\n    <!-- Still exists in \"String Parameter Bad Bank\" for use here    -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2018-11-07'\" />\n        <xsl:with-param name=\"message\" select=\"'the  exercise.backmatter.*  parameters that control the visibility of components of exercises and projects in the back matter have been removed and replaced by the &quot;solutions&quot; element, which is much more versatile'\"/>\n            <xsl:with-param name=\"incorrect-use\" select=\"not(($exercise.backmatter.statement = '') and ($exercise.backmatter.hint = '') and ($exercise.backmatter.answer = '') and ($exercise.backmatter.solution = ''))\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-10  obsolete  html.css.file  removed             -->\n    <!-- Still exists in \"String Parameter Bad Bank\" for use here -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-10'\" />\n        <xsl:with-param name=\"message\" select=\"'the obsolete  html.css.file  parameter has been removed, please use html.css.colorfile to choose a color scheme'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"($html.css.file != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-02-20  replace author-tools with author.tools                       -->\n    <!-- Still exists and is respected, move to \"String Parameter Bad Bank\" later -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2019-02-20'\" />\n        <xsl:with-param name=\"message\" select=\"'the  author-tools  parameter has been replaced by the functionally equivalent  author.tools'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"not($author-tools = '')\"/>\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-03-07  replace latex.watermark with watermark.text                  -->\n    <!-- 2022-10-24  update - to publication file                                 -->\n    <!-- Still exists and is respected, move to \"String Parameter Bad Bank\" later -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2019-03-07'\" />\n        <xsl:with-param name=\"message\" select=\"'the  latex.watermark  string parameter has been replaced by a publication file entry which is effective in HTML as well as LaTeX'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"($latex.watermark != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-03-07  replace latex.watermark.scale with watermark.scale           -->\n    <!-- 2022-10-24  update - to publication file                                 -->\n    <!-- Still exists and is respected, move to \"String Parameter Bad Bank\" later -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2019-03-07'\" />\n        <xsl:with-param name=\"message\" select=\"'the  latex.watermark.scale  string parameter has been replaced by a publication file entry which is effective in HTML as well as LaTeX'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"($latex.watermark.scale != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- And switches for analytics  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2019-11-28'\" />\n        <xsl:with-param name=\"message\" select=\"'use of string parameters for analytics configuration has been deprecated.  Existing switches are being respected, but please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.&#xa;  * For StatCounter this is a cosmetic change.&#xa;  * Google Classic has been deprecated by Google and will not be supported.&#xa;  * Google Universal has been replaced, your ID may continue to work.&#xa;  * Google Global Site Tag is fully supported, try your Universal ID.&#xa;'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"($html.statcounter.project != '') or ($html.statcounter.security != '') or ($html.google-classic != '') or ($html.google-universal != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2019-11-29  deprecated Google search via string parameter -->\n    <!-- see 2019-04-14 for docinfo deprecation                    -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2019-11-29'\" />\n        <xsl:with-param name=\"message\" select=\"'Google search is no longer specified with a string parameter.  Please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"$html.google-search != ''\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2020-05-10  permalinks (their style actually) are now controlled by Javascript -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2020-05-10'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.permalink  parameter is now obsolete and will be ignored as this is now controlled by Javascript'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.permalink != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2020-05-29  HTML calculator model controlled by publisher file -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2020-05-29'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.calculator  parameter has been replaced by the  html/calculator/@model  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.calculator != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2020-11-22  LaTeX print option controlled by publisher file -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2020-11-22'\" />\n        <xsl:with-param name=\"message\" select=\"'the  latex.print  parameter has been replaced by the  latex/@print  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($latex.print != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2020-11-22  LaTeX sideness option controlled by publisher file -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2020-11-22'\" />\n        <xsl:with-param name=\"message\" select=\"'the  latex.sides  parameter has been replaced by the  latex/@sides  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($latex.sides != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2021-01-03  chunk.level now in publisher file -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-01-03'\" />\n        <xsl:with-param name=\"message\" select=\"'the  chunk.level  parameter has been replaced by the  common/chunking/@level  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($chunk.level != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2021-01-03  toc.level now in publisher file -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-01-03'\"/>\n        <xsl:with-param name=\"message\" select=\"'the  toc.level  parameter has been replaced by the  common/tableofcontents/@level  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($toc.level != '')\" />\n    </xsl:call-template>\n    <!-- 2020-11-23  directory.images replaced by publisher file specification -->\n    <!-- Reverse this soon, hot fix -->\n    <!--\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2020-11-23'\" />\n        <xsl:with-param name=\"message\" select=\"'the  directory.images  parameter has been replaced by specification of two directories in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($directory.images != '')\" />\n    </xsl:call-template>\n -->\n    <!--  -->\n    <!--                                                  -->\n    <!-- 2021-01-23  Seventeen old knowl-ization switches -->\n    <!--                                                  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-01-23'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.knowl.theorem  parameter has been replaced by the  html/knowl/@theorem  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.knowl.theorem != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-01-23'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.knowl.proof  parameter has been replaced by the  html/knowl/@proof  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.knowl.proof != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-01-23'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.knowl.definition  parameter has been replaced by the  html/knowl/@definition  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.knowl.definition != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-01-23'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.knowl.example  parameter has been replaced by the  html/knowl/@example  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.knowl.example != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-01-23'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.knowl.project  parameter has been replaced by the  html/knowl/@project  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.knowl.project != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-01-23'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.knowl.task  parameter has been replaced by the  html/knowl/@task  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.knowl.task != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-01-23'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.knowl.list  parameter has been replaced by the  html/knowl/@list  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.knowl.list != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-01-23'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.knowl.remark  parameter has been replaced by the  html/knowl/@remark  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.knowl.remark != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-01-23'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.knowl.objectives  parameter has been replaced by the  html/knowl/@objectives  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.knowl.objectives != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-01-23'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.knowl.outcomes  parameter has been replaced by the  html/knowl/@outcomes  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.knowl.outcomes != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-01-23'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.knowl.figure  parameter has been replaced by the  html/knowl/@figure  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.knowl.figure != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-01-23'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.knowl.table  parameter has been replaced by the  html/knowl/@table  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.knowl.table != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-01-23'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.knowl.listing  parameter has been replaced by the  html/knowl/@listing  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.knowl.listing != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-01-23'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.knowl.exercise.inline  parameter has been replaced by the  html/knowl/@exercise-inline  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.knowl.exercise.inline != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-01-23'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.knowl.exercise.sectional  parameter has been replaced by the  html/knowl/@exercise-divisional  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.knowl.exercise.sectional != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-01-23'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.knowl.exercise.worksheet  parameter has been replaced by the  html/knowl/@exercise-worksheet  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.knowl.exercise.worksheet != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-01-23'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.knowl.exercise.readingquestion  parameter has been replaced by the  html/knowl/@exercise-readingquestion  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.knowl.exercise.readingquestion != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2014-02-14 Five parameters for numbering level to publisher file -->\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-02-14'\" />\n        <xsl:with-param name=\"message\" select=\"'the  numbering.maximum.level  parameter has been replaced by the  numbering/divisions/@level  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($numbering.maximum.level != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-02-14'\" />\n        <xsl:with-param name=\"message\" select=\"'the  numbering.theorems.level  parameter has been replaced by the  numbering/blocks/@level  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($numbering.theorems.level != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-02-14'\" />\n        <xsl:with-param name=\"message\" select=\"'the  numbering.projects.level  parameter has been replaced by the  numbering/projects/@level  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($numbering.projects.level != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-02-14'\" />\n        <xsl:with-param name=\"message\" select=\"'the  numbering.equations.level  parameter has been replaced by the  numbering/equations/@level  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($numbering.equations.level != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-02-14'\" />\n        <xsl:with-param name=\"message\" select=\"'the  numbering.footnotes.level  parameter has been replaced by the  numbering/footnotes/@level  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($numbering.footnotes.level != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-02-14'\" />\n        <xsl:with-param name=\"message\" select=\"'the  debug.chapter.start  parameter has been removed entirely and so will be ignored.  Please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($debug.chapter.start != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2021-11-04'\" />\n        <xsl:with-param name=\"message\" select=\"'the  text.alignment  parameter has been deprecated, but we will attempt to honor your intent.  Please switch to using the Publishers File for configuration of LaTeX page shape, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($text.alignment != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-01-31  exercise component visibility setting 1/20 -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-01-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the  exercise.inline.statement  string parameter is now deprecated, but we will attempt to honor your intent.  Please switch to using the Publication File, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($exercise.inline.statement != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-01-31  exercise component visibility setting 2/20 -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-01-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the  exercise.inline.hint  string parameter is now deprecated, but we will attempt to honor your intent.  Please switch to using the Publication File, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($exercise.inline.hint != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-01-31  exercise component visibility setting 3/20 -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-01-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the  exercise.inline.answer  string parameter is now deprecated, but we will attempt to honor your intent.  Please switch to using the Publication File, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($exercise.inline.answer != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-01-31  exercise component visibility setting 4/20 -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-01-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the  exercise.inline.solution  string parameter is now deprecated, but we will attempt to honor your intent.  Please switch to using the Publication File, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($exercise.inline.solution != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-01-31  exercise component visibility setting 5/20 -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-01-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the  exercise.divisional.statement  string parameter is now deprecated, but we will attempt to honor your intent.  Please switch to using the Publication File, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($exercise.divisional.statement != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-01-31  exercise component visibility setting 6/20 -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-01-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the  exercise.divisional.hint  string parameter is now deprecated, but we will attempt to honor your intent.  Please switch to using the Publication File, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($exercise.divisional.hint != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-01-31  exercise component visibility setting 7/20 -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-01-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the  exercise.divisional.answer  string parameter is now deprecated, but we will attempt to honor your intent.  Please switch to using the Publication File, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($exercise.divisional.answer != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-01-31  exercise component visibility setting 8/20 -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-01-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the  exercise.divisional.solution  string parameter is now deprecated, but we will attempt to honor your intent.  Please switch to using the Publication File, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($exercise.divisional.solution != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-01-31  exercise component visibility setting 9/20 -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-01-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the  exercise.worksheet.statement  string parameter is now deprecated, but we will attempt to honor your intent.  Please switch to using the Publication File, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($exercise.worksheet.statement != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-01-31  exercise component visibility setting 10/20 -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-01-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the  exercise.worksheet.hint  string parameter is now deprecated, but we will attempt to honor your intent.  Please switch to using the Publication File, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($exercise.worksheet.hint != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-01-31  exercise component visibility setting 11/20 -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-01-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the  exercise.worksheet.answer  string parameter is now deprecated, but we will attempt to honor your intent.  Please switch to using the Publication File, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($exercise.worksheet.answer != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-01-31  exercise component visibility setting 12/20 -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-01-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the  exercise.worksheet.solution  string parameter is now deprecated, but we will attempt to honor your intent.  Please switch to using the Publication File, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($exercise.worksheet.solution != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-01-31  exercise component visibility setting 13/20 -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-01-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the  exercise.reading.statement  string parameter is now deprecated, but we will attempt to honor your intent.  Please switch to using the Publication File, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($exercise.reading.statement != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-01-31  exercise component visibility setting 14/20 -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-01-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the  exercise.reading.hint  string parameter is now deprecated, but we will attempt to honor your intent.  Please switch to using the Publication File, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($exercise.reading.hint != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-01-31  exercise component visibility setting 15/20 -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-01-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the  exercise.reading.answer  string parameter is now deprecated, but we will attempt to honor your intent.  Please switch to using the Publication File, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($exercise.reading.answer != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-01-31  exercise component visibility setting 16/20 -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-01-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the  exercise.reading.solution  string parameter is now deprecated, but we will attempt to honor your intent.  Please switch to using the Publication File, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($exercise.reading.solution != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-01-31  exercise component visibility setting 17/20 -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-01-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the  project.statement  string parameter is now deprecated, but we will attempt to honor your intent.  Please switch to using the Publication File, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($project.statement != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-01-31  exercise component visibility setting 18/20 -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-01-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the  project.hint  string parameter is now deprecated, but we will attempt to honor your intent.  Please switch to using the Publication File, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($project.hint != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-01-31  exercise component visibility setting 19/20 -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-01-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the  project.answer  string parameter is now deprecated, but we will attempt to honor your intent.  Please switch to using the Publication File, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($project.answer != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-01-31  exercise component visibility setting 20/20 -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-01-31'\" />\n        <xsl:with-param name=\"message\" select=\"'the  project.solution  string parameter is now deprecated, but we will attempt to honor your intent.  Please switch to using the Publication File, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($project.solution != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-05-23  experimental scheme for \"fast-id\" abandonend -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-05-23'\" />\n        <xsl:with-param name=\"message\" select=\"'the  oldids  string parameter was used for testing, was deprecated on 2021-03-03, is now obsolete, there is no replacement, relevant code has been removed, and the parameter is being ignored'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($oldids != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-05-28  \"latex.fillin.style\" is deprecated for publisher variables -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-05-28'\" />\n        <xsl:with-param name=\"message\" select=\"'the  latex.fillin.style  parameter has been replaced by the  common/fillin/@textstyle  and  common/fillin/mathstyle  entries in the publication file. The default style for a text fillin is now  underline  and the default style for a math fillin is now  shade .  To use  box  style for either, set values in the publication file.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($numbering.maximum.level != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-10-24  \"latex.font.size\" is deprecated for publisher variables -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-10-24'\" />\n        <xsl:with-param name=\"message\" select=\"'the  latex.font.size  parameter has been replaced by the  latex/@font-size  entry in the publication file.   We will attempt to honor your intent.  Note that possible values are the same, but you no longer provide &quot;pt&quot; as the unit of measure.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($latex.font.size != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-10-24  \"latex.geometry\" is deprecated for publisher variables -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-10-24'\" />\n        <xsl:with-param name=\"message\" select=\"'the  latex.geometry  parameter has been replaced by the  latex/page/geometry  entry in the publication file.  We will attempt to honor your intent.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($latex.geometry != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-10-24  \"latex.pageref\" is deprecated for publisher variables -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-10-24'\" />\n        <xsl:with-param name=\"message\" select=\"'the  latex.pageref string parameter has been replaced by the  latex/@pageref  entry in the publication file.  We will attempt to honor your intent.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($latex.pageref != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-10-24  \"latex.draft\" is deprecated for publisher variables -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-10-24'\" />\n        <xsl:with-param name=\"message\" select=\"'the  latex.draft string parameter has been replaced by the  latex/@draft  entry in the publication file.  We will attempt to honor your intent.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($latex.draft != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-10-24  watermark.text  deprecated in favor of publication file entry-->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-10-24'\" />\n        <xsl:with-param name=\"message\" select=\"'the  watermark.text  string parameter has been replaced by a publication file entry.  We will try to honor your intent.'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"($watermark.text != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-10-24  watermark.scale  deprecated in favor of publication file entry-->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-10-24'\" />\n        <xsl:with-param name=\"message\" select=\"'the  watermark.scale  string parameter has been replaced by a publication file entry.  We will try to honor your intent.'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"($watermark.scale != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-11-19  webwork.inline.static  deprecated in favor of publication file entry-->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-11-19'\" />\n        <xsl:with-param name=\"message\" select=\"'the  webwork.inline.static  string parameter has been replaced by a publication file entry.  We will try to honor your intent.'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"($webwork.inline.static != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-11-19  webwork.divisional.static  deprecated in favor of publication file entry-->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-11-19'\" />\n        <xsl:with-param name=\"message\" select=\"'the  webwork.divisional.static  string parameter has been replaced by a publication file entry.  We will try to honor your intent.'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"($webwork.divisional.static != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-11-19  webwork.reading.static  deprecated in favor of publication file entry-->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-11-19'\" />\n        <xsl:with-param name=\"message\" select=\"'the  webwork.reading.static  string parameter has been replaced by a publication file entry.  We will try to honor your intent.'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"($webwork.reading.static != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-11-19  webwork.worksheet.static  deprecated in favor of publication file entry-->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-11-19'\" />\n        <xsl:with-param name=\"message\" select=\"'the  webwork.worksheet.static  string parameter has been replaced by a publication file entry.  We will try to honor your intent.'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"($webwork.worksheet.static != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-11-19  webwork.project.static  deprecated in favor of publication file entry-->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-11-19'\" />\n        <xsl:with-param name=\"message\" select=\"'the  webwork.project.static  string parameter has been replaced by a publication file entry.  We will try to honor your intent.'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"($webwork.project.static != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-11-20  html.navigation.logic  deprecated in favor of publication file entry-->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-11-20'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.navigation.logic  string parameter has been replaced by a publication file entry.  We will try to honor your intent.'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"($html.navigation.logic != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-11-20  html.navigation.upbutton  deprecated in favor of publication file entry-->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-11-20'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.navigation.upbutton  string parameter has been replaced by a publication file entry.  We will try to honor your intent.'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"($html.navigation.upbutton != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-11-20  html.navigation.style  deprecated in favor of publication file entry-->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-11-20'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.navigation.style  string parameter has been replaced by a publication file entry.  We will try to honor your intent.'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"($html.navigation.style != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2022-11-20  emdash.space deprecated in favor of publication file entry-->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2022-11-20'\" />\n        <xsl:with-param name=\"message\" select=\"'the  emdash.space  string parameter has been replaced by a publication file entry.  We will try to honor your intent.'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"($emdash.space != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2023-01-11  EPUB cover image publication file entry totally reworked -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2023-01-11'\" />\n        <xsl:with-param name=\"message\" select=\"'the  epub/@cover  publication file entry has been replaced, and likely you will only get a simple generic cover image.  Please read the documentation for how to transition to the new specification'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"($publication/epub/@cover != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2023-05-05  HTML navigation buttons' style publication file entry removed -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2023-05-05'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html/navigation/@style  publication file entry has been removed, since the &quot;compact&quot; option is no longer implemented, and the only option left is &quot;full&quot;.  Remove your publication file entry to stop this message re-appearing'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"($publication/html/navigation/@style != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2024-02-16  \"commentary\" string parameter deprecated with changes in \"commentary\" element -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2024-02-16'\" />\n        <xsl:with-param name=\"message\" select=\"'the  commentary  string parameter has been deprecated, is no longer functional, and has no replacement.  Instead control the visibility of a &quot;commentary&quot; element by placing it into a component and using version support.  You likely also have related deprecation messages about that situation which are more informative.'\" />\n            <xsl:with-param name=\"incorrect-use\" select=\"($commentary != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2024-07-12'\" />\n        <xsl:with-param name=\"message\" select=\"'the html/css/@style publication file entry has been deprecated for replacement by @theme. See the Guide for theme options.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($publication/html/css/@style != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2024-07-12'\" />\n        <xsl:with-param name=\"message\" select=\"'the html/css/@toc, @navbar, @shell, @knowls, and @banner publication entries have been deprecated. Use @theme to control html appearance. See the Guide for theme options.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($publication/html/css/@toc != '' or $publication/html/css/@navbar != '' or $publication/html/css/@shell != '' or $publication/html/css/@knowls != '' or $publication/html/css/@banner != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2025-05-09'\" />\n        <xsl:with-param name=\"message\" select=\"'the webwork/@coursepassword and @userpassword publication entries have been deprecated. Use @password instead.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($publication/webwork/@coursepassword != '' or $publication/webwork/@userpassword != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2026-06-07'\" />\n        <xsl:with-param name=\"message\" select=\"'the  debug.project.number  parameter has been replaced by the  numbering/projects/@distinct  entry in the publisher file.  It will be ignored.  Please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($debug.project.number != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2026-07-25  HTML annotation platform controlled by publisher file -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2026-07-25'\" />\n        <xsl:with-param name=\"message\" select=\"'the  html.annotation  parameter has been replaced by the  html/annotation/@platform  entry in the publisher file.  We will attempt to honor your selection.  But please switch to using the Publishers File for configuration, as documented in the PreTeXt Guide.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($html.annotation != '')\" />\n    </xsl:call-template>\n    <!--  -->\n    <!-- 2026-08-02  managed directories are the only scheme -->\n    <xsl:call-template name=\"parameter-deprecation-message\">\n        <xsl:with-param name=\"date-string\" select=\"'2026-08-02'\" />\n        <xsl:with-param name=\"message\" select=\"'the  directory.images  parameter is now ignored: managed directories are the only scheme.  Generated assets live in the directory given by  source/directories/@generated  in the publication file (default: &quot;generated&quot;, beside the source), and external assets in the directory given by  &quot;directories/@external&quot;  within  &quot;docinfo&quot;.'\" />\n        <xsl:with-param name=\"incorrect-use\" select=\"($directory.images != '')\" />\n    </xsl:call-template>\n    <!--  -->\n</xsl:template>\n\n</xsl:stylesheet>\n","xml-to-json.xsl":"<?xml version=\"1.0\"?>\n\n<!--********************************************************************\nCopyright 2023 Jason Siefken\n\nThis file is part of PreTeXt.\n\nPreTeXt is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 or version 3 of the\nLicense (at your option).\n\nPreTeXt is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.\n*********************************************************************-->\n\n<!--\n    A basic recreation of the XSLT3.0 xml-to-json conversion.\n    Valid JSON nodes are: <map>, <array>, <number>, <string>, <boolean>, <null>.\n    Each node may have an optional @key (but only if the node is a child of <map>.\n    Nodes must be in the namespace http://www.w3.org/2005/xpath-functions\n\n    See https://www.w3.org/TR/xslt-30/#json-to-xml-mapping for some examples.\n\n    In addition to the usual JSON elements, a <raw> tag has been added. Contents of the <raw> tag\n    are passed directly through and printed (though leading indentation is still applied).\n\n    Example:\n    ```\n    <map xmlns=\"http://www.w3.org/2005/xpath-functions\">\n        <number key=\"Sunday\">\n            1\n        </number>\n        <boolean key=\"Wednesday\">\n            true\n        </boolean>\n        <boolean key=\"Wednesday\">\n        </boolean>\n        <null key=\"Monday\" />\n        <array key=\"content\">\n            <map>\n                <number key=\"id\">\n                    70805774\n                </number>\n                <string key=\"value\">1  0\\\"01\"fo\\o &gt;&#xa;bar</string>\n                <array key=\"position\">\n                    <number>\n                        1004.0\n                    </number>\n                    <number>\n                        288.0\n                    </number>\n                    <number>\n                        1050.0\n                    </number>\n                    <number>\n                        324.0\n                    </number>\n                </array>\n            </map>\n        </array>\n    </map>\n    ```\n    will produce in the document\n    ```\n    {\n       \"Sunday\": 1,\n       \"Wednesday\": true,\n       \"Wednesday\": false,\n       \"Monday\": null,\n       \"content\": [\n          {\n             \"id\": 70805774,\n             \"value\": \"1  0\\\\\\\"01\\\"fo\\\\o >\\nbar\",\n             \"position\": [\n                1004.0,\n                288.0,\n                1050.0,\n                324.0\n             ]\n          }\n       ]\n    }\n    ```\n\n    For debuggining, it can be helpful to have xsltproc run whenever this file changes. If you\n    are on linux and have inotifywait installed, you can run\n    `while inotifywait -e close_write xml-to-json.xsl; do xsltproc xml-to-json.xsl sample-data.xml;\ndone`\n    where `sample-data.xml` is the JSON data you're converting.\n-->\n\n<xsl:stylesheet version=\"1.0\"\n    xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n    xmlns:fn=\"http://www.w3.org/2005/xpath-functions\"\n    xmlns:exsl=\"http://exslt.org/common\"\n>\n    <xsl:output method=\"text\" encoding=\"utf-8\" />\n    <xsl:preserve-space elements=\"fn:string\" />\n\n\n    <!-- This is the main template that should be called to output\n         JSON from the structured XML content. -->\n    <xsl:template name=\"json\">\n        <xsl:param name=\"content\" />\n        <xsl:param name=\"indentDepth\" select=\"0\" />\n        <xsl:variable name=\"output\">\n            <xsl:apply-templates select=\"exsl:node-set($content)/*\" />\n        </xsl:variable>\n        <xsl:variable name=\"indentation\">\n            <xsl:call-template name=\"indent\">\n                <xsl:with-param name=\"depth\" select=\"$indentDepth\" />\n            </xsl:call-template></xsl:variable>\n        <xsl:call-template name=\"printIndented\">\n            <xsl:with-param name=\"indent\" select=\"$indentation\" />\n            <xsl:with-param name=\"text\" select=\"$output\" />\n        </xsl:call-template>\n    </xsl:template>\n\n    <xsl:template match=\"fn:raw\">\n        <xsl:apply-templates select=\"@key\" mode=\"attr\" />\n        <xsl:value-of select=\".\" />\n    </xsl:template>\n\n    <xsl:template match=\"fn:null\">\n        <xsl:apply-templates select=\"@key\" mode=\"attr\" />\n        <xsl:text>null</xsl:text>\n    </xsl:template>\n\n    <xsl:template match=\"fn:boolean\">\n        <xsl:apply-templates select=\"@key\" mode=\"attr\" />\n        <xsl:choose>\n            <xsl:when test=\"normalize-space(text()) = 'false'\">\n                <xsl:text>false</xsl:text>\n            </xsl:when>\n            <xsl:when test=\"normalize-space(text()) = '0'\">\n                <xsl:text>false</xsl:text>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:text>true</xsl:text>\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:template>\n\n    <xsl:template match=\"fn:number\">\n        <xsl:apply-templates select=\"@key\" mode=\"attr\" />\n        <xsl:value-of select=\"normalize-space(text())\" />\n    </xsl:template>\n\n    <xsl:template match=\"fn:string\">\n        <xsl:apply-templates select=\"@key\" mode=\"attr\" />\n        <xsl:text>\"</xsl:text>\n        <xsl:call-template name=\"escape-for-json\" />\n        <xsl:text>\"</xsl:text>\n    </xsl:template>\n\n    <xsl:template match=\"fn:array\">\n        <xsl:variable name=\"depth\" select=\"count(ancestor::*)\" />\n        <xsl:apply-templates\n            select=\"@key\"\n            mode=\"attr\" />\n        <xsl:text>[&#xa;</xsl:text>\n        <xsl:for-each select=\"./*\">\n            <xsl:call-template name=\"indent\">\n                <xsl:with-param name=\"depth\" select=\"$depth+1\"></xsl:with-param>\n            </xsl:call-template>\n            <xsl:apply-templates select=\".\" />\n            <xsl:if test=\"not(position() = last())\">\n                <xsl:text>,&#xa;</xsl:text>\n            </xsl:if>\n        </xsl:for-each>\n        <xsl:text>&#xa;</xsl:text>\n        <xsl:call-template name=\"indent\">\n            <xsl:with-param name=\"depth\" select=\"$depth\"></xsl:with-param>\n        </xsl:call-template>\n        <xsl:text>]</xsl:text>\n    </xsl:template>\n\n    <xsl:template match=\"fn:map\">\n        <xsl:variable name=\"depth\" select=\"count(ancestor::*)\" />\n        <xsl:apply-templates select=\"@key\" mode=\"attr\" />\n        <xsl:text>{&#xa;</xsl:text>\n        <xsl:for-each select=\"./*\">\n            <xsl:call-template name=\"indent\">\n                <xsl:with-param name=\"depth\" select=\"$depth+1\"></xsl:with-param>\n            </xsl:call-template>\n            <xsl:apply-templates select=\".\" />\n            <xsl:if test=\"not(position() = last())\">\n                <xsl:text>,&#xa;</xsl:text>\n            </xsl:if>\n        </xsl:for-each>\n        <xsl:text>&#xa;</xsl:text>\n        <xsl:call-template name=\"indent\">\n            <xsl:with-param name=\"depth\" select=\"$depth\"></xsl:with-param>\n        </xsl:call-template>\n        <xsl:text>}</xsl:text>\n    </xsl:template>\n\n\n    <!-- Wrap any @key in quotes. No special care is taken to escape the key name,\n         so make it sensible right from the get-go! -->\n    <xsl:template match=\"@key\" mode=\"attr\">\n        <xsl:text>\"</xsl:text>\n        <xsl:value-of select=\".\" />\n        <xsl:text>\": </xsl:text>\n    </xsl:template>\n\n    <!-- 2 paces of indentation for each $depth -->\n    <xsl:template name=\"indent\">\n        <xsl:param name=\"depth\" select=\"'0'\" />\n\n        <xsl:call-template name=\"duplicate-string\">\n             <xsl:with-param name=\"text\" select=\"'  '\"/>\n             <xsl:with-param name=\"count\" select=\"$depth\" />\n        </xsl:call-template>\n    </xsl:template>\n\n    <!-- Escape strings for JSON. This process first escapes backslashes,\n         then escapes quotes (\") and finally escapes newlines. Other characters\n         should be valid JSON -->\n    <xsl:template name=\"escape-for-json\">\n        <xsl:param name=\"pText\" select=\".\" />\n        <xsl:variable name=\"escaped1\">\n            <xsl:call-template name=\"escapeBackslash\">\n                <xsl:with-param name=\"pText\" select=\"$pText\" />\n            </xsl:call-template>\n        </xsl:variable>\n        <xsl:variable name=\"escaped2\">\n            <xsl:call-template name=\"escapeQuotes\">\n                <xsl:with-param name=\"pText\" select=\"$escaped1\" />\n            </xsl:call-template>\n        </xsl:variable>\n        <xsl:variable name=\"escaped3\">\n            <xsl:call-template name=\"escapeNewlines\">\n                <xsl:with-param name=\"pText\" select=\"$escaped2\" />\n            </xsl:call-template>\n        </xsl:variable>\n        <xsl:value-of select=\"$escaped3\" />\n    </xsl:template>\n\n    <xsl:template name=\"escapeBackslash\">\n        <xsl:param name=\"pText\" select=\".\" />\n        <xsl:variable name=\"head\" select=\"substring-before($pText, '\\')\" />\n        <xsl:variable name=\"tail\" select=\"substring-after($pText, '\\')\" />\n        <xsl:choose>\n            <xsl:when test=\"$head or $tail\">\n                <xsl:value-of select=\"$head\" />\n                <xsl:text>\\\\</xsl:text>\n                <xsl:call-template name=\"escapeBackslash\">\n                    <xsl:with-param name=\"pText\" select=\"$tail\" />\n                </xsl:call-template>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$pText\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:template>\n\n    <xsl:template name=\"escapeQuotes\">\n        <xsl:param name=\"pText\" select=\".\" />\n        <xsl:variable name=\"head\" select=\"substring-before($pText, '&quot;')\" />\n        <xsl:variable name=\"tail\" select=\"substring-after($pText, '&quot;')\" />\n        <xsl:choose>\n            <xsl:when test=\"$head or $tail\">\n                <xsl:value-of select=\"$head\" />\n                <xsl:text>\\\"</xsl:text>\n                <xsl:call-template name=\"escapeQuotes\">\n                    <xsl:with-param name=\"pText\" select=\"$tail\" />\n                </xsl:call-template>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$pText\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:template>\n\n    <xsl:template name=\"escapeNewlines\">\n        <xsl:param name=\"pText\" select=\".\" />\n        <xsl:variable name=\"head\" select=\"substring-before($pText, '&#xa;')\" />\n        <xsl:variable name=\"tail\" select=\"substring-after($pText, '&#xa;')\" />\n        <xsl:choose>\n            <xsl:when test=\"$head or $tail\">\n                <xsl:value-of select=\"$head\" />\n                <xsl:text>\\n</xsl:text>\n                <xsl:call-template name=\"escapeNewlines\">\n                    <xsl:with-param name=\"pText\" select=\"$tail\" />\n                </xsl:call-template>\n            </xsl:when>\n            <xsl:otherwise>\n                <xsl:value-of select=\"$pText\" />\n            </xsl:otherwise>\n        </xsl:choose>\n    </xsl:template>\n\n    <!-- This function is from Stack Overflow\n    https://stackoverflow.com/questions/24513266/indent-multi-line-blocks-of-xsltext\n    CC-BY-SA license -->\n    <xsl:template name=\"printIndented\">\n        <xsl:param name=\"text\" />\n        <xsl:param name=\"indent\" />\n\n        <xsl:if test=\"$text\">\n            <xsl:value-of select=\"$indent\" />\n            <xsl:variable name=\"thisLine\" select=\"substring-before($text, '&#10;')\" />\n            <xsl:choose>\n                <xsl:when test=\"$thisLine\"><!-- $text contains at least one newline -->\n                    <!-- print this line -->\n                    <xsl:value-of select=\"concat($thisLine, '&#10;')\" />\n                    <!-- and recurse to process the rest -->\n                    <xsl:call-template name=\"printIndented\">\n                        <xsl:with-param name=\"text\" select=\"substring-after($text, '&#10;')\" />\n                        <xsl:with-param name=\"indent\" select=\"$indent\" />\n                    </xsl:call-template>\n                </xsl:when>\n                <xsl:otherwise>\n                    <xsl:value-of select=\"$text\" />\n                </xsl:otherwise>\n            </xsl:choose>\n        </xsl:if>\n    </xsl:template>\n</xsl:stylesheet>\n","xml-to-string.xsl":"<!--\nCopyright (c) 2001-2009, Evan Lenz\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n    * Neither the name of Lenz Consulting Group nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\n\t    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nRecent changes:\n\n2010-06-10: Added the $force-exclude-all-namespaces parameter\n2009-10-19: Added the $exclude-these-namespaces parameter \n2009-10-08: Added $att-value parameter and template name to template rule for attributes.\n\n2025-05-27: PreTeXt, R. Beezer.  Escaped \"greater-than\".\n\n-->\n<xsl:stylesheet version=\"1.0\"\n  xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n\n  <xsl:output omit-xml-declaration=\"yes\"/>\n\n  <xsl:param name=\"use-empty-syntax\" select=\"true()\"/>\n  <xsl:param name=\"exclude-unused-prefixes\" select=\"true()\"/>\n\n  <xsl:param name=\"force-exclude-all-namespaces\" select=\"false()\"/>\n\n  <!-- a node-set; each node's string-value\n       will be interpreted as a namespace URI to be\n       excluded from the serialization. -->\n  <xsl:param name=\"namespaces-to-exclude\" select=\"/..\"/>\n                                          <!-- initialized to empty node-set -->\n\n  <xsl:param name=\"start-tag-start\"     select=\"'&lt;'\"/>\n  <xsl:param name=\"start-tag-end\"       select=\"'>'\"/>\n  <xsl:param name=\"empty-tag-end\"       select=\"'/>'\"/>\n  <xsl:param name=\"end-tag-start\"       select=\"'&lt;/'\"/>\n  <xsl:param name=\"end-tag-end\"         select=\"'>'\"/>\n  <xsl:param name=\"space\"               select=\"' '\"/>\n  <xsl:param name=\"ns-decl\"             select=\"'xmlns'\"/>\n  <xsl:param name=\"colon\"               select=\"':'\"/>\n  <xsl:param name=\"equals\"              select=\"'='\"/>\n  <xsl:param name=\"attribute-delimiter\" select=\"'&quot;'\"/>\n  <xsl:param name=\"comment-start\"       select=\"'&lt;!--'\"/>\n  <xsl:param name=\"comment-end\"         select=\"'-->'\"/>\n  <xsl:param name=\"pi-start\"            select=\"'&lt;?'\"/>\n  <xsl:param name=\"pi-end\"              select=\"'?>'\"/>\n\n  <xsl:template name=\"xml-to-string\">\n    <xsl:param name=\"node-set\" select=\".\"/>\n    <xsl:apply-templates select=\"$node-set\" mode=\"xml-to-string\">\n      <xsl:with-param name=\"depth\" select=\"1\"/>\n    </xsl:apply-templates>\n  </xsl:template>\n\n  <xsl:template match=\"/\" name=\"xml-to-string-root-rule\">\n    <xsl:call-template name=\"xml-to-string\"/>\n  </xsl:template>\n\n  <xsl:template match=\"/\" mode=\"xml-to-string\">\n    <xsl:param name=\"depth\"/>\n    <xsl:apply-templates mode=\"xml-to-string\">\n      <xsl:with-param name=\"depth\" select=\"$depth\"/>\n    </xsl:apply-templates>\n  </xsl:template>\n\n  <xsl:template match=\"*\" mode=\"xml-to-string\">\n    <xsl:param name=\"depth\"/>\n    <xsl:variable name=\"element\" select=\".\"/>\n    <xsl:value-of select=\"$start-tag-start\"/>\n    <xsl:call-template name=\"element-name\">\n      <xsl:with-param name=\"text\" select=\"name()\"/>\n    </xsl:call-template>\n    <xsl:apply-templates select=\"@*\" mode=\"xml-to-string\"/>\n    <xsl:if test=\"not($force-exclude-all-namespaces)\">\n      <xsl:for-each select=\"namespace::*\">\n        <xsl:call-template name=\"process-namespace-node\">\n          <xsl:with-param name=\"element\" select=\"$element\"/>\n          <xsl:with-param name=\"depth\" select=\"$depth\"/>\n        </xsl:call-template>\n      </xsl:for-each>\n    </xsl:if>\n    <xsl:choose>\n      <xsl:when test=\"node() or not($use-empty-syntax)\">\n        <xsl:value-of select=\"$start-tag-end\"/>\n        <xsl:apply-templates mode=\"xml-to-string\">\n          <xsl:with-param name=\"depth\" select=\"$depth + 1\"/>\n        </xsl:apply-templates>\n        <xsl:value-of select=\"$end-tag-start\"/>\n        <xsl:call-template name=\"element-name\">\n          <xsl:with-param name=\"text\" select=\"name()\"/>\n        </xsl:call-template>\n        <xsl:value-of select=\"$end-tag-end\"/>\n      </xsl:when>\n      <xsl:otherwise>\n        <xsl:value-of select=\"$empty-tag-end\"/>\n      </xsl:otherwise>\n    </xsl:choose>\n  </xsl:template>\n\n  <xsl:template name=\"process-namespace-node\">\n    <xsl:param name=\"element\"/>\n    <xsl:param name=\"depth\"/>\n    <xsl:variable name=\"declaredAbove\">\n      <xsl:call-template name=\"isDeclaredAbove\">\n        <xsl:with-param name=\"depth\" select=\"$depth - 1\"/>\n        <xsl:with-param name=\"element\" select=\"$element/..\"/>\n      </xsl:call-template>\n    </xsl:variable>\n\n    <xsl:variable name=\"is-used-on-this-element\" select=\"($element    | $element/@*) [namespace-uri() = current()]\"/>\n    <xsl:variable name=\"is-used-on-a-descendant\" select=\"($element//* | $element//@*)[namespace-uri() = current()]\"/>          \n    <xsl:variable name=\"is-unused\" select=\"not($is-used-on-this-element) and\n                                           not($is-used-on-a-descendant)\"/>\n    <xsl:variable name=\"exclude-ns\" select=\"($is-unused and $exclude-unused-prefixes) or\n                                            (. = $namespaces-to-exclude)\"/>\n\n    <xsl:variable name=\"force-include\" select=\"$is-used-on-this-element and (. = $namespaces-to-exclude)\"/>\n\n    <xsl:if test=\"(name() != 'xml') and ($force-include or (not($exclude-ns) and not(string($declaredAbove))))\">\n      <xsl:value-of select=\"$space\"/>\n      <xsl:value-of select=\"$ns-decl\"/>\n      <xsl:if test=\"name()\">\n        <xsl:value-of select=\"$colon\"/>\n        <xsl:call-template name=\"ns-prefix\">\n          <xsl:with-param name=\"text\" select=\"name()\"/>\n        </xsl:call-template>\n      </xsl:if>\n      <xsl:value-of select=\"$equals\"/>\n      <xsl:value-of select=\"$attribute-delimiter\"/>\n      <xsl:call-template name=\"ns-uri\">\n        <xsl:with-param name=\"text\" select=\"string(.)\"/>\n      </xsl:call-template>\n      <xsl:value-of select=\"$attribute-delimiter\"/>\n    </xsl:if>\n  </xsl:template>\n\n  <xsl:template name=\"isDeclaredAbove\">\n    <xsl:param name=\"element\"/>\n    <xsl:param name=\"depth\"/>\n    <xsl:if test=\"$depth > 0\">\n      <xsl:choose>\n        <xsl:when test=\"$element/namespace::*[name(.)=name(current()) and .=current()]\">1</xsl:when>\n        <xsl:when test=\"$element/namespace::*[name(.)=name(current())]\"/>\n        <xsl:otherwise>\n          <xsl:call-template name=\"isDeclaredAbove\">\n            <xsl:with-param name=\"depth\" select=\"$depth - 1\"/>\n            <xsl:with-param name=\"element\" select=\"$element/..\"/>\n          </xsl:call-template>\n        </xsl:otherwise>\n      </xsl:choose>\n    </xsl:if>\n  </xsl:template>\n\n  <xsl:template match=\"@*\" mode=\"xml-to-string\" name=\"serialize-attribute\">\n    <xsl:param name=\"att-value\" select=\"string(.)\"/>\n    <xsl:value-of select=\"$space\"/>\n    <xsl:call-template name=\"attribute-name\">\n      <xsl:with-param name=\"text\" select=\"name()\"/>\n    </xsl:call-template>\n    <xsl:value-of select=\"$equals\"/>\n    <xsl:value-of select=\"$attribute-delimiter\"/>\n    <xsl:call-template name=\"attribute-value\">\n      <xsl:with-param name=\"text\" select=\"$att-value\"/>\n    </xsl:call-template>\n    <xsl:value-of select=\"$attribute-delimiter\"/>\n  </xsl:template>\n\n  <xsl:template match=\"comment()\" mode=\"xml-to-string\">\n    <xsl:value-of select=\"$comment-start\"/>\n    <xsl:call-template name=\"comment-text\">\n      <xsl:with-param name=\"text\" select=\"string(.)\"/>\n    </xsl:call-template>\n    <xsl:value-of select=\"$comment-end\"/>\n  </xsl:template>\n\n  <xsl:template match=\"processing-instruction()\" mode=\"xml-to-string\">\n    <xsl:value-of select=\"$pi-start\"/>\n    <xsl:call-template name=\"pi-target\">\n      <xsl:with-param name=\"text\" select=\"name()\"/>\n    </xsl:call-template>\n    <xsl:value-of select=\"$space\"/>\n    <xsl:call-template name=\"pi-text\">\n      <xsl:with-param name=\"text\" select=\"string(.)\"/>\n    </xsl:call-template>\n    <xsl:value-of select=\"$pi-end\"/>\n  </xsl:template>\n\n  <xsl:template match=\"text()\" mode=\"xml-to-string\">\n    <xsl:call-template name=\"text-content\">\n      <xsl:with-param name=\"text\" select=\"string(.)\"/>\n    </xsl:call-template>\n  </xsl:template>\n\n  <xsl:template name=\"element-name\">\n    <xsl:param name=\"text\"/>\n    <xsl:value-of select=\"$text\"/>\n  </xsl:template>\n\n  <xsl:template name=\"attribute-name\">\n    <xsl:param name=\"text\"/>\n    <xsl:value-of select=\"$text\"/>\n  </xsl:template>\n\n  <xsl:template name=\"attribute-value\">\n    <xsl:param name=\"text\"/>\n    <xsl:variable name=\"escaped-markup\">\n      <xsl:call-template name=\"escape-markup-characters\">\n        <xsl:with-param name=\"text\" select=\"$text\"/>\n      </xsl:call-template>\n    </xsl:variable>\n    <xsl:choose>\n      <xsl:when test=\"$attribute-delimiter = &quot;'&quot;\">\n        <xsl:call-template name=\"replace-string\">\n          <xsl:with-param name=\"text\" select=\"$escaped-markup\"/>\n          <xsl:with-param name=\"replace\" select=\"&quot;'&quot;\"/>\n          <xsl:with-param name=\"with\" select=\"'&amp;apos;'\"/>\n        </xsl:call-template>\n      </xsl:when>\n      <xsl:when test=\"$attribute-delimiter = '&quot;'\">\n        <xsl:call-template name=\"replace-string\">\n          <xsl:with-param name=\"text\" select=\"$escaped-markup\"/>\n          <xsl:with-param name=\"replace\" select=\"'&quot;'\"/>\n          <xsl:with-param name=\"with\" select=\"'&amp;quot;'\"/>\n        </xsl:call-template>\n      </xsl:when>\n      <xsl:otherwise>\n        <xsl:call-template name=\"replace-string\">\n          <xsl:with-param name=\"text\" select=\"$escaped-markup\"/>\n          <xsl:with-param name=\"replace\" select=\"$attribute-delimiter\"/>\n          <xsl:with-param name=\"with\" select=\"''\"/>\n        </xsl:call-template>\n      </xsl:otherwise>\n    </xsl:choose>\n  </xsl:template>\n\n  <xsl:template name=\"ns-prefix\">\n    <xsl:param name=\"text\"/>\n    <xsl:value-of select=\"$text\"/>\n  </xsl:template>\n\n  <xsl:template name=\"ns-uri\">\n    <xsl:param name=\"text\"/>\n    <xsl:call-template name=\"attribute-value\">\n      <xsl:with-param name=\"text\" select=\"$text\"/>\n    </xsl:call-template>\n  </xsl:template>\n\n  <xsl:template name=\"text-content\">\n    <xsl:param name=\"text\"/>\n    <xsl:call-template name=\"escape-markup-characters\">\n      <xsl:with-param name=\"text\" select=\"$text\"/>\n    </xsl:call-template>\n  </xsl:template>\n\n  <xsl:template name=\"pi-target\">\n    <xsl:param name=\"text\"/>\n    <xsl:value-of select=\"$text\"/>\n  </xsl:template>\n\n  <xsl:template name=\"pi-text\">\n    <xsl:param name=\"text\"/>\n    <xsl:value-of select=\"$text\"/>\n  </xsl:template>\n\n  <xsl:template name=\"comment-text\">\n    <xsl:param name=\"text\"/>\n    <xsl:value-of select=\"$text\"/>\n  </xsl:template>\n\n  <xsl:template name=\"escape-markup-characters\">\n    <xsl:param name=\"text\"/>\n    <xsl:variable name=\"ampEscaped\">\n      <xsl:call-template name=\"replace-string\">\n        <xsl:with-param name=\"text\" select=\"$text\"/>\n        <xsl:with-param name=\"replace\" select=\"'&amp;'\"/>\n        <xsl:with-param name=\"with\" select=\"'&amp;amp;'\"/>\n      </xsl:call-template>\n    </xsl:variable>\n    <xsl:variable name=\"ltEscaped\">\n      <xsl:call-template name=\"replace-string\">\n        <xsl:with-param name=\"text\" select=\"$ampEscaped\"/>\n        <xsl:with-param name=\"replace\" select=\"'&lt;'\"/>\n        <xsl:with-param name=\"with\" select=\"'&amp;lt;'\"/>\n      </xsl:call-template>\n    </xsl:variable>\n    <!-- 2025-05-27: PreTeXt, R. Beezer.  Escaped \"greater-than\". -->\n    <!-- Inserted new step w/ \"gtEscaped\" variable                -->\n    <xsl:variable name=\"gtEscaped\">\n      <xsl:call-template name=\"replace-string\">\n        <xsl:with-param name=\"text\" select=\"$ltEscaped\"/>\n        <xsl:with-param name=\"replace\" select=\"'&gt;'\"/>\n        <xsl:with-param name=\"with\" select=\"'&amp;gt;'\"/>\n      </xsl:call-template>\n    </xsl:variable>\n    <xsl:call-template name=\"replace-string\">\n      <xsl:with-param name=\"text\" select=\"$gtEscaped\"/>\n      <xsl:with-param name=\"replace\" select=\"']]>'\"/>\n      <xsl:with-param name=\"with\" select=\"']]&amp;gt;'\"/>\n    </xsl:call-template>\n  </xsl:template>\n\n  <xsl:template name=\"replace-string\">\n    <xsl:param name=\"text\"/>\n    <xsl:param name=\"replace\"/>\n    <xsl:param name=\"with\"/>\n    <xsl:variable name=\"stringText\" select=\"string($text)\"/>\n    <xsl:choose>\n      <xsl:when test=\"contains($stringText,$replace)\">\n        <xsl:value-of select=\"substring-before($stringText,$replace)\"/>\n        <xsl:value-of select=\"$with\"/>\n        <xsl:call-template name=\"replace-string\">\n          <xsl:with-param name=\"text\" select=\"substring-after($stringText,$replace)\"/>\n          <xsl:with-param name=\"replace\" select=\"$replace\"/>\n          <xsl:with-param name=\"with\" select=\"$with\"/>\n        </xsl:call-template>\n      </xsl:when>\n      <xsl:otherwise>\n        <xsl:value-of select=\"$stringText\"/>\n      </xsl:otherwise>\n    </xsl:choose>\n  </xsl:template>\n\n</xsl:stylesheet>\n"}