/* =============================================================================
 * print.css — WeasyPrint stylesheet for the MFB book/lexicon PDFs.
 *
 * Loaded by apps/web/src/layouts/print.astro. For A4 builds, print-format-a4.css
 * is layered on top to override page geometry only.
 *
 * Structure:
 *    1. Design tokens          (:root — typography + brand colors)
 *    2. Page setup             (@page rules: size, margins, page numbers)
 *    3. Base elements          (html, body)
 *    4. Typography             (headings, paragraphs, links, labels, quotes)
 *    5. Lists
 *    6. Tables
 *    7. Figures & images
 *    8. Cards
 *    9. Blockquotes
 *   10. YouTube card
 *   11. Table of contents
 *   12. Covers (front / inside / lexicon)
 *   13. Module intro pages
 *   14. License & donate pages
 *   15. Fragmentation (page breaks, orphans/widows, page assignment)
 *   16. Utility classes
 *   17. RTL overrides
 *
 * Conventions:
 *   - Brand colors come from the --color-* tokens; never hard-code brand hex.
 *   - Sizes use pt/mm/em for print predictability. Avoid rem: it follows the
 *     16px root, which overshoots the 10pt body (see the table font-size).
 * ========================================================================== */


/* ============================================================================
 * 1. DESIGN TOKENS
 * ========================================================================== */
:root {
  --ts-font-family: "IBM Plex Sans";

  /* Heading sizes/weights are set directly on h1–h6 in the Typography
   * section (all Medium 500), not via tokens. */

  --ts-label-size: 22px;
  --ts-label-line: 1.2;
  --ts-label-weight: 400;

  --ts-body-size: 10pt;
  --ts-body-line: 1.35;
  --ts-body-weight: 400;

  --ts-quote-line: 1;
  --ts-quote-weight: 400;

  /* Brand colors. Change these in one place to re-skin the PDFs. */
  --color-purple: #422C70;       /* primary brand purple (Student edition) */
  --color-purple-dark: #2B1C58;  /* Educator edition / strong accents */
  --color-purple-light: #5E378E; /* Purple 200 — light card background */
  --color-purple-deep: #5E378E;  /* Purple 200 — definition card background (brand defines no 4th purple) */
  --color-orange: #F7941F;       /* links and accent */
  --color-amber: #FBB040;        /* card emphasis text */
  --color-lilac: #D8D8E7;        /* blockquote attribution */
  --color-caption: #6C6C7D;      /* gray-700 — figure / video captions */
  --color-page-number: #6C6C7D;  /* gray-700 — running page numbers */
  --color-text: #25252B;         /* gray-900 — default body text */
  --color-white: #fff;
  --color-black: #000;

  /* Shared table border (used by table, th, td). */
  --border: 1pt solid var(--color-purple);

  /* Cover / module-intro geometry — sized for the A5 base page. The original
   * design targeted a ~216×286mm sheet; print-format-a4.css restores those
   * values and print-format-us-letter.css caps the heights to Letter.
   * Change formats by overriding these variables, not the rules below. */
  --cover-h: 210mm;                 /* full-bleed cover/module height (= page height) */
  --cover-centered-h: 210mm;        /* centered covers (lexicon, back cover) */
  --cover-inset: 11mm;              /* logo/meta/title/subtitle inset */
  --cover-logo-w: 24mm;
  --cover-meta-size: 10pt;
  --cover-title-top: 43mm;
  --cover-title-size: 62px;
  --cover-subtitle-bottom: 16mm;
  --cover-subtitle-inset2: 89mm;    /* opposite-side offset keeping subtitle narrow */
  --cover-subtitle-size: 21px;
  --cover-deco-h: 132mm;            /* decorative slashes SVG */
  --cover-centered-title-size: 66px;
  --cover-centered-pad: 2.75cm;
  --cover-centered-h2-size: 25px;
  --inside-flex-h: 174mm;           /* legacy centered inside cover (content area) */
  --inside-flex-title-size: 48px;
  --module-h1-top: 16mm;
  --module-inset: 15mm;
  --module-h1-size: 18px;
  --module-h2-top: 28mm;
  --module-h2-inset2: 55mm;  /* mini-TOC only — the title uses the full width */
  /* One size for every language and every program (decision 2026-07-30).
   *
   * Calibrated on **bitcoin-diploma-2610 in English**, the only edition that has
   * to hold its titles on a single line (Ben, 2026-07-31); elsewhere wrapping is
   * accepted. Its widest title, "Custom / Bitcoin As Money", measures 279pt of
   * the 347pt text box at 31px, so one line survives up to 38.5px. 36px keeps
   * ~7% of headroom — worth having, since the 26.10 content is still a draft and
   * two more characters would otherwise break the line.
   *
   * Consequences, accepted: 2610 in Spanish wraps to two lines ("Personalizado /
   * Bitcoin como dinero" would need ≤28.5px to fit), and the older diploma's
   * 30-character titles wrap too. Was 49px, where even English ran to three
   * lines. Re-measure if the trim, the insets or the 26.10 titles change. */
  --module-h2-size: 36px;
  /* The section list is anchored UNDER THE TITLE, not to the page foot
   * (2026-07-31). Bottom-anchored, it sat squarely on the supergraphic, and the
   * page carried a large empty middle.
   *
   * 54mm clears a two-line title (title top 30.5mm + 2 lines at 36px ≈ 50.5mm)
   * with 3.5mm to spare, and lands the LAST entry of the longest list — the
   * 16-section block — at ~148mm, just above the point where the graphic's
   * left-hand slash begins (152.8mm). Both numbers are measured; re-check them
   * together if either the title size or the list spacing moves. */
  --module-toc-top: 54mm;
  --module-toc-size: 13px;
  --module-bg-w: 140mm;
  --module-bg-h: 194mm;
  --matter-min-h: 170mm;            /* license / donate pages (content area) */
  --matter-pad-bottom: 16mm;
  --donate-qr: 2.75cm;
  --donate-title-size: 23px;
  --cover-logo-small: 2.75cm;
}


/* ============================================================================
 * 2. PAGE SETUP
 *
 * Base size is A5; A4 / US Letter builds override `size` via
 * print-format-a4.css / print-format-us-letter.css.
 * Named pages (full, full-bw, clean, :blank) inherit the size and only
 * customise background / page-number visibility.
 * ========================================================================== */
@page {
  size: A5;            /* 148mm × 210mm */
  margin-top: 18mm;
  margin-bottom: 18mm;
  marks: none;         /* KDP rejects crop marks */
  bleed: 0;            /* bleed is already included in the page size */
}

/* Recto (odd) pages: binding is on the left, so the inner (left) margin is
 * larger than the outer (right) margin. T R B L. */
@page :right {
  margin: 15mm 12mm 14mm 15mm;

  @bottom-right {
    content: counter(page);
    position: absolute;
    margin-top: 0.2in;
    margin-bottom: 0.625in;
    z-index: -1;
    color: var(--color-page-number);
    font-size: 8pt;
  }
}

/* Verso (even) pages: binding is on the right, so the inner (right) margin is
 * larger than the outer (left) margin. T R B L. */
@page :left {
  margin: 15mm 15mm 14mm 12mm;

  @bottom-left {
    content: counter(page);
    position: absolute;
    margin-top: 0.2in;
    margin-bottom: 0.625in;
    z-index: -1;
    color: var(--color-page-number);
    font-size: 8pt;
  }
}

/* Full-bleed purple page (front cover, module intros). No margins/counters. */
@page full {
  background: var(--color-purple);
  margin: 0;

  @bottom-right { content: none; }
  @bottom-left { content: none; }
}

/* Full-bleed white page (inside cover). Mirrors @page full without the paint. */
@page full-bw {
  background: var(--color-white);
  margin: 0;

  @bottom-right { content: none; }
  @bottom-left { content: none; }
}

/* Intentionally blank pages: no page numbers. */
@page :blank {
  @bottom-right { content: none; }
  @bottom-left { content: none; }
}

/* Clean front/back-matter pages (license, main TOC): no page numbers. */
@page clean {
  @bottom-right { content: none; }
  @bottom-left { content: none; }
}


/* ============================================================================
 * 3. BASE ELEMENTS
 * ========================================================================== */
html {
  counter-reset: h2-counter;
  color: var(--color-black);
  font-family: var(--ts-font-family);
  hyphens: auto;
  -webkit-hyphens: auto;
}

body {
  margin: 0;
  font-family: var(--ts-font-family);
  font-size: var(--ts-body-size);
  line-height: var(--ts-body-line);
  font-weight: var(--ts-body-weight);
  /* Justify is applied only to prose paragraphs (see `p` below), NOT globally:
   * a document-wide `justify` cascades into headings, card/video titles, TOC
   * links (whose page number floats right) and other short/labels, and any
   * that wrap get their words stretched edge-to-edge. Default the rest to
   * start (direction-aware) so those read left-aligned and snug. */
  text-align: start;
  hyphens: auto;
  orphans: 2;
  widows: 2;
  color: var(--color-text);
}


/* ============================================================================
 * 4. TYPOGRAPHY
 * ========================================================================== */
/* All headings are Medium (brand book §4.2 shows H1–H6 as IBM Plex Sans
 * Medium). h4–h6 need the explicit weight or they fall back to WeasyPrint's
 * UA default of bold (700) and render heavier than Medium. */
h1, h2, h3, h4, h5, h6 {
  font-weight: 500;
}

h1, h2, h3 {
  line-height: 1.2;
}

h1 { font-size: 2.2rem; }
h2 { font-size: 1.6rem; }
h3 { font-size: 1.2rem; }
h4 { font-size: 1.2rem; }
h5 { font-size: 1.1rem; }
h6 { font-size: 1.0rem; }

/* h1/h2 keep the body color; h3–h6 use brand purple. */
h3, h4, h5, h6 {
  color: var(--color-purple);
}

/* Heading vertical rhythm.
 * Top margin > bottom margin: a heading "belongs" to the content that
 * follows it, so it sits tight to the body below and decoupled from the
 * section above. WeasyPrint's default h4–h6 margins (~1.33–1.67em) are
 * disproportionate on this compact scale, so they're set explicitly. */
h1 { margin-top: 0.85em; margin-bottom: 0.25em; }
h2 { margin-top: 0.95em; margin-bottom: 0.30em; }
h3 { margin-top: 1.65em; margin-bottom: 0.25em; }
h4 { margin-top: 1.45em; margin-bottom: 0.25em; }
h5 { margin-top: 1.35em; margin-bottom: 0.25em; }
h6 { margin-top: 1.40em; margin-bottom: 0.25em; }

/* Keep headings with the content that follows them. */
h1, h2, h3, h4 {
  break-after: avoid;
}

/* Headings at the top of a page (auto break or first child) should carry no
 * top margin. `margin-break: auto` truncates the top margin at fragmentation
 * breaks, preserving sibling-section rhythm without stripping it everywhere. */
h1, h2, h3, h4, h5, h6 {
  margin-break: auto;
  padding-top: 0;
}

hr.pagebreak + h4 {
  margin-top: 0;
  padding-top: 0;
}

p {
  text-align: justify;
  margin: 0 0 0.6em;
}

strong {
  color: var(--color-purple-dark);
}

p strong,
.card .content strong {
  font-weight: 600;
}

a {
  color: var(--color-orange);
}

label,
.label {
  font-family: var(--ts-font-family);
  font-size: var(--ts-label-size);
  line-height: var(--ts-label-line);
  font-weight: var(--ts-label-weight);
}

.body-text {
  font-family: var(--ts-font-family);
  font-size: var(--ts-body-size);
  line-height: var(--ts-body-line);
  font-weight: var(--ts-body-weight);
}


/* ============================================================================
 * 5. LISTS
 * ========================================================================== */
ul {
  margin-top: 0.4em;
  margin-bottom: 0.5em;
  padding-left: 1.3em;
}

ul li {
  margin-bottom: 0.15em;
}

/* Task lists (`- [ ] …` → listItem "task"), rendered by the web's
 * TaskList/TaskListItem components. The box is a bordered ::before rather than
 * a character such as ☐ — WeasyPrint only has the faces embedded below, and a
 * missing glyph prints as tofu. Mirrors the screen rule in
 * apps/web/src/styles/global.css. */
ul.mfb-task-list {
  list-style: none;
  padding-left: 0;
}

ul.mfb-task-list .mfb-task-item::before {
  content: "";
  display: inline-block;
  width: 0.7em;
  height: 0.7em;
  margin-right: 0.5em;
  border: 0.5pt solid currentColor;
  border-radius: 1pt;
}

ul.mfb-task-list .mfb-task-item.is-checked::before {
  background: currentColor;
}


/* ============================================================================
 * 6. TABLES
 *
 * Tables come from the web Table.astro component, which adds `.mfb-table`
 * (inside a `.mfb-table-wrapper`) and ships screen styles with larger type
 * and padding. The print rules below redefine table typography and then
 * re-apply it through `body .mfb-table` so it wins over the component CSS.
 * ========================================================================== */
table {
  width: 100%;
  margin: 1.2em 0;
  border: var(--border);
  border-collapse: collapse;
  /* pt, not rem: rem follows the ~16px root and overshoots the 10pt body. */
  font-size: 8.5pt;
  line-height: 1.25;
  overflow: hidden;
}

th, td {
  padding: 2pt 4pt;
  vertical-align: top;
}

th {
  text-align: center;
  background-color: var(--color-purple);
  color: var(--color-white);
  border-bottom: var(--border);
}

td {
  color: var(--color-black);
}

/* Repeat the header row at the top of each page a table spans. */
thead {
  display: table-header-group;
}

/* No hyphenation inside cells so content stays readable. */
table,
table th,
table td {
  hyphens: none;
  -webkit-hyphens: none;
  word-break: normal;
  overflow-wrap: normal;
}

/* Portable Text inside cells inherits the table type instead of body h1–h6
 * rem sizes (which would blow cells out). */
table :is(th, td) :is(h1, h2, h3, h4, h5, h6) {
  font-size: inherit;
  line-height: inherit;
  font-weight: 600;
  margin: 0;
  color: inherit;
}

table thead :is(th, td) :is(h1, h2, h3, h4, h5, h6) {
  font-weight: inherit;
  color: inherit;
}

table :is(th, td) :is(p, ul, ol, li, span, strong, em, a) {
  font-size: inherit;
  line-height: inherit;
}

/* Inner grid: right border on every column but the last. */
table th:not(:last-child),
table td:not(:last-child) {
  border-right: var(--border);
}

/* Inner grid: bottom border on every row but the last. */
table > thead > tr:not(:last-child) > th,
table > thead > tr:not(:last-child) > td,
table > tbody > tr:not(:last-child) > th,
table > tbody > tr:not(:last-child) > td,
table > tfoot > tr:not(:last-child) > th,
table > tfoot > tr:not(:last-child) > td,
table > tr:not(:last-child) > td,
table > tr:not(:last-child) > th,
table > thead:not(:last-child),
table > tbody:not(:last-child),
table > tfoot:not(:last-child) {
  border-bottom: var(--border);
}

/* Neutralise the screen-only frame Table.astro wraps around every table;
 * print.css already owns the table's border. `body` prefix lifts specificity
 * above the component's injected styles. */
body .mfb-table-wrapper {
  border: none;
  border-radius: 0;
  background: transparent;
  overflow: visible;
  margin: 0;
  padding: 0;
}

/* Re-apply print table typography over the component's screen styles. */
body .mfb-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 8.5pt;
  line-height: 1.25;
}

body .mfb-table th,
body .mfb-table td {
  padding: 2pt 4pt;
  vertical-align: top;
}


/* ============================================================================
 * 7. FIGURES & IMAGES
 * ========================================================================== */
figure > figcaption {
  font-size: 0.8em;
  color: var(--color-caption);
}

/* Prevent images from overflowing their figure container (e.g. a figure at
 * width: 80% narrower than the image's natural width). */
figure > img {
  max-width: 100%;
  height: auto;
}

figure.align-right {
  float: right;
}

/* Left-floated figure. Tight margins keep the float area close to the image
 * height so the next paragraph's first line isn't trapped beside it. */
figure.align-left {
  float: left;
  margin: 0 1em 0 0;
}

/* Nudge the image down by the first line's half-leading so its top aligns with
 * the cap-height of the wrapped text. */
figure.align-left > img {
  margin-top: 0.22em;
}

/* Centered figures get a generous bottom margin so a following heading never
 * looks cramped after margin-collapse. */
figure.align-center {
  display: block;
  margin: 0 auto 2.2em;
  text-align: center;
}

figure.align-center > img {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

.layout-narrow {
  width: 30%;
}

.layout-half {
  width: 3.205in;
}

figure.layout-full,
figure.layout-full > img {
  width: 100%;
  margin-left: 0;
  margin-right: 0;
}

/* Per-figure percentage width from Sanity's `customWidth` (1–100%), piped in
 * as `--fig-width` on the element so the HTML carries data, not styling. */
figure.layout-custom {
  width: var(--fig-width, 100%);
}

/* Micrographic blocks: self-contained HTML/CSS from the design library. The
 * block's own stylesheet (scoped under .mg-<slug>) sizes and styles it; this
 * only sets the outer wrapper defaults and keeps it from splitting across a
 * page break. */
.micrographic {
  break-inside: avoid;
  margin: 1.2em 0;
}
.micrographic > .micrographic-caption {
  font-size: 0.8em;
  color: var(--color-caption);
  margin-top: 0.4em;
}

/* Per-placement size (micrographicRef.size). Non-full widths center in the
 * content column; full-page gets its own printed page. */
.micrographic--half {
  width: 50%;
  margin-inline: auto;
}
.micrographic--narrow {
  width: 33%;
  margin-inline: auto;
}
.micrographic--custom {
  width: var(--mg-width, 100%);
  margin-inline: auto;
}
.micrographic--full-page {
  width: 100%;
  break-before: page;
  break-after: page;
}


/* ============================================================================
 * 8. CARDS
 * ========================================================================== */
.card {
  margin-top: 1.2em;
  margin-bottom: 1.2em;
  background: var(--color-purple-dark);
  color: var(--color-white);
}

.card strong {
  color: var(--color-white);
}

.card.light {
  background: var(--color-purple-light);
  color: var(--color-white);
}

.card.dark {
  background: var(--color-purple-dark);
  color: var(--color-white);
}

.card.callout {
  background: var(--color-purple);
  color: var(--color-white);
}

.card.definition {
  background: var(--color-purple-deep);
  color: var(--color-white);
}

.card > header {
  padding: 1em 1.5em 0.2em;
}

.card > header > h6,
.card.dark > header > h6,
.card.light > header > h6 {
  color: var(--color-white);
  margin: 0;
}

.card.light > header,
.card.light > header > strong {
  color: var(--color-black);
}

.card .content {
  padding: 1em 1.5em;
  /* Even short cards keep the height of a two-line block. */
  min-height: 2.8em;
}

.card .content p {
  margin: 0;
}

.card .content em {
  font-style: normal;
  color: var(--color-amber);
}

/* Clear floated icons so short cards don't clip them. */
.card .content::after {
  content: "";
  display: block;
  clear: both;
}

/* Card icon: matched to two body lines (2 × 1.4 line-height = 2.8em). */
.card > div.content > img {
  float: left;
  display: block;
  margin-right: 1em;
  margin-left: -5px;
  width: 2.8em;
  height: 2.8em;
  max-width: none;
  max-height: none;
  object-fit: contain;
}


/* ============================================================================
 * 9. BLOCKQUOTES
 * ========================================================================== */
blockquote,
.quote {
  font-family: var(--ts-font-family);
  font-size: var(--ts-body-size);
  line-height: var(--ts-quote-line);
  font-weight: var(--ts-quote-weight);
}

blockquote {
  margin: 0.8em 0 1em;
  padding: 0.9em 1.5em;
  background: var(--color-purple);
  color: var(--color-white);
  font-size: 1em;
  font-weight: 700;
}

blockquote strong {
  color: var(--color-white) !important;
}

/* Attribution line (rendered from emphasis), centered under the quote. */
blockquote em {
  display: inline-block;
  padding-top: 0.5em;
  color: var(--color-lilac);
  text-align: center;
  font-style: normal;
  font-weight: 400;
}

blockquote em::before {
  content: "— ";
}


/* ============================================================================
 * 10. YOUTUBE CARD
 *
 * Compact horizontal block: thumbnail (left), title + caption (middle),
 * QR code (right). A standalone <figure>, not a `.card`.
 * ========================================================================== */
figure.youtube-card {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0.8em;
  width: 100%;
  box-sizing: border-box;
  padding: 0.6em;
  margin: 1em 0;
  border: 1pt solid var(--color-purple);
  border-radius: 2px;
  page-break-inside: avoid;
}

figure.youtube-card > .yt-thumb {
  position: relative;
  display: block;
  flex: 0 0 auto;
  /* Height matches the QR box (80px); width keeps the 16:9 thumbnail ratio. */
  width: 142px;
  height: 80px;
  overflow: hidden;
  border-radius: 2px;
  line-height: 0;
}

figure.youtube-card > .yt-thumb > img {
  display: block;
  width: 100%;
  height: 100%;
  margin: 0;
  object-fit: cover;
}

figure.youtube-card > .yt-thumb > .yt-play {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 32px;
  height: 32px;
  margin: -16px 0 0 -16px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  border: 1pt solid var(--color-purple);
}

figure.youtube-card > .yt-thumb > .yt-play::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 55%;
  width: 0;
  height: 0;
  margin: -7px 0 0 -5px;
  border-style: solid;
  border-width: 7px 0 7px 11px;
  border-color: transparent transparent transparent var(--color-orange);
}

figure.youtube-card > .yt-text {
  flex: 1 1 auto;
  min-width: 0;
}

figure.youtube-card > .yt-text > .yt-title {
  margin: 0;
  font-weight: 600;
  font-size: 0.95em;
  line-height: 1.25;
  color: var(--color-purple-dark);
}

figure.youtube-card > .yt-text > .yt-caption {
  margin: 0.35em 0 0;
  font-size: 0.85em;
  line-height: 1.35;
  color: var(--color-caption);
}

figure.youtube-card > .yt-qr {
  flex: 0 0 auto;
  width: 80px;
  height: 80px;
  padding: 2px;
  border: 0.5pt solid var(--color-purple);
  border-radius: 2px;
  box-sizing: border-box;
  line-height: 0;
}

figure.youtube-card > .yt-qr > a,
figure.youtube-card > .yt-qr > a > img {
  display: block;
  width: 100%;
  height: 100%;
  margin: 0;
}


/* ============================================================================
 * 11. TABLE OF CONTENTS
 * ========================================================================== */
section.toc ul > li {
  list-style-type: none;
}

/* Each entry is a block that RESERVES the page-number column on its right
 * (`--toc-num-col`), so a long title wraps before it reaches the number
 * instead of running underneath it. The number itself is positioned into that
 * reserved gutter, aligned with the entry's last line. It used to be a
 * `float: right` on the `::after`, which only claims space on the line where
 * the float is placed (the last one) — the first line of a two-line title had
 * nothing stopping it ("2.15 … actividades de compraventa" collided with "49",
 * 2026-09-21). */
section.toc ul > li > a {
  display: block;
  position: relative;
  padding-top: 0.15em;
  padding-bottom: 0.15em;
  padding-right: var(--toc-num-col, 3em);
  /* A block inherits the body's `hyphens: auto`; an index entry must wrap on
   * whole words ("… de compraventa" / "ni de promoción"), not "pro-moción". */
  hyphens: manual;
  text-decoration: none;
  color: var(--color-black);
}

section.toc ul > li > a::after {
  content: target-counter(attr(href), page);
  position: absolute;
  right: 0;
  bottom: 0.15em;
  font-size: 12pt;
}

/* The appendix intro page is a visual opener, not a navigational index, so
 * its mini-TOC links don't show page numbers (the main TOC fills that role). */
section#appendices section.toc ul > li > a {
  padding-right: 0;
}

section#appendices section.toc ul > li > a::after {
  content: none;
}

.toc ul li {
  background-image: none;
  padding-top: 0.25em;
  padding-bottom: 0.25em;
}

.toc h5 {
  margin-bottom: 0;
  padding-bottom: 0;
}

/* Main book TOC: title flush to the top, space below only. */
section.toc.main-toc > h2 {
  margin-top: 0;
  margin-bottom: 0.85em;
}

/* Main book TOC: keep each list on a single page. */
section.toc.main-toc ul {
  break-inside: avoid;
  page-break-inside: avoid;
}


/* ============================================================================
 * 12. COVERS (front / inside / lexicon)
 * ========================================================================== */
/* Centered cover layouts (lexicon, back cover). Explicit mm heights because
 * WeasyPrint doesn't grow flex containers via vh/min-height. */
section.fullpage.cover {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: var(--cover-centered-h);
  text-align: center;
  box-sizing: border-box;
}

section.inside-cover {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: var(--inside-flex-h); /* content area with default @page margins */
  text-align: center;
  box-sizing: border-box;
}

section.fullpage.cover > *,
section.inside-cover > * {
  position: relative;
  z-index: 2;
}

/* Centered cover headings. */
.cover h1 {
  font-size: var(--cover-centered-title-size);
  font-weight: 500;
  padding-left: var(--cover-centered-pad);
  padding-right: var(--cover-centered-pad);
}

.cover h2 {
  font-size: var(--cover-centered-h2-size);
  font-weight: 400;
  padding-left: 0;
  padding-right: 0;
}

/* White !important protects the centered cover layouts (lexicon covers render
 * in-flow <h1>/<h2>). The inside cover reuses front-cover markup but stays
 * black on white, so it's excluded. */
.cover:not(.inside-cover) h1,
.cover:not(.inside-cover) h2 {
  color: var(--color-white) !important;
}

.inside-cover h1 {
  font-size: var(--inside-flex-title-size);
  padding-left: 0;
  padding-right: 0;
}

.inside-cover h2 {
  font-size: var(--cover-centered-h2-size);
  font-weight: 400;
}

section.inside-cover h2 {
  padding-left: 0;
  padding-right: 0;
}

/* --- Front cover ----------------------------------------------------------
 * Asymmetric layout: logo top-left, book label top-right, title
 * upper-left, subtitle bottom-left, decorative slashes bottom-right.
 * Children are absolutely positioned to escape the flex centering above. */
section.fullpage.cover.front-cover {
  display: block;
  position: relative;
  width: 100%;
  height: var(--cover-h);
  padding: 0;
  overflow: hidden;
  text-align: left;
  color: var(--color-white);
}

/* Educator edition repaints the cover with the darker purple. */
section.fullpage.cover.front-cover.cover-educator {
  background-color: var(--color-purple-dark);
}

section.fullpage.cover.front-cover > * {
  position: absolute;
  z-index: 2;
}

section.fullpage.cover.front-cover .fc-logo {
  top: var(--cover-inset);
  left: var(--cover-inset);
  display: block;
  line-height: 0;
}

section.fullpage.cover.front-cover .fc-logo > img {
  width: var(--cover-logo-w);
  height: auto;
}

section.fullpage.cover.front-cover .fc-meta {
  top: var(--cover-inset);
  right: var(--cover-inset);
  text-align: right;
  color: var(--color-white);
  font-size: var(--cover-meta-size);
  line-height: 1.3;
}

section.fullpage.cover.front-cover .fc-book {
  font-weight: 400;
}

section.fullpage.cover.front-cover .fc-version {
  font-weight: 400;
}

section.fullpage.cover.front-cover .fc-title {
  top: var(--cover-title-top);
  left: var(--cover-inset);
  right: var(--cover-inset);
  margin: 0;
  padding: 0;
  color: var(--color-white);
  font-size: var(--cover-title-size);
  font-weight: 500;
  line-height: 1.05;
  letter-spacing: -0.01em;
  hyphens: manual;
  -webkit-hyphens: manual;
}

section.fullpage.cover.front-cover .fc-subtitle {
  bottom: var(--cover-subtitle-bottom);
  left: var(--cover-inset);
  right: var(--cover-subtitle-inset2);
  margin: 0;
  padding: 0;
  color: var(--color-white);
  font-size: var(--cover-subtitle-size);
  font-weight: 400;
  line-height: 1.25;
  text-align: left;
  hyphens: manual;
  -webkit-hyphens: manual;
}

/* Decorative slashes (Group 195 SVG) anchored bottom-right; cropped by the
 * cover's `overflow: hidden`. */
section.fullpage.cover.front-cover .fc-deco {
  right: 0;
  bottom: 0;
  width: auto;
  height: var(--cover-deco-h);
  z-index: 1;
  pointer-events: none;
}

/* --- Inside cover ---------------------------------------------------------
 * Black-and-white variant of the front cover (same layout, rendered via
 * @page full-bw). Kept separate from the front-cover rules so color
 * overrides stay explicit and the layouts can diverge later. */
section.fullpage.cover.inside-cover {
  display: block;
  position: relative;
  width: 100%;
  height: var(--cover-h);
  padding: 0;
  overflow: hidden;
  text-align: left;
  color: var(--color-black);
  background-color: var(--color-white);
  page: full-bw;
}

section.fullpage.cover.inside-cover > * {
  position: absolute;
  z-index: 2;
}

section.fullpage.cover.inside-cover .fc-logo {
  top: var(--cover-inset);
  left: var(--cover-inset);
  display: block;
  line-height: 0;
}

section.fullpage.cover.inside-cover .fc-logo > img {
  width: var(--cover-logo-w);
  height: auto;
}

section.fullpage.cover.inside-cover .fc-meta {
  top: var(--cover-inset);
  right: var(--cover-inset);
  text-align: right;
  color: var(--color-black);
  font-size: var(--cover-meta-size);
  line-height: 1.3;
}

section.fullpage.cover.inside-cover .fc-book {
  font-weight: 400;
}

section.fullpage.cover.inside-cover .fc-version {
  font-weight: 400;
}

section.fullpage.cover.inside-cover .fc-title {
  top: var(--cover-title-top);
  left: var(--cover-inset);
  right: var(--cover-inset);
  margin: 0;
  padding: 0;
  color: var(--color-black);
  font-size: var(--cover-title-size);
  font-weight: 500;
  line-height: 1.05;
  letter-spacing: -0.01em;
  hyphens: manual;
  -webkit-hyphens: manual;
}

section.fullpage.cover.inside-cover .fc-subtitle {
  bottom: var(--cover-subtitle-bottom);
  left: var(--cover-inset);
  right: var(--cover-subtitle-inset2);
  margin: 0;
  padding: 0;
  color: var(--color-black);
  font-size: var(--cover-subtitle-size);
  font-weight: 400;
  line-height: 1.25;
  text-align: left;
  hyphens: manual;
  -webkit-hyphens: manual;
}

/* --- Full-bleed background layers ----------------------------------------- */
.gradient {
  background-color: var(--color-purple);
}

.fullpage div.gradient,
.fullpage .module {
  position: absolute;
  bottom: 0;
  left: 0;
  width: var(--module-bg-w);
  height: var(--module-bg-h);
  margin: 0;
  max-width: none;
  object-fit: cover;
  z-index: 1;
}

/* --- Lexicon cover --------------------------------------------------------
 * The lexicon keeps the original centered cover layout. These classes
 * replace the per-element inline styles that used to handle spacing/badging. */
.lex-cover-title {
  margin-bottom: 0.4em;
}

.lex-cover-subtitle {
  font-size: 19pt;
  font-style: normal;
  border-radius: 8pt;
  padding: 0.5em 0.8em;
}

.lex-cover-language {
  font-size: 12pt;
  border-radius: 8pt;
  padding: 0.5em 0.8em;
}

/* Small centered logo (4cm) on the book back cover and lexicon covers. */
.cover-logo-small {
  width: var(--cover-logo-small);
}


/* ============================================================================
 * 13. MODULE INTRO PAGES
 *
 * Share the cover's asymmetric layout — module label top-left, large title,
 * mini-TOC bottom-left, slashes bottom-right — but on WHITE, not the cover's
 * solid purple (changed 2026-07-30). A dark full-page field recurring every
 * module prints heavily and goes muddy in greyscale; the purple survives as ink
 * and as the tinted supergraphic. Children are absolutely positioned.
 * ========================================================================== */
section.fullpage.module {
  display: block;
  position: relative;
  width: 100%;
  height: var(--cover-h);
  padding: 0;
  overflow: hidden;
  text-align: left;
  /* Light, not the cover's purple: a full-page dark field prints heavily and
   * turns muddy in black and white, which is how the low-cost edition will be
   * printed (MFB-155). The front cover stays purple — it is one sheet and it is
   * the shelf face; a divider recurs every module. */
  color: var(--color-purple);
  background-color: var(--color-white);
}

/* Educator books keep their distinction through the darker purple ink and their
 * own supergraphic, rather than through a darker background. */
section.fullpage.module.module-educator {
  color: var(--color-purple-dark);
}

section.fullpage.module > * {
  position: absolute;
  z-index: 2;
}

section.fullpage.module h1,
section.fullpage.module h2,
section.fullpage.module p,
section.fullpage.module li,
section.fullpage.module strong,
section.fullpage.module a {
  color: inherit;
}

/* The supergraphic stays as the brand signature, tinted back so it reads on white
 * instead of competing with the title. The SVG carries a fixed `fill="#5E378E"`,
 * so opacity is the lever — no second asset to keep in step with the first.
 *
 * 20% was chosen against rendered samples (Ben, 2026-07-31): 12% read as a faint
 * watermark rather than the cover's motif, 30% weighed the page down. Sizes,
 * position and artwork are the cover's; the tint is the one deliberate
 * difference, because the cover puts this shape on purple and a divider puts it
 * on white. */
section.fullpage.module .fc-deco {
  opacity: 0.2;
}

/* "Module N" label. */
section.fullpage.module h1 {
  top: var(--module-h1-top);
  left: var(--module-inset);
  right: var(--module-inset);
  margin: 0;
  padding: 0;
  font-size: var(--module-h1-size);
  font-weight: 400;
  line-height: 1;
  letter-spacing: 0;
}

/* Module title.
 *
 * Uses the FULL text width (`--module-inset` on both sides), not the narrow
 * `--module-h2-inset2` the mini-TOC needs. That inset exists to clear the
 * bottom-right supergraphic — but the graphic starts around 85mm down the page
 * while the title sits at ~30mm, so the title was being squeezed into 82mm of a
 * 152mm page for a collision that cannot happen. Widening it is most of what
 * makes a title fit on one line.
 *
 * `--module-h2-size` is deliberately ONE size for every language: an English
 * title fits on a single line and the longest translated one (55 chars) takes at
 * most two. A per-language size would make the same book look different in each
 * edition. See the token for how it is calibrated. */
section.fullpage.module h2 {
  top: var(--module-h2-top);
  left: var(--module-inset);
  right: var(--module-inset);
  margin: 0;
  padding: 0;
  font-size: var(--module-h2-size);
  font-weight: 500;
  line-height: 1.05;
  letter-spacing: -0.01em;
  hyphens: manual;
  -webkit-hyphens: manual;
}

/* Mini table of contents, sitting directly under the title (2026-07-31).
 *
 * It used to be anchored to the page foot with a narrow right inset. That put it
 * inside the supergraphic — the 26.10 blocks carry 12 to 16 sections, so the
 * list ran straight across the slashes — while the middle of the page stayed
 * empty. Anchored under the title it reads in order (label → title → contents)
 * and, with the graphic now confined to the bottom corner, it also gets the
 * FULL width, so entries like "1.10 Central Bank Digital Currencies (CBDCs)"
 * stop wrapping. */
section.fullpage.module > .toc {
  top: var(--module-toc-top);
  left: var(--module-inset);
  right: var(--module-inset);
}

section.fullpage.module > .toc > ul {
  margin: 0;
  padding: 0;
  background: transparent;
  list-style: none;
}

section.fullpage.module > .toc > ul > li {
  margin: 0;
  /* Tight on purpose: the list's leading is the only lever left for lifting
   * entries clear of the supergraphic. `--module-toc-top` cannot rise above
   * ~53mm without meeting a two-line title (Spanish block 4), so every
   * millimetre comes from here — 0.10em of padding with 1.36 leading is ~0.58mm
   * per entry against the original 0.18em/1.45, which lifts the tenth entry
   * 5.3mm and the last one 8.7mm. */
  padding: 0.10em 0;
  background: none;
  font-size: var(--module-toc-size);
  line-height: 1.36;
  /* Index entries wrap on whole words, never "doble gas-to" (the body sets
   * `hyphens: auto`). Same rule as the main TOC's entries. */
  hyphens: manual;
  /* `inherit`, not white: this rule is more specific than the section's text
   * colour, so hardcoding white here rendered the whole mini-TOC white on the
   * new white background — the list vanished from every divider. */
  color: inherit;
}

/* Fixed-width "N.M" column so titles line up. */
section.fullpage.module > .toc > ul > li > .toc-num {
  display: inline-block;
  width: 2.6em;
  font-weight: 400;
}

section.fullpage.module .fc-deco {
  right: 0;
  bottom: 0;
  /* Identical to the cover — same artwork, same size, same corner — so a divider
   * reads as part of the same design. Neither shrunk nor cropped: both were
   * tried (2026-07-31) and both weakened it. */
  width: auto;
  height: var(--cover-deco-h);
  z-index: 1;
  pointer-events: none;
}


/* ============================================================================
 * 14. LICENSE & DONATE PAGES
 * ========================================================================== */
/* Copyright + CC BY-SA verso: notice and badge sit at the foot of the page. */
section.license-page {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: var(--matter-min-h);
  box-sizing: border-box;
  break-after: page;
}

section.license-page .license-page__footer {
  text-align: left;
  max-width: 100%;
}

section.license-page .license-page__text {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0.6em;
  margin: 0;
  color: var(--color-black);
  font-size: 13px; /* match back matter */
}

section.license-page .license-page__text .left.license-badge {
  float: none;
  margin: 0;
  flex-shrink: 0;
  width: auto;
}

/* Creative Commons license badge (88×31 image). */
.license-badge {
  height: 1.05cm;
  width: auto;
}

/* Donate + QR block: B&W frame, flat fills, uniform border. */
.donate-block {
  display: inline-block;
  box-sizing: border-box;
  width: auto;
  margin: 0 auto;
  padding: 0.45cm 0.4cm 0.5cm;
  text-align: center;
  vertical-align: top;
  border: 1.5pt solid var(--color-black);
  border-radius: 0;
  background: var(--color-white);
  color: var(--color-black);
  -webkit-print-color-adjust: exact;
}

.donate-block a {
  color: var(--color-black);
  text-decoration: none;
}

.donate-block .donate-qr {
  display: block;
  width: var(--donate-qr);
  height: var(--donate-qr);
  margin: 0;
}

.donate-block .donate-title {
  display: block;
  width: var(--donate-qr);
  margin: 0 0 0.4em;
  padding: 0;
  color: var(--color-black);
  font-size: var(--donate-title-size);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.01em;
  text-align: center;
}

/* Inside-cover donate block, bottom-right (matches fc-meta inset). */
section.fullpage.cover.inside-cover .inside-cover__donate {
  position: absolute;
  top: auto;
  bottom: var(--cover-subtitle-bottom);
  left: auto;
  right: var(--cover-inset);
  margin: 0;
  z-index: 3;
  width: auto;
  max-width: 100%;
  text-align: center;
}

/* Standalone donate + QR page (B&W only, no accent fills). */
section.inner-cover-donate {
  page: clean;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: flex-end;
  min-height: var(--matter-min-h);
  padding: 0 var(--cover-inset) var(--matter-pad-bottom) var(--cover-inset);
  break-after: page;
  box-sizing: border-box;
  background: var(--color-white);
  color: var(--color-black);
  -webkit-print-color-adjust: exact;
}


/* ============================================================================
 * 15. FRAGMENTATION (page breaks, page assignment, orphans/widows)
 * ========================================================================== */
/* Book sections live in sibling <article class="section"> blocks. The gap
 * before a title comes from the article's top margin (not h3 margin-top, which
 * stays 0 so a section starting a page sits flush). margin-break trims that
 * top margin at page breaks. */
article.section {
  margin-break: auto;
}

article.section + article.section {
  margin-top: 2em;
}

/* Front matter: no gap above the title; space below only. */
article[id^="frontmatter-"] {
  margin-top: 0;
}

article.section + article.section[id^="frontmatter-"],
article[id^="frontmatter-"] + article.section {
  margin-top: 0;
}

/* A section's own title must outrank the subheadings inside it. Both are <h3>:
 * the title from BookDocument, and every in-content heading that came from a
 * `###` in the source Markdown (import-md maps heading levels straight through,
 * and PortableContent uses astro-portabletext's default h3 → <h3>). At the same
 * 1.2rem they read as siblings, so a section like "Welcome To The Bitcoin
 * Diploma" looked no more important than its own "About Us" subheading.
 *
 * Fixed here rather than in the source Markdown, because demoting those `###`
 * to `####` would not have helped — print's h3 and h4 are both 1.2rem, so the
 * two levels are visually identical anyway. Sized between h2 (1.6rem) and h3
 * (1.2rem) so a section title still sits clearly below a module title. Colour
 * stays brand purple, as for any h3. `:first-of-type` is what separates the
 * title from the in-content headings — PortableContent emits them as siblings,
 * not inside a wrapper. */
article.section > h3:first-of-type {
  font-size: 1.4rem;
  margin-top: 0;
  margin-bottom: 0.25em;
}

article[id^="frontmatter-"] > h3:first-of-type {
  margin-top: 0;
  margin-bottom: 0.85em;
}

/* Activity metadata box styling lives in ActivityHeader.astro (scoped <style>,
   inlined into this print route too). In print it drops the border/background
   and prioritizes readability. Keep the activity title with its content so the
   heading is never orphaned at the bottom of a page. */
article.section.activity > h3 {
  break-after: avoid;
  page-break-after: avoid;
}

/* Section-level page breaks. */
section.toc,
section.fullpage,
section.inside-cover {
  break-after: page;
}

section.module {
  break-before: right;
}

.fullpage {
  page: full;
}

/* Module dividers are white since 2026-07-30, so they must not sit on the purple
 * `full` page. The section covers the sheet only when `--cover-h` equals the page
 * height — true for 6×9 and Letter, but A4 caps it 11.25mm short, which would
 * show as a purple band at the foot of every divider. `full-bw` is the white
 * full-bleed page and suppresses folios the same way. */
section.fullpage.module {
  page: full-bw;
}

.fullpage:last-child {
  break-before: left;
}

/* Front/back-matter pages don't show running page numbers; numbering begins
 * on the first content page after the TOC. */
section.license-page,
section.toc.main-toc {
  page: clean;
}

hr.pagebreak {
  break-after: page;
  visibility: hidden;
}

/* Keep these blocks intact across page boundaries. */
.card,
blockquote,
table {
  page-break-inside: avoid;
  break-inside: avoid;
}

p,
li {
  orphans: 2;
  widows: 2;
}


/* ============================================================================
 * 16. UTILITY CLASSES
 * ========================================================================== */
.black { color: var(--color-black); }
.white { color: var(--color-white); }
.orange { color: var(--color-orange); }
.color { color: var(--color-purple); }
.bgcolor { background-color: var(--color-purple); }
.center { text-align: center; }
.right { float: right; }
.left { float: left; }

ul.white li strong {
  color: var(--color-white);
}

/* Bold, upright numbering prefix in the TOC ("1.2 Section title"). */
.toc-subnum {
  font-weight: 600;
  font-style: normal;
}

/* Appendix links: bolder than body links so the label stands out. */
.appendix-link {
  font-weight: 700;
}

/* QR code image (generated in QRCode.astro). Fixed height keeps it scannable. */
.qr img {
  height: 120px;
}

hr {
  border: none;
  border-top: 1.2px solid var(--color-purple-dark);
  margin-top: 1em;
}


/* ============================================================================
 * 17. RTL OVERRIDES
 *
 * Print mirror for RTL locales (`dir="rtl"` from isRtlLocale): mirror the
 * asymmetric cover/module layouts and keep TOC / front matter in reading flow.
 * ========================================================================== */
html[dir="rtl"] ul {
  padding-left: 0;
  padding-right: 1.3em;
}

html[dir="rtl"] section.toc ul > li > a::after {
  float: left;
}

html[dir="rtl"] section.license-page .license-page__footer {
  text-align: right;
}

html[dir="rtl"] section.license-page .license-page__text {
  flex-direction: row-reverse;
}

html[dir="rtl"] section.inner-cover-donate {
  align-items: flex-start;
}

html[dir="rtl"] section.fullpage.cover.front-cover,
html[dir="rtl"] section.fullpage.cover.inside-cover,
html[dir="rtl"] section.fullpage.module {
  text-align: right;
}

html[dir="rtl"] section.fullpage.cover.front-cover .fc-logo,
html[dir="rtl"] section.fullpage.cover.inside-cover .fc-logo {
  left: auto;
  right: var(--cover-inset);
}

html[dir="rtl"] section.fullpage.cover.front-cover .fc-meta,
html[dir="rtl"] section.fullpage.cover.inside-cover .fc-meta {
  right: auto;
  left: var(--cover-inset);
  text-align: left;
}

html[dir="rtl"] section.fullpage.cover.front-cover .fc-title,
html[dir="rtl"] section.fullpage.cover.inside-cover .fc-title {
  text-align: right;
}

html[dir="rtl"] section.fullpage.cover.front-cover .fc-subtitle,
html[dir="rtl"] section.fullpage.cover.inside-cover .fc-subtitle {
  left: var(--cover-subtitle-inset2);
  right: var(--cover-inset);
  text-align: right;
}

html[dir="rtl"] section.fullpage.cover.front-cover .fc-deco,
html[dir="rtl"] section.fullpage.module .fc-deco {
  right: auto;
  left: 0;
  transform: scaleX(-1);
  transform-origin: left bottom;
}

html[dir="rtl"] section.fullpage.cover.inside-cover .inside-cover__donate {
  right: auto;
  left: var(--cover-inset);
}

html[dir="rtl"] section.fullpage.module h1 {
  left: auto;
  right: var(--module-inset);
}

html[dir="rtl"] section.fullpage.module h2 {
  left: var(--module-h2-inset2);
  right: var(--module-inset);
  text-align: right;
}

html[dir="rtl"] section.fullpage.module > .toc {
  left: var(--module-h2-inset2);
  right: var(--module-inset);
}

html[dir="rtl"] section.fullpage.module > .toc > ul > li {
  text-align: right;
}
