/*
:filename: wexa_statics/css/book.css
:author: Brigitte Bigi
:contact: contact@sppas.org
:summary: a CSS framework to make reports from web content

-------------------------------------------------------------------------

This file is part of Whakerexa: https://github.com/brigitte-bigi/Whakerexa

Copyright (C) 2023-2026 Brigitte Bigi, CNRS
Laboratoire Parole et Langage, Aix-en-Provence, France

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

This banner notice must not be removed.

-------------------------------------------------------------------------

Architecture:
  - Unlayered rules: structural invariants that must always win (layout, sizing,
    counters, positioning, transitions). These cannot be overridden by themes.
  - @layer theme block at the bottom: visual defaults (colors, accent borders,
    backgrounds, shadows). Theme files injected later in <head> override these
    within the same layer by source order.

*/

:root {
    --toc-width: 0;

    /* The band the folded panel leaves free on the left, where the button that
       brings it back stands. It is what that button takes: its two paddings,
       the line its text is written on -- the text is turned on its side, so
       that line is a width -- and the room its outline is drawn in. A page has
       nothing to reserve, and the band follows the size of the text, in
       contrast mode as on any screen. */
    --toc-aside-width: calc(var(--typography-spacing-horizontal)
                            + 0.75 * var(--font-size) * var(--line-height)
                            + 2 * var(--outline-size));
}


@media screen {
    html {
        margin-left: var(--toc-width);
    }

    html:has(aside.book-toc-aside) {
        margin-left: var(--toc-aside-width);
        transition: margin-left var(--transition, 0.25s ease-in-out);
    }

    html:has(aside.book-toc-aside.open) {
        margin-left: calc(var(--toc-aside-width) + var(--toc-width));
    }

    /* A narrow screen has no width to lend to a column nobody reads: the
       toggle and the panel stand over the text instead of pushing it. */
    @media (max-width: 1023.98px) {
        html,
        html:has(aside.book-toc-aside),
        html:has(aside.book-toc-aside.open) {
            margin-left: 0;
        }
    }
}

body {
    width: 100%;
    counter-reset: chapter;
}

/* ----------------------------------------------------------------------- */
/* ------------------------------- Titles  ------------------------------- */
/* ----------------------------------------------------------------------- */

/* A new numbered chapter in the document */
.chapter {
    counter-increment: chapter;
    counter-reset: ssection;
    text-align: left;
    min-height: 100vh;
}

.chapter > h1 {
    width: 100%;
    padding-top: calc(var(--font-size) * 2);
    padding-bottom: calc(var(--font-size) * 2);
    margin-bottom: calc(var(--font-size) * 4);
    line-height: calc(4 * var(--font-size));

    /* a chapter title is a box for 2 items: number + title */
    display: inline-flex;
    flex-direction: column;
    justify-content: center;
    align-items: start;
    text-align: left;
}

/* The number is announced by the word it numbers, in the language the document
   is written in: a number alone says what it counts to nobody. */
.chapter > h1::before {
    content: "Chapter " counter(chapter) ".";
    padding-top: calc(var(--font-size) * 1);
    margin-top: 0;
    margin-right: calc(var(--font-size) * 1);
}

html:lang(fr) .chapter > h1::before {
    content: "Chapitre " counter(chapter) ".";
}

/* A new numbered section in the chapter */
.ssection {
    counter-increment: ssection;
    counter-reset: subssection;
    padding-left: 0;
    padding-right: 0;
}

/* The size of a title belongs to wexa.css: the number takes the size of the
   title it numbers. */
.ssection h2::before {
    content: counter(chapter) "." counter(ssection) " ";
}

/* A new numbered sub-section in the section */
.subssection {
    counter-increment: subssection;
    padding-left: 0;
    padding-right: 0;
}

.subssection h3::before {
    content: counter(chapter) "." counter(ssection) "." counter(subssection) " ";
}

/* ----------------------------------------------------------------------- */
/* ---------------------- BOOK NAVIGATION: Table of Content -------------- */
/* ----------------------------------------------------------------------- */

/* One table of contents, two containers: 'nav.book-toc' is always shown at the
   left of the document, 'aside.book-toc-aside' is folded behind a button that
   book.js injects. Only two things separate them -- where each is placed, and
   how far each level is indented, a narrow panel having less width to give.
   Everything else is written once, for both.

   Usage of the folded one:
     <aside class="book-toc-aside" id="book-toc-aside">
        <h1>Table of contents</h1>
        <ul id="toc"></ul>
     </aside>
*/

/* ------------------------- Placement: fixed panel ---------------------- */

nav.book-toc {
    z-index: 9;
    width: var(--toc-width);
    height: 100%;
    position: fixed;
    top: var(--typography-spacing-vertical);
    left: 0;
    padding-bottom: calc(var(--font-size) * 3);
    margin-top: calc(-1 * var(--typography-spacing-vertical));
    font-size: 90%;
    overflow-x: hidden;
    display: block;
}

body:has(nav.nav-wexa.top) nav.book-toc {
    top: var(--nav-height);
}

/* ------------------------ Placement: folded panel ---------------------- */

aside.book-toc-aside {
    width: var(--toc-width);
    display: block;
    padding: var(--typography-spacing-vertical) var(--typography-spacing-horizontal);
    padding-bottom: calc(var(--font-size) * 3);
}

@media screen {
    aside.book-toc-aside {
        z-index: 10;
        height: 100%;
        position: fixed;
        top: 0;
        left: var(--toc-aside-width);
        overflow-x: hidden;
        transform: translateX(calc(-1 * (var(--toc-aside-width) + var(--toc-width))));
        transition: transform var(--transition, 0.25s ease-in-out);
    }

    aside.book-toc-aside.open {
        transform: translateX(0);
    }

    body:has(nav.nav-wexa.top) aside.book-toc-aside {
        top: var(--nav-height);
    }

    /* Toggle button injected by book.js. Its z-index stands above the panel it
       commands: the two shared one, and the DOM order settled it for the aside. */
    button.book-toc-toggle {
        position: fixed;
        top: 50vh;
        left: 0;
        z-index: 11;
        writing-mode: vertical-rl;
        transform: translateY(-50%) rotate(180deg);
        padding: var(--typography-spacing-vertical) calc(0.5 * var(--typography-spacing-horizontal));
        border-radius: var(--border-radius) 0 0 var(--border-radius);
        cursor: pointer;
        font-size: calc(0.75 * var(--font-size));
        font-family: inherit;
        transition: left var(--transition, 0.25s ease-in-out);
    }

    body:has(aside.book-toc-aside.open) button.book-toc-toggle {
        left: 0;
    }
}

/* ------------------------------- The reset ----------------------------- */

/* Whatever the panel inherited is dropped. The margin is the one declaration
   the two containers cannot share: the fixed panel centres what it holds --
   a title, a logo -- while the folded one lines its entries up on the edge. */

nav.book-toc * {
    margin: auto;
    padding: 0;
    font-size: calc(0.8 * var(--font-size));
}

aside.book-toc-aside *:not([role=button]) {
    margin: 0;
    padding: 0;
    font-size: calc(0.8 * var(--font-size));
    background-color: transparent;
}

/* --------------------------- Common: the panel ------------------------- */

:is(nav.book-toc, aside.book-toc-aside) > ul,
:is(nav.book-toc, aside.book-toc-aside) > hr,
:is(nav.book-toc, aside.book-toc-aside) > h1,
:is(nav.book-toc, aside.book-toc-aside) > h2 {
    margin-top: calc(var(--font-size) * 1);
    margin-bottom: calc(var(--font-size) * 2);
}

:is(nav.book-toc, aside.book-toc-aside) h1 {
    font-size: calc(1.5 * var(--font-size));
    font-weight: var(--font-weight-black);
}

:is(nav.book-toc, aside.book-toc-aside) h2 {
    font-size: calc(1.5 * var(--font-size));
    font-weight: var(--font-weight-bold);
}

:is(nav.book-toc, aside.book-toc-aside) a[role=button],
:is(nav.book-toc, aside.book-toc-aside) button {
    width: calc(0.75 * var(--toc-width));
    height: calc(3 * var(--font-size));
    border-radius: calc(3 * (var(--border-width)));
    display: flex;
    justify-content: center;
    flex-direction: column;
    margin-bottom: calc(var(--font-size) * 0.5);
}

/* --------------------------- Common: the entries ----------------------- */

/* The table is generated from the <h*> of the document: the tag of a heading
   becomes the class of its entry, thanks to book.js. */

:is(nav.book-toc, aside.book-toc-aside) ul {
    display: initial;
}

:is(nav.book-toc, aside.book-toc-aside) a:not([role=button],[role=menuitem]) {
    display: initial;
}

/* An entry is read in two columns: what numbers it, and what it says. A number
   in the flow of the text pushes the title around and breaks it in two when
   the panel is narrow. */
:is(nav.book-toc, aside.book-toc-aside) li.h1,
:is(nav.book-toc, aside.book-toc-aside) li.h2,
:is(nav.book-toc, aside.book-toc-aside) li.h3,
:is(nav.book-toc, aside.book-toc-aside) li.h4,
:is(nav.book-toc, aside.book-toc-aside) li.h5,
:is(nav.book-toc, aside.book-toc-aside) li.h6 {
    display: grid;
    grid-template-columns: var(--toc-number-width) 1fr;
    column-gap: var(--typography-spacing-horizontal);
    margin-bottom: calc(var(--font-size) * 0.2);
    text-align: left;
}

/* The reset above gives the fixed panel "margin: auto", which would centre
   each title in its column. Inside an entry, both columns start where they
   should. */
:is(nav.book-toc, aside.book-toc-aside) li > a {
    margin: 0;
    justify-self: start;
}

/* The width of the number is fixed for each level: a column as wide as its
   content is a column of a different width at every line, and no two titles
   ever start at the same place. */
:is(nav.book-toc, aside.book-toc-aside) li {
    --toc-number-width: calc(var(--font-size) * 1.5);
}
:is(nav.book-toc, aside.book-toc-aside) li.h1 { --toc-number-width: calc(var(--font-size) * 2); }
:is(nav.book-toc, aside.book-toc-aside) li.h2 { --toc-number-width: calc(var(--font-size) * 2.2); }
:is(nav.book-toc, aside.book-toc-aside) li.h3 { --toc-number-width: calc(var(--font-size) * 2.8); }

/* An entry of the table is numbered by the rules below, and an entry that
   numbers nothing -- a browsing button -- shows nothing: the bullet of
   wexa.css is written for a list of text, and its exclusion knows 'nav'
   alone. */
:is(nav.book-toc, aside.book-toc-aside) li::before {
    content: none;
    margin: 0;
    padding-right: 0;
    justify-self: end;
    text-align: right;
    white-space: nowrap;
}

/* The number of an entry is written in the size of the title it numbers: the
   reset sets every child of the panel to one size, and each level gives its
   own back to the link and to its number. */
:is(nav.book-toc, aside.book-toc-aside) li.h1::before { font-size: calc(1.2 * var(--font-size)); }
:is(nav.book-toc, aside.book-toc-aside) li.h2::before { font-size: var(--font-size); }
:is(nav.book-toc, aside.book-toc-aside) li.h3::before { font-size: calc(0.9 * var(--font-size)); }

/* -------------------------- Common: the numbering ---------------------- */

/* The entries of the table of contents bear the same numbers as the titles
   they lead to. They are counted here and nowhere else: a script counting
   them a second time would be a second truth. An entry coming from a chapter
   that bears "nonumber" carries it too, and is numbered by nobody. */

:is(nav.book-toc, aside.book-toc-aside) ul {
    counter-reset: toc-chapter;
}
:is(nav.book-toc, aside.book-toc-aside) li.h1 {
    counter-increment: toc-chapter;
    counter-reset: toc-ssection;
}
:is(nav.book-toc, aside.book-toc-aside) li.h2 {
    counter-increment: toc-ssection;
    counter-reset: toc-subssection;
}
:is(nav.book-toc, aside.book-toc-aside) li.h3 {
    counter-increment: toc-subssection;
}

/* An entry that is numbered by nobody keeps no column for a number: the width
   of that column changes with the level, so keeping it would step every entry
   a different distance from the edge. */
:is(nav.book-toc, aside.book-toc-aside) li.nonumber {
    counter-increment: none;
    --toc-number-width: 0;
    column-gap: 0;
}

:is(nav.book-toc, aside.book-toc-aside) li.h1::before {
    content: counter(toc-chapter) ".";
    padding-right: calc(0.4 * var(--typography-spacing-horizontal));
}
:is(nav.book-toc, aside.book-toc-aside) li.h2::before {
    content: counter(toc-chapter) "." counter(toc-ssection);
    padding-right: calc(0.4 * var(--typography-spacing-horizontal));
}
:is(nav.book-toc, aside.book-toc-aside) li.h3::before {
    content: counter(toc-chapter) "." counter(toc-ssection) "." counter(toc-subssection);
    padding-right: calc(0.4 * var(--typography-spacing-horizontal));
}
:is(nav.book-toc, aside.book-toc-aside) li.h1.nonumber::before,
:is(nav.book-toc, aside.book-toc-aside) li.h2.nonumber::before,
:is(nav.book-toc, aside.book-toc-aside) li.h3.nonumber::before {
    content: "";
    padding-right: 0;
}
:is(nav.book-toc, aside.book-toc-aside) li.h4::before {
    content: "-";
    padding-right: calc(0.4 * var(--typography-spacing-horizontal));
}
:is(nav.book-toc, aside.book-toc-aside) li.h5::before {
    content: "□";
    padding-right: calc(0.4 * var(--typography-spacing-horizontal));
}

/* ------------------------- Common: the links ---------------------------- */

:is(nav.book-toc, aside.book-toc-aside) li.h1 a {
    text-decoration: none;
    font-variant-caps: small-caps;
    font-weight: var(--font-weight-bold);
    font-size: calc(1.2 * var(--font-size));
}
:is(nav.book-toc, aside.book-toc-aside) li.h2 a {
    text-decoration: none;
    font-weight: var(--font-weight-semibold);
    text-overflow: ellipsis;
    font-size: var(--font-size);
}
:is(nav.book-toc, aside.book-toc-aside) li.h3 a {
    text-decoration: none;
    font-weight: var(--font-weight-normal);
    text-overflow: ellipsis;
    font-size: calc(0.9 * var(--font-size));
}
:is(nav.book-toc, aside.book-toc-aside) li.h4 a {
    text-decoration: none;
    font-weight: var(--font-weight-semithin);
    white-space: nowrap;
    text-overflow: ellipsis;
}
:is(nav.book-toc, aside.book-toc-aside) li.h5 a {
    text-decoration: none;
    font-weight: var(--font-weight-thin);
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: calc(0.75 * var(--font-size));
}
:is(nav.book-toc, aside.book-toc-aside) li.h6 a {
    text-decoration: none;
    font-weight: var(--font-weight-thin);
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: calc(0.7 * var(--font-size));
}

/* --------------------------- Common: the indentation -------------------- */

/* One space between two entries, and a wider one before a chapter: a list
   whose gaps change at every level is a list nobody follows. Both panels are
   'var(--toc-width)' wide, so both indent the same way. */

:is(nav.book-toc, aside.book-toc-aside) li.h1 {
    margin-top: calc(var(--font-size) * 1.5);
    margin-bottom: calc(var(--font-size) * 1);
    padding-left: 0;
}
:is(nav.book-toc, aside.book-toc-aside) li.h2 {
    margin-top: calc(var(--font-size) * 1);
    padding-left: calc(var(--font-size) * 0.5);
}
:is(nav.book-toc, aside.book-toc-aside) li.h3 { padding-left: calc(var(--font-size) * 1.5); }
:is(nav.book-toc, aside.book-toc-aside) li.h4 { padding-left: calc(var(--font-size) * 2); }
:is(nav.book-toc, aside.book-toc-aside) li.h5 { padding-left: calc(var(--font-size) * 3); }
:is(nav.book-toc, aside.book-toc-aside) li.h6 { padding-left: calc(var(--font-size) * 4); }

/* ----------------------------------------------------------------------- */
/* ----------------------------- Abstract -------------------------------- */
/* ----------------------------------------------------------------------- */

.abstract {
    margin-left: calc(2 * var(--typography-spacing-horizontal));
    margin-right: calc(2 * var(--typography-spacing-horizontal));
    margin-top: var(--typography-spacing-vertical);
    margin-bottom: var(--typography-spacing-vertical);
    padding: var(--typography-spacing-vertical) var(--typography-spacing-horizontal);
    border-radius: var(--border-radius);
    font-size: calc(0.9 * var(--font-size));
    font-style: italic;
}

.abstract * {
    background-color: transparent;
    color: inherit;
}

.abstract h2 {
    font-style: normal;
}

/* ----------------------------------------------------------------------- */
/* ---------------------- Chapters without numbering --------------------- */
/* ----------------------------------------------------------------------- */

.chapter.nonumber {
    counter-increment: none;
}

.chapter.nonumber > h1 {
    display: block;
}

.chapter.nonumber > h1::before {
    display: none;
}

.chapter.nonumber .ssection h2::before {
    /* book.js #get_headings() includes a heading in the ToC only if
       getComputedStyle(el, '::before').content differs from 'none', '""'
       and "''". Using content: none would exclude these headings from the ToC.
       A zero-size non-breaking space (\00a0) passes the JS filter while
       remaining invisible and taking no space. */
    content: "\00a0";
    color: transparent;
    font-size: 0;
    padding: 0;
    margin: 0;
}

.chapter.nonumber .subssection h3::before {
    /* Same reason as h2::before above. */
    content: "\00a0";
    color: transparent;
    font-size: 0;
    padding: 0;
    margin: 0;
}

/* ----------------------------------------------------------------------- */
/* ------------- VISUAL DEFAULTS — @layer theme, overrideable ------------ */
/*                                                                         */
/* Theme files injected by ThemeManager are appended to <head> after this  */
/* stylesheet. Within @layer theme, later source order wins, so any theme  */
/* file that defines the same selectors will automatically override these  */
/* defaults without specificity tricks.                                    */
/* ----------------------------------------------------------------------- */

@layer theme {

    /* Chapter title: accent border, and a number written in the accent */
    .chapter > h1 {
        border-top: calc(4 * var(--border-width)) solid var(--custom-color1);
        border-bottom: calc(4 * var(--border-width)) solid var(--custom-color1);
    }

    .chapter > h1::before {
        color: var(--custom-color1);
    }

    /* Section / sub-section numbering and underline */
    .ssection h2 {
        border-bottom: var(--border-width) solid var(--h2-color);
    }

    .ssection h2::before {
        color: var(--custom-color1);
    }

    .subssection h3::before {
        color: var(--custom-color1);
    }

    /* Table of content: text color. The universal selector does not reach a
       pseudo-element, and the number of an entry is one: it is given the
       colour of the entry it numbers, and not the one of a link. */
    :is(nav.book-toc, aside.book-toc-aside) *:not([role=button]),
    :is(nav.book-toc, aside.book-toc-aside) li::before {
        color: var(--nav-fg-color);
    }

    /* Toggleable aside ToC: panel and toggle button decoration */
    @media screen {
        aside.book-toc-aside {
            background: var(--nav-bg-color);
            box-shadow: calc(var(--font-size) * 0.3) 0 calc(var(--font-size) * 1.2) var(--shadow-color);
        }

        button.book-toc-toggle {
            background: var(--nav-bg-color);
            color: var(--nav-fg-color);
            border: var(--border-width) solid var(--border-color);
        }
    }

    /* Abstract block */
    .abstract {
        background-color: var(--bg-color-alt);
        color: var(--fg-color-alt);
        box-shadow: 0 calc(var(--font-size) * 0.2) calc(var(--font-size) * 0.8) var(--shadow-color);
    }

}
