/* @mds/paginator structural layout. The container becomes a fixed-height box
   whose content scrolls horizontally one viewport-sized page at a time. The
   consumer adds the `paginated` class to activate; removing it falls back to a
   continuous flow because the page wrappers go `display: contents`. */

.paginated {
  /* svh, not dvh: dvh resizes as the iOS Safari URL bar shows/hides, but
     pages packed for the URL-bar-hidden height clip mid-line in the 150ms
     before the visualViewport resize debounce re-paginates. svh sizes
     pages for the URL-bar-visible state always; when the bar hides, a
     small empty strip appears below the last page rather than the bottom
     of the current page jumping into the bar's space. Desktop unaffected
     (svh == dvh == lvh on engines without URL-bar transitions). */
  height: 100svh;
  overflow: hidden;
  display: grid;
  grid-template-rows: auto 1fr;
}

.paginated > .paginator-article {
  /* Page margins -- printed-book proportions. The inline (left/right)
     value scales with viewport width; the block (top/bottom) value
     scales with viewport height. Both have a 2rem floor so phone-sized
     viewports retain readable margins. Consumers override either
     variable to tighten or loosen the text block. */
  --ebook-margin: max(2rem, 6vw);
  --ebook-margin-block: max(2rem, 6vh);
  min-height: 0;
  min-width: 0;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: row;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  scroll-behavior: auto;
  scroll-snap-type: x mandatory;
  -webkit-tap-highlight-color: transparent;
}

.paginated > .paginator-article::-webkit-scrollbar {
  display: none;
}

.paginated .ebook-page {
  box-sizing: border-box;
  flex: 0 0 100vw;
  height: 100%;
  overflow: hidden;
  padding: var(--ebook-margin-block) var(--ebook-margin);
  scroll-snap-align: start;
}

.paginated .ebook-page > .ebook-page-content {
  box-sizing: border-box;
  width: 100%;
  max-width: var(--content-max-width, 760px);
  margin: 0 auto;
}

/* Book typography: fully justify body text in paginated mode, with
   hyphenation so narrow viewports don't open rivers between words
   (hyphens: auto needs the document's lang attribute; both consumers
   set it). Headings stay start-aligned; code never hyphenates.
   Continuous mode is untouched by this sheet; the mds and reader apps
   apply the same typography there via reading.css. The measurement
   probe is deliberately NOT exempted from these rules: hyphenation
   changes line breaks, and the probe must render exactly what the
   page will. */
.paginated .ebook-page > .ebook-page-content {
  text-align: justify;
  -webkit-hyphens: auto;
  hyphens: auto;
}
.paginated .ebook-page-content h1,
.paginated .ebook-page-content h2,
.paginated .ebook-page-content h3,
.paginated .ebook-page-content h4,
.paginated .ebook-page-content h5,
.paginated .ebook-page-content h6 {
  text-align: start;
  -webkit-hyphens: none;
  hyphens: none;
}
.paginated .ebook-page-content code,
.paginated .ebook-page-content pre {
  -webkit-hyphens: none;
  hyphens: none;
}
/* Tables are data, not prose: justification opens gaps inside narrow
   cells, and hyphenation changes the cells' intrinsic widths -- at
   mobile widths the auto table layout then disagrees between the
   measurement probe and the page badly enough to clip whole fragments. */
.paginated .ebook-page-content table {
  text-align: start;
  -webkit-hyphens: none;
  hyphens: none;
}
/* A paragraph split across pages: the head fragment's rendered last
   line is mid-paragraph, not a true paragraph end, so keep it justified
   rather than letting text-align-last's default rag it. Scoped to p --
   on container fragments (ol/blockquote heads) the property would
   inherit into child blocks and justify their genuine final lines.
   Fragments containing forced breaks are exempt: text-align-last also
   applies to every line right before a <br>, so a newsletter-style
   paragraph would have its hard-broken lines stretched edge to edge --
   and a split that lands exactly at a <br> leaves a head whose last
   line is a genuine segment end, where ragging is correct. */
.paginated .ebook-page-content p[data-split-continues]:not(:has(br)) {
  text-align-last: justify;
}

/* Keep replaced content within the page horizontally. Vertical fit is
   the imageSplitter's job: when an image-bearing unit (`<img>`,
   `<picture>`, `<figure>`) overflows the page, pack calls into the
   strategy with the available space, and the strategy sets an inline
   maxHeight that fits the per-page budget. The previous viewport-relative
   max-height ceiling was a flat global cap that did not adapt to where
   the figure actually landed; layout-time sizing is more precise. */
.ebook-page-content img,
.ebook-page-content svg {
  max-width: 100%;
  height: auto;
}

/* Keep <pre> blocks within the page inline-axis. Default white-space
   is "pre" (no wrap), so a long code line blows out the .ebook-page-content
   max-width on mobile viewports and leaks past the page's right edge.
   The page is overflow: hidden so the leak is invisible to the user,
   but the structural invariant -- content fits its column -- is
   violated; downstream measurement and the imageSplitter both rely on
   the column being honest. Make the pre its own horizontally-scrollable
   block so the line stays accessible without breaking the column. */
.ebook-page-content pre {
  max-width: 100%;
  overflow-x: auto;
}

/* Figure layout for image + caption: flex-column lets the strategy's
   inline maxHeight on the image shrink it while the caption keeps its
   natural height. object-fit: contain preserves the image's aspect
   ratio under the maxHeight constraint. */
.ebook-page-content figure {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.ebook-page-content figure > img,
.ebook-page-content figure > svg,
.ebook-page-content figure > picture > img,
.ebook-page-content figure > a > img {
  min-height: 0;
  flex: 1 1 auto;
  object-fit: contain;
}
.ebook-page-content figure > figcaption {
  flex: 0 0 auto;
}

/* Continuous mode: the wrappers exist in the DOM but are transparent to
   layout, so a mode flip needs no rebuild. */
.paginator-article > section.ebook-page,
.paginator-article > section.ebook-page > .ebook-page-content {
  display: contents;
}
.paginated .paginator-article > section.ebook-page,
.paginated .paginator-article > section.ebook-page > .ebook-page-content {
  display: revert;
}

/* Strip the leading top-margin from every page's first child in paginated
   mode. In continuous flow, an <h2> / <p> top-margin collapses with the
   preceding sibling's bottom-margin so the spacing looks right; the
   paginator slices that flow into pages without rewriting margins, so the
   first child on each page would otherwise start at
   (page-padding + own margin-top), and pages whose first child happens to
   be a heading (heavier margin) would visibly start lower than pages whose
   first child is a paragraph. Scoped to .paginated so continuous mode --
   where the wrappers are display: contents and adjacent block margins
   collapse normally -- is unaffected. */
.paginated .ebook-page:not(.ebook-probe) > .ebook-page-content > :first-child {
  margin-top: 0;
}

/* Symmetric rule for the trailing edge: a page-last child's bottom-margin
   is invisible empty space at the break, but engines count it in the
   section's scrollHeight, so a tightly-packed page (especially the
   document's final page, whose last unit is measured without a
   gap-below) reports phantom overflow. CSS fragmentation truncates
   margins adjoining a break; do the same.

   Both rules exempt the measurement probe (.ebook-probe): it simulates a
   continuous flow run, and DomMeasurer reads the batch-last unit's
   margin-bottom -- which the :last-child rule would zero mid-read. */
.paginated .ebook-page:not(.ebook-probe) > .ebook-page-content > :last-child {
  margin-bottom: 0;
}

/* Container fragmentation seam: when an oversized wrapper is split across
   pages, the continuation fragments drop their leading border/padding/margin
   and the originating fragments drop their trailing ones. This polyfills the
   default `box-decoration-break: slice` semantics on the wrapper. Consumers
   who want the wrapper's full borders on each fragment ("clone" semantics)
   can override these rules. */
.ebook-page-content [data-split-from] {
  border-block-start: 0;
  padding-block-start: 0;
  margin-block-start: 0;
}
.ebook-page-content [data-split-continues] {
  border-block-end: 0;
  padding-block-end: 0;
  margin-block-end: 0;
}

.ebook-pagina {
  position: fixed;
  bottom: 1rem;
  right: 1rem;
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
  color: var(--muted, #666);
  background: var(--surface, #fff);
  padding: 0.25rem 0.6rem;
  border-radius: 4px;
  border: 1px solid var(--border, #ddd);
  z-index: 30;
  pointer-events: none;
  user-select: none;
}
.ebook-pagina:not(.paginated .ebook-pagina) {
  display: none;
}
