@bendyline/squisq 2.7.0 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1589,6 +1589,16 @@ interface ExpandDocBlocksOptions {
1589
1589
  * defaults to `true` to preserve video/narration pacing.
1590
1590
  */
1591
1591
  splitLongBlocks?: boolean;
1592
+ /**
1593
+ * Merge blocks whose *scheduled* duration falls under the ~5s minimum
1594
+ * transition gap into their predecessor, and drop trailing blocks that would
1595
+ * start just before a segment boundary. That pacing rule keeps timed playback
1596
+ * from flashing slides, but it REMOVES authored blocks from the sequence.
1597
+ * Discrete-slide consumers (the PPTX exporter) pass `false` so every authored
1598
+ * slide survives into the deck. Only affects the audio-timed path; defaults to
1599
+ * `true` to preserve video/narration pacing.
1600
+ */
1601
+ mergeShortBlocks?: boolean;
1592
1602
  /**
1593
1603
  * User-defined custom templates to merge onto the built-in registry
1594
1604
  * before expanding blocks. Typically passed straight from
@@ -2093,6 +2103,57 @@ interface DocToMarkdownOptions {
2093
2103
  */
2094
2104
  declare function docToMarkdown(doc: Doc, options?: DocToMarkdownOptions): MarkdownDocument;
2095
2105
 
2106
+ /**
2107
+ * buildPreviewDoc — Converts a markdown-derived Doc into a player-ready Doc
2108
+ * with TemplateBlock slides and interleaved images.
2109
+ *
2110
+ * This is THE canonical slideshow projection: the editor's live preview, the
2111
+ * HTML slideshow export, and the PPTX exporter all run a doc through here so
2112
+ * the slide sequence cannot drift by consumer. It is the slide-mode sibling of
2113
+ * `materializePageSections` (page mode) and lives in core for the same reason —
2114
+ * exporters must be able to reach it without depending on a React package.
2115
+ *
2116
+ * Pipeline:
2117
+ * 1. Flatten hierarchical blocks into a linear slide sequence
2118
+ * 2. Convert each block into a TemplateBlock-compatible object
2119
+ * 3. Interleave images as standalone imageWithCaption slides
2120
+ * 4. Synthesize a dummy audio segment for timer-based playback
2121
+ */
2122
+
2123
+ /**
2124
+ * Build a player-ready Doc from a markdown-derived Doc.
2125
+ *
2126
+ * Flattens hierarchical blocks, converts each to a TemplateBlock-compatible
2127
+ * slide, interleaves images, recalculates timing, and adds a synthetic
2128
+ * audio segment.
2129
+ */
2130
+ interface BuildPreviewDocOptions {
2131
+ /**
2132
+ * Human-facing title to use as the header of the leading heading-less
2133
+ * "preamble" block when the document has no frontmatter `title:`. Hosts
2134
+ * typically pass the file name (extension stripped) via
2135
+ * {@link documentTitleFromFileName}. When neither this nor a frontmatter
2136
+ * title is present, the preamble simply renders with no header rather than
2137
+ * the placeholder block id.
2138
+ */
2139
+ documentTitle?: string;
2140
+ /**
2141
+ * Whether unused document images become standalone interleaved
2142
+ * `imageWithCaption` slides (default true — the slideshow behavior).
2143
+ * Consumers with a fixed cell budget (the dashboard projection) pass
2144
+ * false so synthetic filler slides never compete with real blocks.
2145
+ */
2146
+ interleaveImages?: boolean;
2147
+ }
2148
+ /**
2149
+ * Derive a display title from a file name: strip any directory prefix and the
2150
+ * trailing extension (`docs/Longview Plan.md` → `Longview Plan`). Returns an
2151
+ * empty string for an absent/blank name so callers can pass the result through
2152
+ * without extra guards.
2153
+ */
2154
+ declare function documentTitleFromFileName(fileName?: string): string;
2155
+ declare function buildPreviewDoc(doc: Doc, options?: BuildPreviewDocOptions): Doc;
2156
+
2096
2157
  /**
2097
2158
  * Frontmatter serialization for user-defined custom templates (layouts).
2098
2159
  *
@@ -2355,7 +2416,7 @@ declare function pageStyleDataAttributes(pageStyle: ThemePageStyle): Record<stri
2355
2416
  * Structural, theme-independent stylesheet for the page rendition.
2356
2417
  * Everything is scoped under `.squisq-page`.
2357
2418
  */
2358
- declare const PAGE_BASE_CSS = "\n/* \u2500\u2500 Base \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page {\n background: var(--squisq-page-bg);\n color: var(--squisq-page-text);\n font-family: var(--squisq-page-body-font);\n line-height: var(--squisq-page-line-height);\n --squisq-page-divider-color: color-mix(in srgb, var(--squisq-page-text) 16%, transparent);\n --squisq-page-section-pad: 3.5rem;\n --squisq-page-shadow: none;\n}\n.squisq-page *, .squisq-page *::before, .squisq-page *::after { box-sizing: border-box; }\n.squisq-page img { max-width: 100%; height: auto; }\n.squisq-page a {\n color: var(--squisq-page-primary);\n text-decoration-color: color-mix(in srgb, var(--squisq-page-primary) 40%, transparent);\n}\n\n/* Page pattern washes (very low intensity) */\n.squisq-page[data-pattern='dots'] {\n background-image: radial-gradient(color-mix(in srgb, var(--squisq-page-text) 7%, transparent) 1px, transparent 1px);\n background-size: 22px 22px;\n}\n.squisq-page[data-pattern='grid'] {\n background-image:\n linear-gradient(color-mix(in srgb, var(--squisq-page-primary) 7%, transparent) 1px, transparent 1px),\n linear-gradient(90deg, color-mix(in srgb, var(--squisq-page-primary) 7%, transparent) 1px, transparent 1px);\n background-size: 44px 44px;\n}\n.squisq-page[data-pattern='diagonal'] {\n background-image: repeating-linear-gradient(\n -45deg,\n color-mix(in srgb, var(--squisq-page-text) 4%, transparent) 0 1px,\n transparent 1px 14px\n );\n}\n.squisq-page[data-pattern='noise'] { background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)' opacity='0.35'/%3E%3C/svg%3E\"); }\n\n/* Spacing scale */\n.squisq-page[data-spacing='compact'] { --squisq-page-section-pad: 2.25rem; }\n.squisq-page[data-spacing='comfortable'] { --squisq-page-section-pad: 3.5rem; }\n.squisq-page[data-spacing='generous'] { --squisq-page-section-pad: 5.25rem; }\n\n/* Shadow language */\n.squisq-page[data-shadow='soft'] { --squisq-page-shadow: 0 14px 36px color-mix(in srgb, var(--squisq-page-text) 14%, transparent); }\n.squisq-page[data-shadow='crisp'] { --squisq-page-shadow: 0 2px 10px color-mix(in srgb, var(--squisq-page-text) 26%, transparent); }\n.squisq-page[data-shadow='heavy'] { --squisq-page-shadow: 10px 10px 0 color-mix(in srgb, var(--squisq-page-text) 82%, transparent); }\n\n/* \u2500\u2500 Sections \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-section { position: relative; padding-block: var(--squisq-page-section-pad); }\n.squisq-page-section-inner {\n max-width: var(--squisq-page-content-max);\n margin-inline: auto;\n padding-inline: 24px;\n}\n/* Backdrops anchor to the section; these content roots stack above them. */\n.squisq-page-hero-body,\n.squisq-page-banner-body,\n.squisq-page-quote-figure { position: relative; }\n.squisq-page-section--feature-split .squisq-page-section-inner,\n.squisq-page-section--gallery .squisq-page-section-inner,\n.squisq-page-section--table-section .squisq-page-section-inner,\n.squisq-page-section--canvas-embed .squisq-page-section-inner,\n.squisq-page-section--stat-band .squisq-page-section-inner,\n.squisq-page-section--card-grid .squisq-page-section-inner,\n.squisq-page-section--media-figure .squisq-page-section-inner,\n.squisq-page-section--hero .squisq-page-section-inner {\n max-width: var(--squisq-page-wide-max);\n}\n\n/* Background rhythm */\n.squisq-page-section--bg-alternate { background: var(--squisq-page-bg-alt); }\n.squisq-page-section--bg-accent {\n background: var(--squisq-page-accent-bg);\n color: var(--squisq-page-accent-text);\n}\n.squisq-page-section--bg-media { color: #ffffff; }\n\n/* Dividers between adjacent sections */\n.squisq-page[data-divider='hairline'] .squisq-page-section + .squisq-page-section { border-top: 1px solid var(--squisq-page-divider-color); }\n.squisq-page[data-divider='thick-rule'] .squisq-page-section + .squisq-page-section { border-top: 3px solid var(--squisq-page-primary); }\n.squisq-page[data-divider='double-rule'] .squisq-page-section + .squisq-page-section { border-top: 4px double var(--squisq-page-divider-color); }\n.squisq-page[data-divider='dotted'] .squisq-page-section + .squisq-page-section { border-top: 2px dotted var(--squisq-page-divider-color); }\n/* Banded sections carry their own edges; media sections never need rules. */\n.squisq-page .squisq-page-section--bg-media,\n.squisq-page .squisq-page-section--bg-media + .squisq-page-section,\n.squisq-page .squisq-page-section--timeline-rail + .squisq-page-section--timeline-rail { border-top: none; }\n\n/* \u2500\u2500 Headings, eyebrows \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-section-title {\n font-family: var(--squisq-page-title-font);\n font-weight: var(--squisq-page-title-weight);\n line-height: 1.15;\n margin: 0 0 0.5em;\n}\n.squisq-page[data-heading-case='uppercase'] .squisq-page-section-title { text-transform: uppercase; letter-spacing: 0.03em; }\n.squisq-page[data-underline='accent-bar'] .squisq-page-section-title::after {\n content: '';\n display: block;\n width: 56px;\n height: 4px;\n margin-top: 0.4em;\n border-radius: 2px;\n background: var(--squisq-page-accent);\n}\n.squisq-page[data-underline='full-rule'] .squisq-page-section-title {\n border-bottom: 1px solid var(--squisq-page-divider-color);\n padding-bottom: 0.35em;\n}\n\n.squisq-page-eyebrow {\n display: block;\n font-size: 0.8125rem;\n font-weight: 600;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--squisq-page-accent);\n margin: 0 0 0.9em;\n}\n.squisq-page[data-eyebrow='numbered'] .squisq-page-eyebrow::after { content: ' \u2014'; color: var(--squisq-page-text-muted); }\n.squisq-page[data-eyebrow='mono-tag'] .squisq-page-eyebrow {\n display: inline-block;\n font-family: var(--squisq-page-mono-font);\n text-transform: none;\n letter-spacing: 0.06em;\n border: 1px solid color-mix(in srgb, var(--squisq-page-accent) 55%, transparent);\n border-radius: var(--squisq-page-radius);\n padding: 0.15em 0.6em;\n background: color-mix(in srgb, var(--squisq-page-accent) 10%, transparent);\n}\n.squisq-page[data-eyebrow='mono-tag'] .squisq-page-eyebrow::before { content: '['; opacity: 0.6; }\n.squisq-page[data-eyebrow='mono-tag'] .squisq-page-eyebrow::after { content: ']'; opacity: 0.6; }\n\n/* \u2500\u2500 Hero \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-section--hero { padding-block: calc(var(--squisq-page-section-pad) * 1.5); }\n.squisq-page-hero-title {\n font-family: var(--squisq-page-title-font);\n font-weight: var(--squisq-page-title-weight);\n line-height: 1.08;\n margin: 0;\n font-size: 2.75rem;\n}\n.squisq-page[data-heading-scale='display'] .squisq-page-hero-title { font-size: 3.4rem; }\n.squisq-page[data-heading-scale='oversized'] .squisq-page-hero-title { font-size: 4rem; font-size: clamp(3rem, 9cqw, 6rem); line-height: 1.02; }\n.squisq-page[data-heading-case='uppercase'] .squisq-page-hero-title { text-transform: uppercase; letter-spacing: 0.02em; }\n.squisq-page-hero-subtitle {\n margin: 1.1em 0 0;\n font-size: 1.25rem;\n color: var(--squisq-page-text-muted);\n max-width: 42em;\n white-space: pre-line;\n}\n.squisq-page-section--bg-media .squisq-page-hero-subtitle { color: rgba(255, 255, 255, 0.88); }\n\n/* Stacked (default): centered column */\n.squisq-page[data-hero-style='stacked'] .squisq-page-hero-body { text-align: center; }\n.squisq-page[data-hero-style='stacked'] .squisq-page-hero-subtitle { margin-inline: auto; }\n\n/* Oversized type: hard left, no decoration */\n.squisq-page[data-hero-style='oversized-type'] .squisq-page-hero-title { font-size: 4.25rem; font-size: clamp(3.25rem, 10cqw, 6.5rem); line-height: 0.98; }\n\n/* Split: text and media side by side */\n.squisq-page-hero-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 3rem; align-items: center; }\n.squisq-page-hero-grid .squisq-page-hero-media img { width: 100%; object-fit: cover; }\n\n/* Full-bleed & letterbox: media behind text */\n.squisq-page-section--hero-media {\n padding-block: 0;\n min-height: min(72svh, 620px);\n display: flex;\n align-items: flex-end;\n}\n.squisq-page[data-hero-style='letterbox'] .squisq-page-section--hero-media { min-height: min(52svh, 460px); }\n.squisq-page-hero-backdrop { position: absolute; inset: 0; overflow: hidden; }\n.squisq-page-hero-backdrop img { width: 100%; height: 100%; object-fit: cover; }\n.squisq-page-hero-backdrop::after {\n content: '';\n position: absolute;\n inset: 0;\n background: linear-gradient(180deg, rgba(0, 0, 0, 0.1) 30%, rgba(0, 0, 0, 0.68) 100%);\n}\n.squisq-page[data-hero-style='letterbox'] .squisq-page-hero-backdrop img { filter: saturate(0.9); }\n.squisq-page-section--hero-media .squisq-page-section-inner { padding-block: 3rem; width: 100%; }\n\n/* \u2500\u2500 Banner (sectionHeader) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-banner-title { font-size: 2rem; }\n.squisq-page[data-heading-scale='display'] .squisq-page-banner-title { font-size: 2.5rem; }\n.squisq-page[data-heading-scale='oversized'] .squisq-page-banner-title { font-size: 3rem; font-size: clamp(2.25rem, 6cqw, 3.75rem); }\n.squisq-page-section--banner.squisq-page-section--bg-media { padding-block: 0; min-height: 280px; display: flex; align-items: flex-end; }\n.squisq-page-section--banner.squisq-page-section--bg-media .squisq-page-section-inner { padding-block: 2rem; width: 100%; }\n.squisq-page-section--banner .squisq-page-section-title { margin-bottom: 0; }\n\n/* \u2500\u2500 Stat band \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-stats { display: flex; gap: 3rem; justify-content: center; text-align: center; flex-wrap: wrap; }\n.squisq-page-stat { flex: 1 1 220px; max-width: 420px; }\n.squisq-page-stat-value {\n display: block;\n font-family: var(--squisq-page-title-font);\n font-weight: 700;\n font-size: 3.25rem;\n line-height: 1;\n color: var(--squisq-page-accent);\n}\n.squisq-page[data-numerals='oversized'] .squisq-page-stat-value { font-size: 4.5rem; font-size: clamp(3.5rem, 8cqw, 5.5rem); }\n.squisq-page[data-numerals='mono'] .squisq-page-stat-value { font-family: var(--squisq-page-mono-font); letter-spacing: -0.02em; }\n.squisq-page[data-numerals='boxed'] .squisq-page-stat-value {\n display: inline-block;\n border: 2px solid var(--squisq-page-accent);\n border-radius: var(--squisq-page-radius);\n padding: 0.18em 0.4em;\n}\n.squisq-page-stat-title { display: block; margin-top: 0.9em; font-size: 1.125rem; font-weight: 600; }\n.squisq-page-stat-body { display: block; margin-top: 0.45em; color: var(--squisq-page-text-muted); font-size: 0.95rem; }\n.squisq-page-stat-meta { text-align: center; margin-top: 1.5rem; color: var(--squisq-page-text-muted); font-size: 0.85rem; }\n.squisq-page-stat-bar { height: 10px; border-radius: 999px; background: var(--squisq-page-accent); margin-top: 0.8em; }\n.squisq-page-stat--bars { text-align: left; }\n\n/* \u2500\u2500 Quote band \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-quote {\n margin: 0;\n font-family: var(--squisq-page-title-font);\n font-size: 1.6rem;\n line-height: 1.35;\n white-space: pre-line;\n}\n.squisq-page-section--em-strong .squisq-page-quote { font-size: 2.1rem; }\n.squisq-page-section--em-quiet .squisq-page-quote { font-size: 1.25rem; color: var(--squisq-page-text-muted); }\n.squisq-page-quote-attribution { margin-top: 1.1em; font-family: var(--squisq-page-body-font); font-size: 0.95rem; color: var(--squisq-page-text-muted); }\n.squisq-page-quote-attribution::before { content: '\u2014 '; }\n.squisq-page[data-quote-mark='accent-bar'] .squisq-page-quote-figure { border-left: 4px solid var(--squisq-page-accent); padding-left: 1.5rem; }\n.squisq-page[data-quote-mark='oversized-glyph'] .squisq-page-quote-figure { position: relative; padding-top: 1.25rem; }\n.squisq-page[data-quote-mark='oversized-glyph'] .squisq-page-quote-figure::before {\n content: '\\201C';\n position: absolute;\n top: -0.12em;\n left: -0.05em;\n font-family: var(--squisq-page-title-font);\n font-size: 5.5rem;\n line-height: 1;\n color: color-mix(in srgb, var(--squisq-page-accent) 42%, transparent);\n pointer-events: none;\n}\n.squisq-page-section--v-display .squisq-page-quote-figure { text-align: center; border-left: none; }\n.squisq-page-section--v-display .squisq-page-quote { font-size: 2.4rem; font-size: clamp(1.9rem, 5cqw, 3rem); }\n.squisq-page-section--v-editorial .squisq-page-quote-figure {\n border-block: 3px solid var(--squisq-page-primary);\n border-left: none;\n padding: 2rem 0.5rem;\n}\n/* Full-bleed quote over media */\n.squisq-page-section--quote-band.squisq-page-section--bg-media { padding-block: 0; min-height: 380px; display: flex; align-items: center; }\n.squisq-page-section--quote-band.squisq-page-section--bg-media .squisq-page-section-inner { padding-block: 3.5rem; }\n.squisq-page-quote-backdrop { position: absolute; inset: 0; overflow: hidden; }\n.squisq-page-quote-backdrop img, .squisq-page-quote-backdrop video { width: 100%; height: 100%; object-fit: cover; }\n.squisq-page-quote-backdrop::after { content: ''; position: absolute; inset: 0; background: rgba(0, 0, 0, 0.55); }\n.squisq-page-section--quote-band[data-hint-vignette] .squisq-page-quote-backdrop::after {\n background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0.35) 0%, rgba(0, 0, 0, 0.75) 100%);\n}\n.squisq-page-section--quote-band.squisq-page-section--bg-media .squisq-page-quote-figure { border: none; text-align: center; }\n\n/* \u2500\u2500 Feature split \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-feature { display: grid; grid-template-columns: 1fr 1fr; gap: 3rem; align-items: center; }\n.squisq-page-feature--media-right .squisq-page-feature-media { order: 2; }\n.squisq-page-feature-media img { width: 100%; object-fit: cover; }\n.squisq-page-feature-title { font-size: 1.75rem; }\n.squisq-page-feature-body { color: var(--squisq-page-text-muted); font-size: 1.05rem; white-space: pre-line; margin: 0; }\n\n/* \u2500\u2500 Media figure \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-figure { margin: 0; }\n.squisq-page-figure img, .squisq-page-figure video { width: 100%; display: block; }\n.squisq-page-figure figcaption { margin-top: 0.9em; font-size: 0.9rem; color: var(--squisq-page-text-muted); text-align: center; }\n.squisq-page-media-credit { font-size: 0.78rem; opacity: 0.75; }\n\n/* Media frame treatment (figures, features, gallery tiles, cards) */\n.squisq-page-media-frame { overflow: hidden; }\n.squisq-page[data-framing='rounded'] .squisq-page-media-frame { border-radius: var(--squisq-page-radius); }\n.squisq-page[data-framing='bordered'] .squisq-page-media-frame { border: 3px solid var(--squisq-page-text); }\n.squisq-page[data-framing='polaroid'] .squisq-page-media-frame {\n background: #ffffff;\n padding: 10px 10px 16px;\n border: 1px solid rgba(0, 0, 0, 0.12);\n border-radius: 2px;\n}\n.squisq-page[data-framing='letterboxed'] .squisq-page-media-frame img { aspect-ratio: 21 / 9; object-fit: cover; }\n.squisq-page[data-framing='circle-accent'] .squisq-page-media-frame { border-radius: calc(var(--squisq-page-radius) * 2); }\n.squisq-page .squisq-page-media-frame { box-shadow: var(--squisq-page-shadow); }\n\n/* Rich body nodes that the selected template did not consume. This universal\n * supplement keeps diagrams/media visible without making every template\n * duplicate the same preservation logic. */\n.squisq-page-rich-content {\n margin-top: clamp(1.5rem, 4vw, 3rem);\n padding-top: clamp(1.25rem, 3vw, 2rem);\n border-top: 1px solid var(--squisq-page-divider-color);\n}\n.squisq-page-rich-content :is(img, video) { display: block; max-width: 100%; height: auto; margin-inline: auto; }\n.squisq-page-rich-content .squisq-md-mermaid { min-height: min(520px, 62vh); margin-block: 0; }\n\n/* \u2500\u2500 Gallery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-gallery { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1.25rem; }\n.squisq-page-gallery .squisq-page-media-frame img { width: 100%; height: 100%; aspect-ratio: 4 / 3; object-fit: cover; }\n.squisq-page-gallery-caption { margin-top: 1.1rem; text-align: center; font-size: 0.9rem; color: var(--squisq-page-text-muted); }\n\n/* \u2500\u2500 Callout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-callout {\n border-radius: var(--squisq-page-radius);\n border: 1px solid color-mix(in srgb, var(--squisq-page-accent) 32%, transparent);\n border-left: 5px solid var(--squisq-page-accent);\n background: color-mix(in srgb, var(--squisq-page-accent) 7%, var(--squisq-page-bg));\n padding: 1.75rem 2rem;\n box-shadow: var(--squisq-page-shadow);\n display: flex;\n gap: 1.75rem;\n align-items: flex-start;\n}\n.squisq-page-callout-title { font-family: var(--squisq-page-title-font); font-size: 1.35rem; font-weight: 700; margin: 0 0 0.5em; }\n.squisq-page-callout-body { margin: 0; white-space: pre-line; }\n.squisq-page-callout-meta { margin-top: 0.9em; font-size: 0.82rem; color: var(--squisq-page-text-muted); }\n.squisq-page-callout .squisq-page-media-frame { flex: 0 0 132px; }\n.squisq-page-callout .squisq-page-media-frame img { width: 132px; height: 132px; object-fit: cover; }\n.squisq-page-callout[data-hint-framing='circle-accent'] .squisq-page-media-frame,\n.squisq-page-callout[data-hint-framing='circle-accent'] .squisq-page-media-frame img { border-radius: 50%; }\n.squisq-page-section--v-definition .squisq-page-callout-title { font-style: italic; }\n.squisq-page-section--v-diagnostic .squisq-page-callout { border-left-color: var(--squisq-page-highlight); }\n\n/* \u2500\u2500 Card grid \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1.5rem; }\n.squisq-page-card {\n border-radius: var(--squisq-page-radius);\n background: var(--squisq-page-bg-alt);\n border-top: 4px solid var(--squisq-page-card-accent, var(--squisq-page-accent));\n padding: 1.75rem 1.75rem 1.9rem;\n box-shadow: var(--squisq-page-shadow);\n}\n.squisq-page-card-title { font-family: var(--squisq-page-title-font); font-size: 1.3rem; margin: 0 0 0.4em; }\n.squisq-page-card-body { margin: 0; color: var(--squisq-page-text-muted); white-space: pre-line; }\n.squisq-page-cards-title { text-align: center; font-size: 1.9rem; margin-bottom: 1.75rem; }\n\n/* \u2500\u2500 Item list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-items { list-style: none; margin: 0; padding: 0; counter-reset: squisq-item; max-width: 40em; }\n.squisq-page-items li {\n counter-increment: squisq-item;\n position: relative;\n padding: 0.9em 0 0.9em 3.4em;\n font-size: 1.1rem;\n}\n.squisq-page-items li + li { border-top: 1px solid var(--squisq-page-divider-color); }\n.squisq-page-items li::before {\n content: counter(squisq-item, decimal-leading-zero);\n position: absolute;\n left: 0;\n top: 0.85em;\n font-family: var(--squisq-page-title-font);\n font-weight: 700;\n color: var(--squisq-page-accent);\n font-size: 1.15em;\n}\n.squisq-page[data-numerals='mono'] .squisq-page-items li::before { font-family: var(--squisq-page-mono-font); }\n.squisq-page-items-title { font-size: 1.9rem; }\n\n/* \u2500\u2500 Timeline rail (dateEvent) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-section--timeline-rail { padding-block: 1.4rem; }\n.squisq-page-section--timeline-rail:first-child { padding-top: var(--squisq-page-section-pad); }\n.squisq-page-milestone { display: grid; grid-template-columns: 150px 1fr; gap: 2rem; align-items: baseline; position: relative; }\n.squisq-page-milestone-date {\n font-family: var(--squisq-page-title-font);\n font-weight: 700;\n color: var(--squisq-page-accent);\n font-size: 1.05rem;\n text-align: right;\n}\n.squisq-page-milestone-rail {\n position: absolute;\n left: 166px;\n top: -1.4rem;\n bottom: -1.4rem;\n width: 2px;\n background: color-mix(in srgb, var(--squisq-page-accent) 35%, transparent);\n}\n.squisq-page-milestone-rail::after {\n content: '';\n position: absolute;\n left: 50%;\n top: 0.55em;\n width: 12px;\n height: 12px;\n border-radius: 50%;\n transform: translateX(-50%);\n background: var(--squisq-page-accent);\n border: 2px solid var(--squisq-page-bg);\n}\n.squisq-page-milestone-body { padding-left: 2.25rem; white-space: pre-line; }\n.squisq-page-milestone-footer { margin-top: 0.5em; font-size: 0.85rem; color: var(--squisq-page-text-muted); }\n\n/* \u2500\u2500 Table section \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-table-title { font-size: 1.9rem; }\n.squisq-page-table-scroll { overflow-x: auto; border-radius: var(--squisq-page-radius); box-shadow: var(--squisq-page-shadow); }\n.squisq-page-table { width: 100%; border-collapse: collapse; font-size: 0.98rem; }\n.squisq-page-table th {\n background: var(--squisq-page-accent-bg);\n color: var(--squisq-page-accent-text);\n font-family: var(--squisq-page-title-font);\n text-align: left;\n padding: 0.8em 1em;\n}\n.squisq-page-table td { padding: 0.7em 1em; border-top: 1px solid var(--squisq-page-divider-color); }\n.squisq-page-table tbody tr:nth-child(even) { background: color-mix(in srgb, var(--squisq-page-text) 3.5%, transparent); }\n\n/* \u2500\u2500 Canvas embed (spatial SVG) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-canvas {\n width: 100%;\n margin-inline: auto;\n overflow: hidden;\n border-radius: var(--squisq-page-radius);\n}\n.squisq-page-canvas svg { display: block; width: 100%; height: 100%; }\n.squisq-page-canvas--framed { border: 1px solid var(--squisq-page-divider-color); box-shadow: var(--squisq-page-shadow); }\n.squisq-page-canvas--terminal { border: 1px solid color-mix(in srgb, var(--squisq-page-accent) 45%, transparent); }\n.squisq-page-canvas--terminal::before {\n content: '\\25CF \\25CF \\25CF';\n display: block;\n font-size: 9px;\n letter-spacing: 4px;\n padding: 6px 12px;\n color: color-mix(in srgb, var(--squisq-page-accent) 70%, transparent);\n background: color-mix(in srgb, var(--squisq-page-accent) 9%, var(--squisq-page-bg));\n border-bottom: 1px solid color-mix(in srgb, var(--squisq-page-accent) 30%, transparent);\n}\n\n/* \u2500\u2500 Prose \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-section--prose { padding-block: calc(var(--squisq-page-section-pad) * 0.45); }\n.squisq-page[data-divider] .squisq-page-section--prose + .squisq-page-section--prose { border-top: none; }\n.squisq-page-prose { font-size: 1.05rem; }\n.squisq-page-prose p { margin: 0; }\n.squisq-page-prose p + p { margin-top: 1.25em; }\n.squisq-page-prose > * + * { margin-top: 1.1em; }\n.squisq-page-prose code { font-family: var(--squisq-page-mono-font); font-size: 0.9em; }\n.squisq-page-prose :not(pre) > code { background: color-mix(in srgb, var(--squisq-page-text) 8%, transparent); border-radius: 4px; padding: 0.12em 0.35em; }\n.squisq-page-prose pre { background: color-mix(in srgb, var(--squisq-page-text) 6%, transparent); border-radius: var(--squisq-page-radius); padding: 1em 1.25em; overflow-x: auto; }\n.squisq-page-prose pre code { background: none; border-radius: 0; padding: 0; }\n.squisq-page .squisq-md-code-frame { position: relative; margin: 1em 0; }\n.squisq-page .squisq-md-code-frame > pre { margin: 0; padding-right: 5rem; }\n.squisq-page .squisq-md-code-copy {\n position: absolute;\n z-index: 1;\n top: 0.55rem;\n right: 0.55rem;\n min-width: 3.7rem;\n padding: 0.28rem 0.5rem;\n border: 1px solid color-mix(in srgb, var(--squisq-page-text) 20%, transparent);\n border-radius: 5px;\n background: color-mix(in srgb, var(--squisq-page-bg) 90%, transparent);\n color: inherit;\n font: 500 0.72rem/1.2 system-ui, sans-serif;\n cursor: pointer;\n opacity: 0.58;\n transition: opacity 120ms ease, background-color 120ms ease;\n}\n.squisq-page .squisq-md-code-frame:hover > .squisq-md-code-copy,\n.squisq-page .squisq-md-code-copy:focus-visible,\n.squisq-page .squisq-md-code-copy[data-copy-state='copied'],\n.squisq-page .squisq-md-code-copy[data-copy-state='failed'] { opacity: 1; }\n.squisq-page .squisq-md-code-copy:hover { background: var(--squisq-page-bg); }\n.squisq-page .squisq-md-code-copy:disabled { cursor: wait; }\n.squisq-page-prose blockquote { margin: 0; border-left: 4px solid var(--squisq-page-accent); padding-left: 1.25em; color: var(--squisq-page-text-muted); }\n.squisq-page-prose ul, .squisq-page-prose ol { padding-left: 1.5em; margin: 0; }\n.squisq-page-prose li + li { margin-top: 0.4em; }\n.squisq-page-prose hr { border: none; border-top: 1px solid var(--squisq-page-divider-color); }\n.squisq-page-prose table { width: 100%; border-collapse: collapse; }\n.squisq-page-prose th { font-family: var(--squisq-page-title-font); text-align: left; padding: 0.6em 0.8em; border-bottom: 2px solid var(--squisq-page-divider-color); }\n.squisq-page-prose td { padding: 0.55em 0.8em; border-bottom: 1px solid var(--squisq-page-divider-color); }\n.squisq-page-prose img { border-radius: var(--squisq-page-radius); }\n.squisq-page-prose h1, .squisq-page-prose h2, .squisq-page-prose h3,\n.squisq-page-prose h4, .squisq-page-prose h5, .squisq-page-prose h6 {\n font-family: var(--squisq-page-title-font);\n font-weight: var(--squisq-page-title-weight);\n line-height: 1.2;\n margin: 0 0 0.45em;\n}\n.squisq-page-prose h1 { font-size: 2.1rem; }\n.squisq-page-prose h2 { font-size: 1.65rem; }\n.squisq-page-prose h3 { font-size: 1.35rem; }\n.squisq-page-prose h4, .squisq-page-prose h5, .squisq-page-prose h6 { font-size: 1.15rem; }\n.squisq-page-section--prose[data-hint-drop-cap] .squisq-page-prose > p:first-child::first-letter {\n font-family: var(--squisq-page-title-font);\n font-size: 3.4em;\n font-weight: 700;\n float: left;\n line-height: 0.85;\n padding-right: 0.12em;\n color: var(--squisq-page-accent);\n}\n\n/* \u2500\u2500 Footer band \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-section--footer { text-align: center; }\n\n/* \u2500\u2500 Thin-margin embedding (chat bubbles) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page--thin .squisq-page-section-inner { padding-inline: 0; }\n.squisq-page--thin .squisq-page-section { padding-block: 1.5rem; }\n\n/* Thumbnail image mode */\n.squisq-page--thumbnail-images .squisq-page-prose img,\n.squisq-page--thumbnail-images .squisq-page-figure img { max-width: 100px; max-height: 100px; object-fit: cover; }\n\n/* \u2500\u2500 Reveal animation (progressive enhancement) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n@media (prefers-reduced-motion: no-preference) {\n .squisq-page-reveal { opacity: 0; transform: translateY(14px); transition: opacity 0.55s ease, transform 0.55s ease; }\n .squisq-page-reveal--in { opacity: 1; transform: none; }\n}\n\n/* \u2500\u2500 Responsive \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n@container squisq-page (max-width: 720px) {\n\n.squisq-page-hero-grid { grid-template-columns: 1fr; gap: 1.5rem; }\n.squisq-page-feature { grid-template-columns: 1fr; }\n.squisq-page-feature--media-right .squisq-page-feature-media { order: 0; }\n.squisq-page-stats { flex-direction: column; gap: 1.75rem; }\n.squisq-page-cards { grid-template-columns: 1fr; }\n.squisq-page-gallery { grid-template-columns: repeat(2, 1fr); }\n.squisq-page-milestone { grid-template-columns: 1fr; gap: 0.5rem; }\n.squisq-page-milestone-rail { display: none; }\n.squisq-page-section-inner { padding-inline: 18px; }\n\n}\n@supports not (container-type: inline-size) {\n @media (max-width: 720px) {\n\n.squisq-page-hero-grid { grid-template-columns: 1fr; gap: 1.5rem; }\n.squisq-page-feature { grid-template-columns: 1fr; }\n.squisq-page-feature--media-right .squisq-page-feature-media { order: 0; }\n.squisq-page-stats { flex-direction: column; gap: 1.75rem; }\n.squisq-page-cards { grid-template-columns: 1fr; }\n.squisq-page-gallery { grid-template-columns: repeat(2, 1fr); }\n.squisq-page-milestone { grid-template-columns: 1fr; gap: 0.5rem; }\n.squisq-page-milestone-rail { display: none; }\n.squisq-page-section-inner { padding-inline: 18px; }\n\n }\n}\n";
2419
+ declare const PAGE_BASE_CSS = "\n/* \u2500\u2500 Base \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page {\n background: var(--squisq-page-bg);\n color: var(--squisq-page-text);\n font-family: var(--squisq-page-body-font);\n line-height: var(--squisq-page-line-height);\n --squisq-page-divider-color: color-mix(in srgb, var(--squisq-page-text) 16%, transparent);\n --squisq-page-section-pad: 3.5rem;\n --squisq-page-shadow: none;\n}\n.squisq-page *, .squisq-page *::before, .squisq-page *::after { box-sizing: border-box; }\n.squisq-page img { max-width: 100%; height: auto; }\n.squisq-page a {\n color: var(--squisq-page-primary);\n text-decoration-color: color-mix(in srgb, var(--squisq-page-primary) 40%, transparent);\n}\n\n/* Page pattern washes (very low intensity) */\n.squisq-page[data-pattern='dots'] {\n background-image: radial-gradient(color-mix(in srgb, var(--squisq-page-text) 7%, transparent) 1px, transparent 1px);\n background-size: 22px 22px;\n}\n.squisq-page[data-pattern='grid'] {\n background-image:\n linear-gradient(color-mix(in srgb, var(--squisq-page-primary) 7%, transparent) 1px, transparent 1px),\n linear-gradient(90deg, color-mix(in srgb, var(--squisq-page-primary) 7%, transparent) 1px, transparent 1px);\n background-size: 44px 44px;\n}\n.squisq-page[data-pattern='diagonal'] {\n background-image: repeating-linear-gradient(\n -45deg,\n color-mix(in srgb, var(--squisq-page-text) 4%, transparent) 0 1px,\n transparent 1px 14px\n );\n}\n.squisq-page[data-pattern='noise'] { background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)' opacity='0.35'/%3E%3C/svg%3E\"); }\n\n/* Spacing scale */\n.squisq-page[data-spacing='compact'] { --squisq-page-section-pad: 2.25rem; }\n.squisq-page[data-spacing='comfortable'] { --squisq-page-section-pad: 3.5rem; }\n.squisq-page[data-spacing='generous'] { --squisq-page-section-pad: 5.25rem; }\n\n/* Shadow language */\n.squisq-page[data-shadow='soft'] { --squisq-page-shadow: 0 14px 36px color-mix(in srgb, var(--squisq-page-text) 14%, transparent); }\n.squisq-page[data-shadow='crisp'] { --squisq-page-shadow: 0 2px 10px color-mix(in srgb, var(--squisq-page-text) 26%, transparent); }\n.squisq-page[data-shadow='heavy'] { --squisq-page-shadow: 10px 10px 0 color-mix(in srgb, var(--squisq-page-text) 82%, transparent); }\n\n/* \u2500\u2500 Sections \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-section { position: relative; padding-block: var(--squisq-page-section-pad); }\n.squisq-page-section-inner {\n max-width: var(--squisq-page-content-max);\n margin-inline: auto;\n padding-inline: 24px;\n}\n/* Backdrops anchor to the section; these content roots stack above them. */\n.squisq-page-hero-body,\n.squisq-page-banner-body,\n.squisq-page-quote-figure { position: relative; }\n.squisq-page-section--feature-split .squisq-page-section-inner,\n.squisq-page-section--gallery .squisq-page-section-inner,\n.squisq-page-section--table-section .squisq-page-section-inner,\n.squisq-page-section--canvas-embed .squisq-page-section-inner,\n.squisq-page-section--stat-band .squisq-page-section-inner,\n.squisq-page-section--card-grid .squisq-page-section-inner,\n.squisq-page-section--media-figure .squisq-page-section-inner,\n.squisq-page-section--hero .squisq-page-section-inner {\n max-width: var(--squisq-page-wide-max);\n}\n\n/* Background rhythm */\n.squisq-page-section--bg-alternate { background: var(--squisq-page-bg-alt); }\n.squisq-page-section--bg-accent {\n background: var(--squisq-page-accent-bg);\n color: var(--squisq-page-accent-text);\n}\n.squisq-page-section--bg-media { color: #ffffff; }\n\n/* Dividers between adjacent sections */\n.squisq-page[data-divider='hairline'] .squisq-page-section + .squisq-page-section { border-top: 1px solid var(--squisq-page-divider-color); }\n.squisq-page[data-divider='thick-rule'] .squisq-page-section + .squisq-page-section { border-top: 3px solid var(--squisq-page-primary); }\n.squisq-page[data-divider='double-rule'] .squisq-page-section + .squisq-page-section { border-top: 4px double var(--squisq-page-divider-color); }\n.squisq-page[data-divider='dotted'] .squisq-page-section + .squisq-page-section { border-top: 2px dotted var(--squisq-page-divider-color); }\n/* Banded sections carry their own edges; media sections never need rules. */\n.squisq-page .squisq-page-section--bg-media,\n.squisq-page .squisq-page-section--bg-media + .squisq-page-section,\n.squisq-page .squisq-page-section--timeline-rail + .squisq-page-section--timeline-rail { border-top: none; }\n\n/* \u2500\u2500 Headings, eyebrows \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-section-title {\n font-family: var(--squisq-page-title-font);\n font-weight: var(--squisq-page-title-weight);\n line-height: 1.15;\n margin: 0 0 0.5em;\n}\n.squisq-page[data-heading-case='uppercase'] .squisq-page-section-title { text-transform: uppercase; letter-spacing: 0.03em; }\n.squisq-page[data-underline='accent-bar'] .squisq-page-section-title::after {\n content: '';\n display: block;\n width: 56px;\n height: 4px;\n margin-top: 0.4em;\n border-radius: 2px;\n background: var(--squisq-page-accent);\n}\n.squisq-page[data-underline='full-rule'] .squisq-page-section-title {\n border-bottom: 1px solid var(--squisq-page-divider-color);\n padding-bottom: 0.35em;\n}\n\n.squisq-page-eyebrow {\n display: block;\n font-size: 0.8125rem;\n font-weight: 600;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--squisq-page-accent);\n margin: 0 0 0.9em;\n}\n.squisq-page[data-eyebrow='numbered'] .squisq-page-eyebrow::after { content: ' \u2014'; color: var(--squisq-page-text-muted); }\n.squisq-page[data-eyebrow='mono-tag'] .squisq-page-eyebrow {\n display: inline-block;\n font-family: var(--squisq-page-mono-font);\n text-transform: none;\n letter-spacing: 0.06em;\n border: 1px solid color-mix(in srgb, var(--squisq-page-accent) 55%, transparent);\n border-radius: var(--squisq-page-radius);\n padding: 0.15em 0.6em;\n background: color-mix(in srgb, var(--squisq-page-accent) 10%, transparent);\n}\n.squisq-page[data-eyebrow='mono-tag'] .squisq-page-eyebrow::before { content: '['; opacity: 0.6; }\n.squisq-page[data-eyebrow='mono-tag'] .squisq-page-eyebrow::after { content: ']'; opacity: 0.6; }\n\n/* \u2500\u2500 Hero \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-section--hero { padding-block: calc(var(--squisq-page-section-pad) * 1.5); }\n.squisq-page-hero-title {\n font-family: var(--squisq-page-title-font);\n font-weight: var(--squisq-page-title-weight);\n line-height: 1.08;\n margin: 0;\n font-size: 2.75rem;\n}\n.squisq-page[data-heading-scale='display'] .squisq-page-hero-title { font-size: 3.4rem; }\n.squisq-page[data-heading-scale='oversized'] .squisq-page-hero-title { font-size: 4rem; font-size: clamp(3rem, 9cqw, 6rem); line-height: 1.02; }\n.squisq-page[data-heading-case='uppercase'] .squisq-page-hero-title { text-transform: uppercase; letter-spacing: 0.02em; }\n.squisq-page-hero-subtitle {\n margin: 1.1em 0 0;\n font-size: 1.25rem;\n color: var(--squisq-page-text-muted);\n max-width: 42em;\n white-space: pre-line;\n}\n.squisq-page-section--bg-media .squisq-page-hero-subtitle { color: rgba(255, 255, 255, 0.88); }\n\n/* Stacked (default): centered column */\n.squisq-page[data-hero-style='stacked'] .squisq-page-hero-body { text-align: center; }\n.squisq-page[data-hero-style='stacked'] .squisq-page-hero-subtitle { margin-inline: auto; }\n\n/* Oversized type: hard left, no decoration */\n.squisq-page[data-hero-style='oversized-type'] .squisq-page-hero-title { font-size: 4.25rem; font-size: clamp(3.25rem, 10cqw, 6.5rem); line-height: 0.98; }\n\n/* Split: text and media side by side */\n.squisq-page-hero-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 3rem; align-items: center; }\n.squisq-page-hero-grid .squisq-page-hero-media img { width: 100%; object-fit: cover; }\n\n/* Full-bleed & letterbox: media behind text */\n.squisq-page-section--hero-media {\n padding-block: 0;\n min-height: min(72svh, 620px);\n display: flex;\n align-items: flex-end;\n}\n.squisq-page[data-hero-style='letterbox'] .squisq-page-section--hero-media { min-height: min(52svh, 460px); }\n.squisq-page-hero-backdrop { position: absolute; inset: 0; overflow: hidden; }\n.squisq-page-hero-backdrop img { width: 100%; height: 100%; object-fit: cover; }\n.squisq-page-hero-backdrop::after {\n content: '';\n position: absolute;\n inset: 0;\n background: linear-gradient(180deg, rgba(0, 0, 0, 0.1) 30%, rgba(0, 0, 0, 0.68) 100%);\n}\n.squisq-page[data-hero-style='letterbox'] .squisq-page-hero-backdrop img { filter: saturate(0.9); }\n.squisq-page-section--hero-media .squisq-page-section-inner { padding-block: 3rem; width: 100%; }\n\n/* \u2500\u2500 Banner (sectionHeader) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-banner-title { font-size: 2rem; }\n.squisq-page[data-heading-scale='display'] .squisq-page-banner-title { font-size: 2.5rem; }\n.squisq-page[data-heading-scale='oversized'] .squisq-page-banner-title { font-size: 3rem; font-size: clamp(2.25rem, 6cqw, 3.75rem); }\n.squisq-page-section--banner.squisq-page-section--bg-media { padding-block: 0; min-height: 280px; display: flex; align-items: flex-end; }\n.squisq-page-section--banner.squisq-page-section--bg-media .squisq-page-section-inner { padding-block: 2rem; width: 100%; }\n.squisq-page-section--banner .squisq-page-section-title { margin-bottom: 0; }\n\n/* \u2500\u2500 Stat band \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-stats { display: flex; gap: 3rem; justify-content: center; text-align: center; flex-wrap: wrap; }\n.squisq-page-stat { flex: 1 1 220px; max-width: 420px; }\n.squisq-page-stat-value {\n display: block;\n font-family: var(--squisq-page-title-font);\n font-weight: 700;\n font-size: 3.25rem;\n line-height: 1;\n color: var(--squisq-page-accent);\n}\n.squisq-page[data-numerals='oversized'] .squisq-page-stat-value { font-size: 4.5rem; font-size: clamp(3.5rem, 8cqw, 5.5rem); }\n.squisq-page[data-numerals='mono'] .squisq-page-stat-value { font-family: var(--squisq-page-mono-font); letter-spacing: -0.02em; }\n.squisq-page[data-numerals='boxed'] .squisq-page-stat-value {\n display: inline-block;\n border: 2px solid var(--squisq-page-accent);\n border-radius: var(--squisq-page-radius);\n padding: 0.18em 0.4em;\n}\n.squisq-page-stat-title { display: block; margin-top: 0.9em; font-size: 1.125rem; font-weight: 600; }\n.squisq-page-stat-body { display: block; margin-top: 0.45em; color: var(--squisq-page-text-muted); font-size: 0.95rem; }\n.squisq-page-stat-meta { text-align: center; margin-top: 1.5rem; color: var(--squisq-page-text-muted); font-size: 0.85rem; }\n.squisq-page-stat-bar { height: 10px; border-radius: 999px; background: var(--squisq-page-accent); margin-top: 0.8em; }\n.squisq-page-stat--bars { text-align: left; }\n\n/* \u2500\u2500 Quote band \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-quote {\n margin: 0;\n font-family: var(--squisq-page-title-font);\n font-size: 1.6rem;\n line-height: 1.35;\n white-space: pre-line;\n}\n.squisq-page-section--em-strong .squisq-page-quote { font-size: 2.1rem; }\n.squisq-page-section--em-quiet .squisq-page-quote { font-size: 1.25rem; color: var(--squisq-page-text-muted); }\n.squisq-page-quote-attribution { margin-top: 1.1em; font-family: var(--squisq-page-body-font); font-size: 0.95rem; color: var(--squisq-page-text-muted); }\n.squisq-page-quote-attribution::before { content: '\u2014 '; }\n.squisq-page[data-quote-mark='accent-bar'] .squisq-page-quote-figure { border-left: 4px solid var(--squisq-page-accent); padding-left: 1.5rem; }\n.squisq-page[data-quote-mark='oversized-glyph'] .squisq-page-quote-figure { position: relative; padding-top: 1.25rem; }\n.squisq-page[data-quote-mark='oversized-glyph'] .squisq-page-quote-figure::before {\n content: '\\201C';\n position: absolute;\n top: -0.12em;\n left: -0.05em;\n font-family: var(--squisq-page-title-font);\n font-size: 5.5rem;\n line-height: 1;\n color: color-mix(in srgb, var(--squisq-page-accent) 42%, transparent);\n pointer-events: none;\n}\n.squisq-page-section--v-display .squisq-page-quote-figure { text-align: center; border-left: none; }\n.squisq-page-section--v-display .squisq-page-quote { font-size: 2.4rem; font-size: clamp(1.9rem, 5cqw, 3rem); }\n.squisq-page-section--v-editorial .squisq-page-quote-figure {\n border-block: 3px solid var(--squisq-page-primary);\n border-left: none;\n padding: 2rem 0.5rem;\n}\n/* Full-bleed quote over media */\n.squisq-page-section--quote-band.squisq-page-section--bg-media { padding-block: 0; min-height: 380px; display: flex; align-items: center; }\n.squisq-page-section--quote-band.squisq-page-section--bg-media .squisq-page-section-inner { padding-block: 3.5rem; }\n.squisq-page-quote-backdrop { position: absolute; inset: 0; overflow: hidden; }\n.squisq-page-quote-backdrop img, .squisq-page-quote-backdrop video { width: 100%; height: 100%; object-fit: cover; }\n.squisq-page-quote-backdrop::after { content: ''; position: absolute; inset: 0; background: rgba(0, 0, 0, 0.55); }\n.squisq-page-section--quote-band[data-hint-vignette] .squisq-page-quote-backdrop::after {\n background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0.35) 0%, rgba(0, 0, 0, 0.75) 100%);\n}\n.squisq-page-section--quote-band.squisq-page-section--bg-media .squisq-page-quote-figure { border: none; text-align: center; }\n\n/* \u2500\u2500 Feature split \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-feature { display: grid; grid-template-columns: 1fr 1fr; gap: 3rem; align-items: center; }\n.squisq-page-feature--media-right .squisq-page-feature-media { order: 2; }\n.squisq-page-feature-media img { width: 100%; object-fit: cover; }\n.squisq-page-feature-title { font-size: 1.75rem; }\n.squisq-page-feature-body { color: var(--squisq-page-text-muted); font-size: 1.05rem; white-space: pre-line; margin: 0; }\n\n/* \u2500\u2500 Media figure \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-figure { margin: 0; }\n.squisq-page-figure img, .squisq-page-figure video { width: 100%; display: block; }\n.squisq-page-figure figcaption { margin-top: 0.9em; font-size: 0.9rem; color: var(--squisq-page-text-muted); text-align: center; }\n.squisq-page-media-credit { font-size: 0.78rem; opacity: 0.75; }\n\n/* Media frame treatment (figures, features, gallery tiles, cards) */\n.squisq-page-media-frame { overflow: hidden; }\n.squisq-page[data-framing='rounded'] .squisq-page-media-frame { border-radius: var(--squisq-page-radius); }\n.squisq-page[data-framing='bordered'] .squisq-page-media-frame { border: 3px solid var(--squisq-page-text); }\n.squisq-page[data-framing='polaroid'] .squisq-page-media-frame {\n background: #ffffff;\n padding: 10px 10px 16px;\n border: 1px solid rgba(0, 0, 0, 0.12);\n border-radius: 2px;\n}\n.squisq-page[data-framing='letterboxed'] .squisq-page-media-frame img { aspect-ratio: 21 / 9; object-fit: cover; }\n.squisq-page[data-framing='circle-accent'] .squisq-page-media-frame { border-radius: calc(var(--squisq-page-radius) * 2); }\n.squisq-page .squisq-page-media-frame { box-shadow: var(--squisq-page-shadow); }\n\n/* Rich body nodes that the selected template did not consume. This universal\n * supplement keeps diagrams/media visible without making every template\n * duplicate the same preservation logic. */\n.squisq-page-rich-content {\n margin-top: clamp(1.5rem, 4vw, 3rem);\n padding-top: clamp(1.25rem, 3vw, 2rem);\n border-top: 1px solid var(--squisq-page-divider-color);\n}\n.squisq-page-rich-content :is(img, video) { display: block; max-width: 100%; height: auto; margin-inline: auto; }\n.squisq-page-rich-content .squisq-md-mermaid { min-height: min(520px, 62vh); margin-block: 0; }\n\n/* \u2500\u2500 Gallery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-gallery { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1.25rem; }\n.squisq-page-gallery .squisq-page-media-frame img { width: 100%; height: 100%; aspect-ratio: 4 / 3; object-fit: cover; }\n.squisq-page-gallery-caption { margin-top: 1.1rem; text-align: center; font-size: 0.9rem; color: var(--squisq-page-text-muted); }\n\n/* \u2500\u2500 Callout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-callout {\n border-radius: var(--squisq-page-radius);\n border: 1px solid color-mix(in srgb, var(--squisq-page-accent) 32%, transparent);\n border-left: 5px solid var(--squisq-page-accent);\n background: color-mix(in srgb, var(--squisq-page-accent) 7%, var(--squisq-page-bg));\n padding: 1.75rem 2rem;\n box-shadow: var(--squisq-page-shadow);\n display: flex;\n gap: 1.75rem;\n align-items: flex-start;\n}\n.squisq-page-callout-title { font-family: var(--squisq-page-title-font); font-size: 1.35rem; font-weight: 700; margin: 0 0 0.5em; }\n.squisq-page-callout-body { margin: 0; white-space: pre-line; }\n.squisq-page-callout-meta { margin-top: 0.9em; font-size: 0.82rem; color: var(--squisq-page-text-muted); }\n.squisq-page-callout .squisq-page-media-frame { flex: 0 0 132px; }\n.squisq-page-callout .squisq-page-media-frame img { width: 132px; height: 132px; object-fit: cover; }\n.squisq-page-callout[data-hint-framing='circle-accent'] .squisq-page-media-frame,\n.squisq-page-callout[data-hint-framing='circle-accent'] .squisq-page-media-frame img { border-radius: 50%; }\n.squisq-page-section--v-definition .squisq-page-callout-title { font-style: italic; }\n.squisq-page-section--v-diagnostic .squisq-page-callout { border-left-color: var(--squisq-page-highlight); }\n\n/* \u2500\u2500 Card grid \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1.5rem; }\n.squisq-page-card {\n border-radius: var(--squisq-page-radius);\n background: var(--squisq-page-bg-alt);\n border-top: 4px solid var(--squisq-page-card-accent, var(--squisq-page-accent));\n padding: 1.75rem 1.75rem 1.9rem;\n box-shadow: var(--squisq-page-shadow);\n}\n.squisq-page-card-title { font-family: var(--squisq-page-title-font); font-size: 1.3rem; margin: 0 0 0.4em; }\n.squisq-page-card-body { margin: 0; color: var(--squisq-page-text-muted); white-space: pre-line; }\n.squisq-page-cards-title { text-align: center; font-size: 1.9rem; margin-bottom: 1.75rem; }\n\n/* \u2500\u2500 Item list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-items { list-style: none; margin: 0; padding: 0; counter-reset: squisq-item; max-width: 40em; }\n.squisq-page-items li {\n counter-increment: squisq-item;\n /* Grid + baseline alignment keeps the marker locked to the first text line\n regardless of marker size, body font, or line-height \u2014 an absolutely\n positioned marker with a fixed top offset drifts as soon as either\n changes. */\n display: grid;\n grid-template-columns: 3.4em 1fr;\n align-items: baseline;\n padding: 0.9em 0;\n font-size: 1.1rem;\n}\n.squisq-page-items li + li { border-top: 1px solid var(--squisq-page-divider-color); }\n.squisq-page-items li::before {\n content: counter(squisq-item, decimal-leading-zero);\n font-family: var(--squisq-page-title-font);\n font-weight: 700;\n color: var(--squisq-page-accent);\n font-size: 1.15em;\n}\n/* Item bodies are rendered markdown: neutralize UA paragraph margins (which\n would otherwise push the first line below the marker) and space blocks. */\n.squisq-page-item-body { min-width: 0; }\n.squisq-page-item-body > * { margin: 0; }\n.squisq-page-item-body > * + * { margin-top: 0.6em; }\n.squisq-page[data-numerals='mono'] .squisq-page-items li::before { font-family: var(--squisq-page-mono-font); }\n.squisq-page-items-title { font-size: 1.9rem; }\n\n/* \u2500\u2500 Timeline rail (dateEvent) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-section--timeline-rail { padding-block: 1.4rem; }\n.squisq-page-section--timeline-rail:first-child { padding-top: var(--squisq-page-section-pad); }\n.squisq-page-milestone { display: grid; grid-template-columns: 150px 1fr; gap: 2rem; align-items: baseline; position: relative; }\n.squisq-page-milestone-date {\n font-family: var(--squisq-page-title-font);\n font-weight: 700;\n color: var(--squisq-page-accent);\n font-size: 1.05rem;\n text-align: right;\n}\n.squisq-page-milestone-rail {\n position: absolute;\n left: 166px;\n top: -1.4rem;\n bottom: -1.4rem;\n width: 2px;\n background: color-mix(in srgb, var(--squisq-page-accent) 35%, transparent);\n}\n.squisq-page-milestone-rail::after {\n content: '';\n position: absolute;\n left: 50%;\n top: 0.55em;\n width: 12px;\n height: 12px;\n border-radius: 50%;\n transform: translateX(-50%);\n background: var(--squisq-page-accent);\n border: 2px solid var(--squisq-page-bg);\n}\n.squisq-page-milestone-body { padding-left: 2.25rem; white-space: pre-line; }\n.squisq-page-milestone-footer { margin-top: 0.5em; font-size: 0.85rem; color: var(--squisq-page-text-muted); }\n\n/* \u2500\u2500 Table section \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-table-title { font-size: 1.9rem; }\n.squisq-page-table-scroll { overflow-x: auto; border-radius: var(--squisq-page-radius); box-shadow: var(--squisq-page-shadow); }\n.squisq-page-table { width: 100%; border-collapse: collapse; font-size: 0.98rem; }\n.squisq-page-table th {\n background: var(--squisq-page-accent-bg);\n color: var(--squisq-page-accent-text);\n font-family: var(--squisq-page-title-font);\n text-align: left;\n padding: 0.8em 1em;\n}\n.squisq-page-table td { padding: 0.7em 1em; border-top: 1px solid var(--squisq-page-divider-color); }\n.squisq-page-table tbody tr:nth-child(even) { background: color-mix(in srgb, var(--squisq-page-text) 3.5%, transparent); }\n\n/* \u2500\u2500 Canvas embed (spatial SVG) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-canvas {\n width: 100%;\n margin-inline: auto;\n overflow: hidden;\n border-radius: var(--squisq-page-radius);\n}\n.squisq-page-canvas svg { display: block; width: 100%; height: 100%; }\n.squisq-page-canvas--framed { border: 1px solid var(--squisq-page-divider-color); box-shadow: var(--squisq-page-shadow); }\n.squisq-page-canvas--terminal { border: 1px solid color-mix(in srgb, var(--squisq-page-accent) 45%, transparent); }\n.squisq-page-canvas--terminal::before {\n content: '\\25CF \\25CF \\25CF';\n display: block;\n font-size: 9px;\n letter-spacing: 4px;\n padding: 6px 12px;\n color: color-mix(in srgb, var(--squisq-page-accent) 70%, transparent);\n background: color-mix(in srgb, var(--squisq-page-accent) 9%, var(--squisq-page-bg));\n border-bottom: 1px solid color-mix(in srgb, var(--squisq-page-accent) 30%, transparent);\n}\n\n/* \u2500\u2500 Prose \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-section--prose { padding-block: calc(var(--squisq-page-section-pad) * 0.45); }\n.squisq-page[data-divider] .squisq-page-section--prose + .squisq-page-section--prose { border-top: none; }\n.squisq-page-prose { font-size: 1.05rem; }\n.squisq-page-prose p { margin: 0; }\n.squisq-page-prose p + p { margin-top: 1.25em; }\n.squisq-page-prose > * + * { margin-top: 1.1em; }\n.squisq-page-prose code { font-family: var(--squisq-page-mono-font); font-size: 0.9em; }\n.squisq-page-prose :not(pre) > code { background: color-mix(in srgb, var(--squisq-page-text) 8%, transparent); border-radius: 4px; padding: 0.12em 0.35em; }\n.squisq-page-prose pre { background: color-mix(in srgb, var(--squisq-page-text) 6%, transparent); border-radius: var(--squisq-page-radius); padding: 1em 1.25em; overflow-x: auto; }\n.squisq-page-prose pre code { background: none; border-radius: 0; padding: 0; }\n.squisq-page .squisq-md-code-frame { position: relative; margin: 1em 0; }\n.squisq-page .squisq-md-code-frame > pre { margin: 0; padding-right: 5rem; }\n.squisq-page .squisq-md-code-copy {\n position: absolute;\n z-index: 1;\n top: 0.55rem;\n right: 0.55rem;\n min-width: 3.7rem;\n padding: 0.28rem 0.5rem;\n border: 1px solid color-mix(in srgb, var(--squisq-page-text) 20%, transparent);\n border-radius: 5px;\n background: color-mix(in srgb, var(--squisq-page-bg) 90%, transparent);\n color: inherit;\n font: 500 0.72rem/1.2 system-ui, sans-serif;\n cursor: pointer;\n opacity: 0.58;\n transition: opacity 120ms ease, background-color 120ms ease;\n}\n.squisq-page .squisq-md-code-frame:hover > .squisq-md-code-copy,\n.squisq-page .squisq-md-code-copy:focus-visible,\n.squisq-page .squisq-md-code-copy[data-copy-state='copied'],\n.squisq-page .squisq-md-code-copy[data-copy-state='failed'] { opacity: 1; }\n.squisq-page .squisq-md-code-copy:hover { background: var(--squisq-page-bg); }\n.squisq-page .squisq-md-code-copy:disabled { cursor: wait; }\n.squisq-page-prose blockquote { margin: 0; border-left: 4px solid var(--squisq-page-accent); padding-left: 1.25em; color: var(--squisq-page-text-muted); }\n.squisq-page-prose ul, .squisq-page-prose ol { padding-left: 1.5em; margin: 0; }\n.squisq-page-prose li + li { margin-top: 0.4em; }\n.squisq-page-prose hr { border: none; border-top: 1px solid var(--squisq-page-divider-color); }\n.squisq-page-prose table { width: 100%; border-collapse: collapse; }\n.squisq-page-prose th { font-family: var(--squisq-page-title-font); text-align: left; padding: 0.6em 0.8em; border-bottom: 2px solid var(--squisq-page-divider-color); }\n.squisq-page-prose td { padding: 0.55em 0.8em; border-bottom: 1px solid var(--squisq-page-divider-color); }\n.squisq-page-prose img { border-radius: var(--squisq-page-radius); }\n.squisq-page-prose h1, .squisq-page-prose h2, .squisq-page-prose h3,\n.squisq-page-prose h4, .squisq-page-prose h5, .squisq-page-prose h6 {\n font-family: var(--squisq-page-title-font);\n font-weight: var(--squisq-page-title-weight);\n line-height: 1.2;\n margin: 0 0 0.45em;\n}\n.squisq-page-prose h1 { font-size: 2.1rem; }\n.squisq-page-prose h2 { font-size: 1.65rem; }\n.squisq-page-prose h3 { font-size: 1.35rem; }\n.squisq-page-prose h4, .squisq-page-prose h5, .squisq-page-prose h6 { font-size: 1.15rem; }\n.squisq-page-section--prose[data-hint-drop-cap] .squisq-page-prose > p:first-child::first-letter {\n font-family: var(--squisq-page-title-font);\n font-size: 3.4em;\n font-weight: 700;\n float: left;\n line-height: 0.85;\n padding-right: 0.12em;\n color: var(--squisq-page-accent);\n}\n\n/* \u2500\u2500 Footer band \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page-section--footer { text-align: center; }\n\n/* \u2500\u2500 Thin-margin embedding (chat bubbles) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.squisq-page--thin .squisq-page-section-inner { padding-inline: 0; }\n.squisq-page--thin .squisq-page-section { padding-block: 1.5rem; }\n\n/* Thumbnail image mode */\n.squisq-page--thumbnail-images .squisq-page-prose img,\n.squisq-page--thumbnail-images .squisq-page-figure img { max-width: 100px; max-height: 100px; object-fit: cover; }\n\n/* \u2500\u2500 Reveal animation (progressive enhancement) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n@media (prefers-reduced-motion: no-preference) {\n .squisq-page-reveal { opacity: 0; transform: translateY(14px); transition: opacity 0.55s ease, transform 0.55s ease; }\n .squisq-page-reveal--in { opacity: 1; transform: none; }\n}\n\n/* \u2500\u2500 Responsive \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n@container squisq-page (max-width: 720px) {\n\n.squisq-page-hero-grid { grid-template-columns: 1fr; gap: 1.5rem; }\n.squisq-page-feature { grid-template-columns: 1fr; }\n.squisq-page-feature--media-right .squisq-page-feature-media { order: 0; }\n.squisq-page-stats { flex-direction: column; gap: 1.75rem; }\n.squisq-page-cards { grid-template-columns: 1fr; }\n.squisq-page-gallery { grid-template-columns: repeat(2, 1fr); }\n.squisq-page-milestone { grid-template-columns: 1fr; gap: 0.5rem; }\n.squisq-page-milestone-rail { display: none; }\n.squisq-page-section-inner { padding-inline: 18px; }\n\n}\n@supports not (container-type: inline-size) {\n @media (max-width: 720px) {\n\n.squisq-page-hero-grid { grid-template-columns: 1fr; gap: 1.5rem; }\n.squisq-page-feature { grid-template-columns: 1fr; }\n.squisq-page-feature--media-right .squisq-page-feature-media { order: 0; }\n.squisq-page-stats { flex-direction: column; gap: 1.75rem; }\n.squisq-page-cards { grid-template-columns: 1fr; }\n.squisq-page-gallery { grid-template-columns: repeat(2, 1fr); }\n.squisq-page-milestone { grid-template-columns: 1fr; gap: 0.5rem; }\n.squisq-page-milestone-rail { display: none; }\n.squisq-page-section-inner { padding-inline: 18px; }\n\n }\n}\n";
2359
2420
  /**
2360
2421
  * Complete stylesheet for a themed page: a `.squisq-page { … }` variable
2361
2422
  * block followed by the structural CSS. For string-HTML consumers; the
@@ -2363,6 +2424,593 @@ declare const PAGE_BASE_CSS = "\n/* \u2500\u2500 Base \u2500\u2500\u2500\u2500\u
2363
2424
  */
2364
2425
  declare function buildPageCss(theme?: Theme): string;
2365
2426
 
2427
+ /**
2428
+ * Supplemental rich-media layout for slideshow blocks.
2429
+ *
2430
+ * Templates still own their no-media composition. When an explicitly
2431
+ * selected text-first template also contains media that it did not consume,
2432
+ * this module selects a second composition with a reserved media rectangle
2433
+ * and maps the template's foreground into the companion content rectangle.
2434
+ * The exhaustive per-template policy selects by viewport orientation, media
2435
+ * aspect, and item count so placement does not depend on a template's name or
2436
+ * incidental overlap between its layers.
2437
+ */
2438
+
2439
+ interface LayerRect {
2440
+ x: number;
2441
+ y: number;
2442
+ width: number;
2443
+ height: number;
2444
+ }
2445
+
2446
+ /**
2447
+ * Dashboard cell zoom policy.
2448
+ *
2449
+ * A cell's "zoom" multiplies the type scale (`TemplateContext.fontScale`)
2450
+ * its block renders with — the %-based composition still targets the cell,
2451
+ * but titles and body text render 1.5×/2× so a sparse block fills its slot
2452
+ * instead of floating in whitespace. Zoom is deliberately a CLOSED ladder
2453
+ * (100% / 150% / 200%), and a dashboard uses at most TWO unique levels —
2454
+ * base 1× plus one boost — so cells still read as consistently sized
2455
+ * rather than each block being fitted independently.
2456
+ *
2457
+ * Levels come from three places, strongest first: an explicit `zoom` on a
2458
+ * custom layout's cell definition (author intent — never changed), the
2459
+ * automatic density pick (short text-led blocks get boosted; spatial,
2460
+ * media, chart, and display-scaled templates always render 1×), and the
2461
+ * `squisq-dashboard-zoom: off` frontmatter kill-switch that pins every
2462
+ * non-explicit cell to 1×.
2463
+ */
2464
+ /** The closed set of zoom multipliers a dashboard cell may render at. */
2465
+ declare const DASHBOARD_ZOOM_LEVELS: readonly [1, 1.5, 2];
2466
+ type DashboardZoomLevel = (typeof DASHBOARD_ZOOM_LEVELS)[number];
2467
+ /** Automatic zoom behavior: density-based boosts, or everything at 1×. */
2468
+ type DashboardZoomMode = 'auto' | 'off';
2469
+ /**
2470
+ * Normalize an authored zoom value to a ladder level. Accepts multipliers
2471
+ * (`1`, `1.5`, `2`) and percentages (`100`, `150`, `200`, `'200%'`).
2472
+ * Returns undefined for anything off the ladder.
2473
+ */
2474
+ declare function normalizeDashboardZoom(value: unknown): DashboardZoomLevel | undefined;
2475
+ /** One cell's input to the zoom policy. */
2476
+ interface DashboardZoomCandidate {
2477
+ /** Resolved template name of the block in this cell. */
2478
+ template?: string;
2479
+ /** Plain-text length of the block's title + body. */
2480
+ textLength: number;
2481
+ /** Author-pinned level from the layout's cell definition. */
2482
+ explicit?: DashboardZoomLevel;
2483
+ }
2484
+ /** The density pick for one cell, before the two-level quantization. */
2485
+ declare function desiredCellZoom(candidate: DashboardZoomCandidate): DashboardZoomLevel;
2486
+ /**
2487
+ * Resolve every cell's final zoom level.
2488
+ *
2489
+ * Explicit levels are honored verbatim. Automatic picks are then
2490
+ * quantized so the dashboard as a whole uses at most base 1× plus ONE
2491
+ * boost level: when both 1.5× and 2× are wanted, the boost with the most
2492
+ * cells wins (explicit pins count double so autos rally to the author's
2493
+ * level; ties boost to 2×), and the other autos snap to it.
2494
+ */
2495
+ declare function resolveDashboardZooms(candidates: readonly DashboardZoomCandidate[], mode: DashboardZoomMode): DashboardZoomLevel[];
2496
+
2497
+ /**
2498
+ * Dashboard layout model.
2499
+ *
2500
+ * A dashboard renders a document's blocks onto ONE canvas: a layout places
2501
+ * N cells (as %-rects) over the canvas's content area, and each cell hosts
2502
+ * one rendered block. Where `materializeBlockLayers` is the slide
2503
+ * projection and `materializePageSections` is the page projection,
2504
+ * `materializeDashboard` (in this directory) is the dashboard projection —
2505
+ * this module holds the layout *definition* shape shared by built-in and
2506
+ * user-authored layouts, plus the geometry helpers that resolve a
2507
+ * definition against a concrete viewport.
2508
+ *
2509
+ * Positions are `%`-strings relative to the layout's CONTENT rect (the
2510
+ * canvas minus the optional title band), mirroring the custom-template
2511
+ * convention: one definition renders at any aspect ratio unchanged.
2512
+ */
2513
+
2514
+ /**
2515
+ * One cell of a dashboard layout. `x`/`y`/`width`/`height` are `%`-strings
2516
+ * relative to the content rect. `block` is an optional 1-based explicit
2517
+ * block assignment ("render block N here"); cells without one fill in
2518
+ * document order.
2519
+ */
2520
+ interface DashboardCellDefinition {
2521
+ x: string;
2522
+ y: string;
2523
+ width: string;
2524
+ height: string;
2525
+ /** 1-based candidate-block index this cell explicitly renders. */
2526
+ block?: number;
2527
+ /**
2528
+ * Type-scale multiplier for the block rendered here: 1, 1.5, or 2
2529
+ * (percent spellings 100/150/200 are accepted and normalized). Pins the
2530
+ * cell's zoom and exempts it from the automatic density pick.
2531
+ */
2532
+ zoom?: number;
2533
+ }
2534
+ /** Where and how tall the optional document-title band renders. */
2535
+ interface DashboardTitleSlotDefinition {
2536
+ /** Which canvas edge hosts the band. Default 'top'. */
2537
+ placement: 'top' | 'bottom';
2538
+ /** Band height as a `%`-string of the canvas height. Default '9%'. */
2539
+ height: string;
2540
+ }
2541
+ /**
2542
+ * A dashboard layout definition — JSON-serializable so built-ins and
2543
+ * frontmatter-authored custom layouts share one schema.
2544
+ */
2545
+ interface DashboardLayoutDefinition {
2546
+ /** Slug id used by `squisq-dashboard-layout` (lowercase, hyphens). */
2547
+ name: string;
2548
+ /** Human-facing picker label. */
2549
+ label: string;
2550
+ description?: string;
2551
+ /**
2552
+ * Per-orientation cell arrays. `landscape` is required and defines the
2553
+ * layout's capacity. Fallbacks when a variant is absent:
2554
+ * square → landscape cells (%-stretch), portrait → transposed landscape.
2555
+ * Variants that are present must match landscape's cell count.
2556
+ */
2557
+ cells: {
2558
+ landscape: DashboardCellDefinition[];
2559
+ portrait?: DashboardCellDefinition[];
2560
+ square?: DashboardCellDefinition[];
2561
+ };
2562
+ /** Overrides the default title band when the doc shows a title. */
2563
+ titleSlot?: DashboardTitleSlotDefinition;
2564
+ /** False excludes the layout from auto-pick (picker-only). Default true. */
2565
+ auto?: boolean;
2566
+ }
2567
+ interface DashboardLayoutValidationError {
2568
+ path: string;
2569
+ message: string;
2570
+ }
2571
+ interface DashboardLayoutValidationResult {
2572
+ valid: boolean;
2573
+ errors: DashboardLayoutValidationError[];
2574
+ /** The normalized definition when `valid` is true. */
2575
+ layout?: DashboardLayoutDefinition;
2576
+ }
2577
+ /** A resolved cell: canvas-unit rect plus the optional explicit pins. */
2578
+ interface ResolvedDashboardCell {
2579
+ rect: LayerRect;
2580
+ block?: number;
2581
+ /** Author-pinned zoom level from the cell definition. */
2582
+ zoom?: DashboardZoomLevel;
2583
+ }
2584
+ /**
2585
+ * Validate an untrusted layout definition (frontmatter, host input) into a
2586
+ * normalized {@link DashboardLayoutDefinition}. Never throws; malformed
2587
+ * definitions come back as `{ valid: false, errors }`.
2588
+ */
2589
+ declare function validateDashboardLayoutDefinition(input: unknown): DashboardLayoutValidationResult;
2590
+ /** Number of blocks the layout can display. */
2591
+ declare function layoutCapacity(def: DashboardLayoutDefinition): number;
2592
+ /**
2593
+ * Swap each cell's axes (x↔y, width↔height) — the automatic portrait
2594
+ * rendition for layouts that only define landscape cells. A row of cells
2595
+ * becomes a column; grids become their transpose.
2596
+ */
2597
+ declare function transposeCells(cells: readonly DashboardCellDefinition[]): DashboardCellDefinition[];
2598
+ /**
2599
+ * Pick the orientation variant (with fallbacks) and resolve its `%`-strings
2600
+ * against a concrete content rect, producing canvas-unit cell rects.
2601
+ */
2602
+ declare function resolveLayoutCells(def: DashboardLayoutDefinition, orientation: ViewportOrientation, contentRect: LayerRect): ResolvedDashboardCell[];
2603
+
2604
+ /**
2605
+ * Built-in dashboard layouts.
2606
+ *
2607
+ * Built-ins use the exact same JSON-serializable schema as user-authored
2608
+ * custom layouts (`squisq-dashboard-layouts` frontmatter), so pickers,
2609
+ * validation, and the auto-pick ladder treat both uniformly. Gutters are
2610
+ * baked into the `%` rects (the photoGrid convention) rather than being a
2611
+ * separate spacing model.
2612
+ */
2613
+
2614
+ /**
2615
+ * The built-in layout library, ordered by capacity — the auto-pick ladder
2616
+ * walks this order. `hero-top` opts out of auto-pick (`auto: false`) so
2617
+ * `grid-2x2` wins the 4-block case; it stays available in pickers.
2618
+ */
2619
+ declare const BUILTIN_DASHBOARD_LAYOUTS: readonly DashboardLayoutDefinition[];
2620
+ /** Picker-facing summary of a layout. */
2621
+ interface DashboardLayoutSummary {
2622
+ id: string;
2623
+ label: string;
2624
+ description?: string;
2625
+ capacity: number;
2626
+ /** True for layouts defined by the document rather than built in. */
2627
+ custom: boolean;
2628
+ }
2629
+ /** Summaries of the built-in layouts, in ladder order. */
2630
+ declare function getDashboardLayoutSummaries(): DashboardLayoutSummary[];
2631
+ /**
2632
+ * Every layout available to a document: its frontmatter-defined custom
2633
+ * layouts first (they win name collisions), then the built-ins. This is
2634
+ * the list pickers and CLI `--layout` validation enumerate.
2635
+ */
2636
+ declare function listDashboardLayouts(doc: Pick<Doc, 'frontmatter'> | undefined): DashboardLayoutSummary[];
2637
+
2638
+ /**
2639
+ * Dashboard layout selection: id lookup plus the auto-pick ladder that
2640
+ * chooses the smallest layout able to hold every block.
2641
+ */
2642
+
2643
+ /** The sentinel layout id meaning "pick the best layout for the doc". */
2644
+ declare const DASHBOARD_AUTO_LAYOUT_ID = "auto";
2645
+ /**
2646
+ * Resolve a layout id against the document's custom layouts (which win
2647
+ * name collisions) and then the built-ins. Undefined when unknown.
2648
+ */
2649
+ declare function resolveDashboardLayoutDefinition(id: string, customLayouts?: readonly DashboardLayoutDefinition[]): DashboardLayoutDefinition | undefined;
2650
+ /**
2651
+ * Auto-pick the best layout for a block count: the smallest-capacity
2652
+ * auto-eligible layout that fits every block, preferring a custom layout
2653
+ * over a built-in at equal capacity. When even the largest layout cannot
2654
+ * hold the count, the largest wins and the caller reports the overflow.
2655
+ *
2656
+ * Orientation deliberately does not change WHICH layout wins — it selects
2657
+ * the cell variant later (via `resolveLayoutCells`) so the same document
2658
+ * keeps the same layout identity across aspect ratios.
2659
+ */
2660
+ declare function chooseDashboardLayout(blockCount: number, _orientation: ViewportOrientation, customLayouts?: readonly DashboardLayoutDefinition[]): DashboardLayoutDefinition;
2661
+
2662
+ /**
2663
+ * Dashboard cell style — the "how it's dressed" axis, orthogonal to the
2664
+ * layout's "where things go".
2665
+ *
2666
+ * A layout answers how many cells there are and what shape they take; a
2667
+ * style answers what a cell LOOKS like: whether the block simply fills its
2668
+ * rect (`basic`, the historical behavior), sits on a raised card, sits in a
2669
+ * flat outlined panel, or on an accent-tinted card. Every style derives its
2670
+ * colors, radius, and accents from the ACTIVE THEME (`colors`,
2671
+ * `style.borderRadius`, `colorSchemes`), so a gezellig dashboard reads as
2672
+ * gezellig and a tech-dark one reads as tech-dark — a style never carries
2673
+ * its own palette.
2674
+ *
2675
+ * Geometry is core-owned like everything else in the dashboard pipeline:
2676
+ * this module returns the card rect the block renders into plus the chrome
2677
+ * layers painted behind it (CELL-LOCAL coordinates — the same space
2678
+ * `materializeDashboard` hands renderers for the title band) and over it
2679
+ * (CARD-LOCAL, so a host clips them with the card's own corner radius).
2680
+ */
2681
+
2682
+ /** The closed set of dashboard cell styles. */
2683
+ declare const DASHBOARD_STYLE_IDS: readonly ["basic", "card", "panel", "accent"];
2684
+ type DashboardStyleId = (typeof DASHBOARD_STYLE_IDS)[number];
2685
+ declare const DEFAULT_DASHBOARD_STYLE: DashboardStyleId;
2686
+ /** Picker-facing summary of a style (mirrors `DashboardLayoutSummary`). */
2687
+ interface DashboardStyleSummary {
2688
+ id: DashboardStyleId;
2689
+ label: string;
2690
+ description: string;
2691
+ }
2692
+ /** The style library, in picker order. */
2693
+ declare const DASHBOARD_STYLES: readonly DashboardStyleSummary[];
2694
+ /** Normalize an authored style value; undefined when unrecognized. */
2695
+ declare function resolveDashboardStyleId(value: unknown): DashboardStyleId | undefined;
2696
+ /**
2697
+ * The canvas fill behind the cells. Card-like styles tint it away from the
2698
+ * card surface (down on light themes, up on dark ones) so cards read as
2699
+ * raised rather than as invisible rectangles on matching paper; flat styles
2700
+ * keep the theme background exactly.
2701
+ */
2702
+ declare function dashboardCanvasFill(style: DashboardStyleId, theme: Theme): string;
2703
+ /**
2704
+ * The accent color for cell `index`. Styles that show an accent rotate
2705
+ * through the theme's own `colorSchemes` (insertion order — the same
2706
+ * vocabulary page mode's `accentRotation` rotates), falling back to the
2707
+ * palette's primary when a theme declares no schemes.
2708
+ */
2709
+ declare function dashboardCellAccent(theme: Theme, index: number): string;
2710
+ /** The chrome + geometry a style contributes to one cell. */
2711
+ interface DashboardCellChrome {
2712
+ /** Card rect in canvas units (the block fills exactly this box). */
2713
+ cardRect: LayerRect;
2714
+ /** Box the block renders into — identical to {@link cardRect}. */
2715
+ contentRect: LayerRect;
2716
+ /** Chrome layers painted BEHIND the block, in cell-local coordinates. */
2717
+ layers: Layer[];
2718
+ /**
2719
+ * Chrome layers painted ON TOP of the block, in card-local coordinates
2720
+ * (origin at the card rect, so a host can clip them with the card's own
2721
+ * radius). Borders and accents live here: a template that paints its own
2722
+ * opaque surface would otherwise bury them.
2723
+ */
2724
+ overlayLayers: Layer[];
2725
+ /** Card corner radius in canvas units. */
2726
+ radius: number;
2727
+ /** CSS `border-radius` for the CONTENT box, percentage-based. */
2728
+ contentRadiusPct?: string;
2729
+ }
2730
+ /**
2731
+ * Build one cell's chrome. Returns null for `basic`, which paints nothing
2732
+ * and leaves the block filling the layout's rect exactly as before.
2733
+ *
2734
+ * The block fills the CARD, rather than sitting in a padded well inside it:
2735
+ * templates already carry their own internal padding, and many paint an
2736
+ * opaque surface or gradient of their own. Letting that surface BE the card
2737
+ * face is what keeps a card from reading as a box inside a box; the chrome
2738
+ * contributes the elevation behind it and the border/accent over it.
2739
+ *
2740
+ * Elevation is drawn as stacked translucent rects rather than an SVG blur
2741
+ * filter: it stays vector-pure, rasterizes identically in the player and in
2742
+ * headless capture, and costs three shapes.
2743
+ */
2744
+ declare function buildDashboardCellChrome(style: DashboardStyleId, options: {
2745
+ theme: Theme;
2746
+ rect: LayerRect;
2747
+ index: number;
2748
+ }): DashboardCellChrome | null;
2749
+ /**
2750
+ * Whether a block's own full-bleed theme-background layer should be
2751
+ * dropped in this style. Card-like styles paint the surface themselves, so
2752
+ * an opaque backdrop from the template would hide the card's tint and
2753
+ * square off its corners. Only a fill that exactly matches the theme
2754
+ * background is ever dropped — a template's accent or gradient backdrop is
2755
+ * authored intent and stays.
2756
+ */
2757
+ declare function stripsBlockBackdrop(style: DashboardStyleId): boolean;
2758
+ /**
2759
+ * Remove a leading full-bleed rect whose fill is exactly the theme
2760
+ * background. Matches `createBackgroundLayer`'s output shape.
2761
+ */
2762
+ declare function stripBlockBackdropLayer(layers: readonly Layer[], theme: Theme): Layer[];
2763
+
2764
+ /**
2765
+ * Dashboard settings persisted in Markdown frontmatter.
2766
+ *
2767
+ * Framework-free (model: `coverSlideSettings.ts`) so the editor, player,
2768
+ * and export pipelines resolve one canonical document contract:
2769
+ *
2770
+ * - `squisq-dashboard-layout`: layout id or `auto` (default `auto`).
2771
+ * - `squisq-dashboard-title`: whether the document title band renders
2772
+ * (default true; the band only appears when a title actually resolves).
2773
+ * - `squisq-dashboard-style`: cell style variant (default `basic`) — the
2774
+ * dressing axis that is orthogonal to the layout's geometry.
2775
+ */
2776
+
2777
+ interface DashboardSettings {
2778
+ /** Preferred layout id, or {@link DASHBOARD_AUTO_LAYOUT_ID}. */
2779
+ layout: string;
2780
+ /** Whether the document-title band renders when a title resolves. */
2781
+ showTitle: boolean;
2782
+ /** Cell zoom behavior: density-based `auto` boosts, or `off` (all 1×). */
2783
+ zoom: DashboardZoomMode;
2784
+ /** Cell style variant (chrome around each block). */
2785
+ style: DashboardStyleId;
2786
+ }
2787
+ declare const DASHBOARD_FRONTMATTER_KEYS: Readonly<{
2788
+ layout: {
2789
+ canonical: string;
2790
+ legacy: string;
2791
+ };
2792
+ showTitle: {
2793
+ canonical: string;
2794
+ legacy: string;
2795
+ };
2796
+ zoom: {
2797
+ canonical: string;
2798
+ legacy: string;
2799
+ };
2800
+ style: {
2801
+ canonical: string;
2802
+ legacy: string;
2803
+ };
2804
+ }>;
2805
+ declare const DEFAULT_DASHBOARD_SETTINGS: Readonly<DashboardSettings>;
2806
+ /**
2807
+ * Caller overrides. `style` is deliberately widened to `string`: hosts pass
2808
+ * raw CLI/UI values through, and an unrecognized one normalizes away rather
2809
+ * than needing a cast at every call site.
2810
+ */
2811
+ type DashboardSettingsOverrides = Partial<Omit<DashboardSettings, 'style'>> & {
2812
+ style?: DashboardStyleId | string;
2813
+ };
2814
+ /** Resolve dashboard settings from frontmatter, then apply caller overrides. */
2815
+ declare function resolveDashboardSettings(frontmatter: Record<string, unknown> | undefined, overrides?: DashboardSettingsOverrides): DashboardSettings;
2816
+
2817
+ /**
2818
+ * Frontmatter serialization for user-defined dashboard layouts.
2819
+ *
2820
+ * Custom layout definitions live in the document's YAML frontmatter under
2821
+ * `squisq-dashboard-layouts` as a single **compact JSON** object keyed by
2822
+ * layout name (the exact convention `squisq-custom-templates` uses — see
2823
+ * `customTemplatesFrontmatter.ts` for the rationale):
2824
+ *
2825
+ * ```yaml
2826
+ * squisq-dashboard-layouts: {"kpi-wall":{"lb":"KPI Wall","ce":{"ls":[{"x":"0%","y":"0%","wd":"50%","hg":"100%","bk":1},…]}}}
2827
+ * ```
2828
+ *
2829
+ * The value is written unquoted on a single line so the line-based
2830
+ * frontmatter parser round-trips it verbatim. Well-known property names
2831
+ * shrink to two-letter codes via {@link LONG_TO_SHORT}; unmapped keys pass
2832
+ * through unchanged, so the format stays lossless as the schema grows.
2833
+ */
2834
+
2835
+ /** Canonical frontmatter key for custom dashboard layouts. */
2836
+ declare const FRONTMATTER_DASHBOARD_LAYOUTS_KEY = "squisq-dashboard-layouts";
2837
+ /**
2838
+ * Read the `squisq-dashboard-layouts` key into validated layout
2839
+ * definitions. Returns undefined when the key is absent or unparseable;
2840
+ * individual malformed entries are dropped rather than failing the doc.
2841
+ */
2842
+ declare function readDashboardLayoutsFromFrontmatter(frontmatter: Record<string, unknown> | undefined): DashboardLayoutDefinition[] | undefined;
2843
+ /**
2844
+ * Encode layout definitions into the compact JSON object described in the
2845
+ * module header. Returns undefined for an empty list so callers can omit
2846
+ * the key entirely.
2847
+ */
2848
+ declare function writeDashboardLayoutsToFrontmatter(layouts: readonly DashboardLayoutDefinition[] | undefined, options?: {
2849
+ pretty?: boolean;
2850
+ }): string | undefined;
2851
+
2852
+ /**
2853
+ * Dashboard projection — the third sibling of the slide projection
2854
+ * (`buildPreviewDoc` + `materializeBlockLayers`) and the page projection
2855
+ * (`materializePageSections`).
2856
+ *
2857
+ * `materializeDashboard(doc, options)` turns a markdown-derived Doc into
2858
+ * ONE canvas: a layout's cells (canvas-unit rects) each holding one block
2859
+ * rendered AT the cell's size — a synthetic per-cell viewport, so
2860
+ * templates re-compose for the cell's orientation and typography scales
2861
+ * via `calculateFontScale` (the same strategy embedded spatial media uses
2862
+ * inside `materializeBlockLayers`). Core owns every geometry decision;
2863
+ * React consumers position cells with the CSS-ready `rectPct` values, and
2864
+ * non-React consumers flatten everything into a single canvas-level
2865
+ * `Layer[]` via {@link composeDashboardLayers}.
2866
+ *
2867
+ * Candidate blocks come from `buildPreviewDoc` (with image interleaving
2868
+ * off) so template resolution and derived inputs match the slideshow
2869
+ * exactly. Blocks beyond the layout's capacity are not rendered — that is
2870
+ * reported as an `overflow` diagnostic, never a console side effect.
2871
+ */
2872
+
2873
+ interface MaterializeDashboardOptions {
2874
+ /** Theme used by cell templates and the canvas backdrop. */
2875
+ theme?: Theme;
2876
+ /** Canvas viewport. Defaults to the landscape preset. */
2877
+ viewport?: ViewportConfig;
2878
+ /**
2879
+ * Layout override: an id, {@link DASHBOARD_AUTO_LAYOUT_ID}, or an inline
2880
+ * definition. Overrides the doc's `squisq-dashboard-layout` frontmatter.
2881
+ */
2882
+ layout?: string | DashboardLayoutDefinition;
2883
+ /** Custom layouts; defaults to the doc's `squisq-dashboard-layouts`. */
2884
+ customLayouts?: readonly DashboardLayoutDefinition[];
2885
+ /** Document-scoped custom templates; defaults to `doc.customTemplates`. */
2886
+ customTemplates?: readonly CustomTemplateDefinition[];
2887
+ /** Title-band override; overrides `squisq-dashboard-title` frontmatter. */
2888
+ showTitle?: boolean;
2889
+ /** Host-supplied title fallback (file name), as in `buildPreviewDoc`. */
2890
+ documentTitle?: string;
2891
+ /** Cell zoom override; overrides `squisq-dashboard-zoom` frontmatter. */
2892
+ zoom?: DashboardZoomMode;
2893
+ /** Cell style override; overrides `squisq-dashboard-style` frontmatter. */
2894
+ style?: DashboardStyleId | string;
2895
+ /** Per-cell failure policy, forwarded to `materializeBlockLayers`. */
2896
+ failureMode?: LayerMaterializationFailureMode;
2897
+ }
2898
+ /** CSS-ready percentages of the FULL canvas for absolute positioning. */
2899
+ interface DashboardRectPct {
2900
+ left: string;
2901
+ top: string;
2902
+ width: string;
2903
+ height: string;
2904
+ }
2905
+ /**
2906
+ * A cell's style chrome — the card/panel surface painted BEHIND the block.
2907
+ * Shaped like {@link DashboardTitle}: layers live in the frame's own
2908
+ * viewport space, so a renderer positions one box and draws into it.
2909
+ * Absent under the `basic` style, which paints no chrome at all.
2910
+ */
2911
+ interface DashboardCellFrame {
2912
+ /** The layout's full cell rect in canvas units (chrome's own box). */
2913
+ rect: LayerRect;
2914
+ /** The frame rect as percentages of the full canvas. */
2915
+ rectPct: DashboardRectPct;
2916
+ /** Viewport the chrome layers were composed against. */
2917
+ viewport: ViewportConfig;
2918
+ /** Chrome layers painted BEHIND the block, in frame-local coordinates. */
2919
+ layers: Layer[];
2920
+ /**
2921
+ * Chrome layers painted ON TOP of the block — borders and accents, which
2922
+ * a template's own opaque surface would otherwise bury. Composed against
2923
+ * {@link DashboardCellFrame.overlayViewport} and positioned at the
2924
+ * block's own rect, so the same clip rounds them to the card's corners.
2925
+ */
2926
+ overlayLayers: Layer[];
2927
+ /** Viewport the overlay layers were composed against (the card box). */
2928
+ overlayViewport: ViewportConfig;
2929
+ /**
2930
+ * CSS `border-radius` (percentage-based, so it scales with any rendered
2931
+ * size) for the block's content box, matching the card's corners. React
2932
+ * consumers apply it with `overflow: hidden` to clip full-bleed cell art.
2933
+ */
2934
+ contentRadiusPct?: string;
2935
+ }
2936
+ /** One populated dashboard cell. */
2937
+ interface DashboardCell {
2938
+ /** Cell ordinal in the layout (0-based, layout order). */
2939
+ index: number;
2940
+ /** The projected slide block rendered in this cell. */
2941
+ block: Block;
2942
+ /** Index in the candidate block sequence (for keys/debugging). */
2943
+ blockIndex: number;
2944
+ /** Layers materialized against {@link DashboardCell.viewport} (un-prefixed). */
2945
+ layers: Layer[];
2946
+ /**
2947
+ * The block's rect in canvas units. Equals the layout cell under `basic`;
2948
+ * under a card style it is the cell inset by the card's padding ring.
2949
+ */
2950
+ rect: LayerRect;
2951
+ /** Block rect as percentages of the full canvas. */
2952
+ rectPct: DashboardRectPct;
2953
+ /** Style chrome painted behind the block; absent under `basic`. */
2954
+ frame?: DashboardCellFrame;
2955
+ /** The synthetic per-cell viewport the layers were rendered against. */
2956
+ viewport: ViewportConfig;
2957
+ /**
2958
+ * Type-scale multiplier the block rendered with (1, 1.5, or 2) — the
2959
+ * layout stays cell-composed, but themed type renders this much larger
2960
+ * so sparse blocks fill their slot. Already baked into `layers`.
2961
+ */
2962
+ zoom: DashboardZoomLevel;
2963
+ source: LayerMaterializationSource;
2964
+ diagnostic?: LayerMaterializationDiagnostic;
2965
+ }
2966
+ interface DashboardDiagnostic {
2967
+ type: 'overflow' | 'unknown-layout' | 'invalid-cell-assignment' | 'empty-doc';
2968
+ message: string;
2969
+ /** Ids of blocks hidden by an `overflow`. */
2970
+ hiddenBlockIds?: string[];
2971
+ /** The unresolvable id behind an `unknown-layout`. */
2972
+ requestedLayout?: string;
2973
+ }
2974
+ /** The rendered document-title band. */
2975
+ interface DashboardTitle {
2976
+ text: string;
2977
+ rect: LayerRect;
2978
+ rectPct: DashboardRectPct;
2979
+ viewport: ViewportConfig;
2980
+ layers: Layer[];
2981
+ }
2982
+ interface DashboardMaterialization {
2983
+ layout: DashboardLayoutDefinition;
2984
+ layoutSource: 'option' | 'frontmatter' | 'auto';
2985
+ /** The resolved cell style variant. */
2986
+ style: DashboardStyleId;
2987
+ viewport: ViewportConfig;
2988
+ cells: DashboardCell[];
2989
+ /** Null when the title band is disabled or no title resolves. */
2990
+ title: DashboardTitle | null;
2991
+ /** Canvas-level base fill + theme/doc persistent layers, applied once. */
2992
+ backdrop: {
2993
+ fill: string;
2994
+ bottomLayers: Layer[];
2995
+ topLayers: Layer[];
2996
+ };
2997
+ diagnostics: DashboardDiagnostic[];
2998
+ }
2999
+ declare function materializeDashboard(doc: Doc, options?: MaterializeDashboardOptions): DashboardMaterialization;
3000
+ /**
3001
+ * Flatten a materialization into one canvas-level `Layer[]` for non-React
3002
+ * consumers. Every cell/title layer is mapped into its canvas rect with a
3003
+ * unique id prefix (templates reuse ids like `title`, so the prefix is
3004
+ * what keeps the flat canvas collision-free). Paint order: backdrop
3005
+ * bottom, then per cell its style chrome followed by its block, then the
3006
+ * title band and the backdrop top.
3007
+ *
3008
+ * The flat canvas has no clipping concept, so a cell's full-bleed art is
3009
+ * not rounded to its card corners here the way a React host clips it with
3010
+ * `frame.contentRadiusPct`.
3011
+ */
3012
+ declare function composeDashboardLayers(materialization: DashboardMaterialization): Layer[];
3013
+
2366
3014
  /**
2367
3015
  * Audio Mapping
2368
3016
  *
@@ -3185,4 +3833,4 @@ declare function treeFromMarkdownList(list: MarkdownList): Tree;
3185
3833
  /** Find the first top-level markdown list in a block's body, if any. */
3186
3834
  declare function findFirstList(contents: MarkdownBlockNode[] | undefined): MarkdownList | undefined;
3187
3835
 
3188
- export { ASCII_CHAR_H, ASCII_CHAR_W, ASCII_DIAGRAM_FENCE_LANGS, ASCII_TIMELINE_FENCE_LANGS, type AccentLayout, type AsciiDiagram, type AsciiDiagramDetection, type AsciiDiagramEdge, type AsciiDiagramNode, type AsciiTimeline, type AsciiTimelineDetection, type AsciiTimelineEvent, type AsciiTimelineLink, type AsciiTimelineMarker, type AsciiTimelineSide, type AsciiTimelineStats, type AsciiTimelineStyle, type AsciiTimelineTrack, type AudioSegmentTiming, BASE_INPUT_DESCRIPTORS, BLOCK_MEDIA_LAYOUT_POLICIES, type BlockLayerMaterialization, type BlockMediaLayoutPolicy, type BuiltInTemplateName, CONTAINER_TEMPLATES, COVER_SLIDE_FRONTMATTER_KEYS, COVER_SLIDE_TEMPLATE_OPTIONS, type ClipBox, type ConnectorAnchor, type ConnectorPort, type ConnectorRouting, type ConnectorSnapPoint, type CoverBlockInput, type CoverSlidePlayback, type CoverSlideSettings, type CoverSlideTemplate, type CoverSlideTemplateOption, DEFAULT_COVER_SLIDE_SETTINGS, DEFAULT_LAYOUT, DIAGRAM_LABEL_HORIZONTAL_PADDING, DIAGRAM_LABEL_LINE_HEIGHT, DIAGRAM_LABEL_MIN_FONT_SIZE, DIAGRAM_LABEL_VERTICAL_PADDING, type DataFenceParseResult, type DeriveTemplateInputsOptions, type DetectAsciiTimelineOptions, type DiagramEdge, type DiagramLabelFit, type DiagramLayout, type DiagramLayoutOptions, type DiagramNodePosition, DocBlock, type DrawingConnector, type DrawingLayout, type DrawingLayoutOptions, type DrawingShape, type DrawingShapeKind, type EmbeddedVideo, type ExpandDocBlocksOptions, type ExtractedTableData, type FirstImage, type InputCoercion, type LayerMaterializationDiagnostic, type LayerMaterializationFailureMode, type LayerMaterializationSource, type LayoutLayerDefaults, type LayoutLayersResult, MAX_COVER_SLIDE_DURATION_SECONDS, type MarkdownToDocOptions, type MarkdownValidationResult, type MaterializeBlockLayersOptions, type NarrationResolution, type NativeMediaLayout, type NoMediaLayout, PAGE_BASE_CSS, PATH_SHAPE_KINDS, PageSection, type PageSectionContext, type PageSectionDraft, PersistentLayerConfig, type RenderAsciiDiagramOptions, type RenderAsciiTimelineOptions, type RenderTreeOptions, type RepairResult, type ResolvedPageBlock, type RichListItem, type RuntimeTemplateRegistry, SHAPE_NAMES, type SectionExtractor, type SupplementalMediaLayoutVariant, type SupplementalMediaShape, type SupplementalMediaVariantMatrix, TABLE_FED_TEMPLATES, TEMPLATE_AUTHORING_METADATA, TEMPLATE_INPUT_DESCRIPTORS, TEMPLATE_METADATA, TREE_FENCE_LANGS, type TemplateAuthoringMetadata, type TemplateAuthoringRole, TemplateBlock, type TemplateBodyPolicy, TemplateContext, type TemplateInputDescriptor, type TemplateMediaOwnership, type TemplateMetadata, type TemplateParamFinding, Theme, ThemeColorScheme, type Tree, type TreeDetection, type TreeItem, type TreeNode, type UnconsumedMediaBehavior, type ValidateOptions, ViewportConfig, ViewportOrientation, adjustY, anchorPoint, applyNarrationTiming, applyRenderStyleToLayers, asciiCellToCanvas, asciiDiagramFromBlocks, asciiDiagramFromTemplateData, asciiDiagramToTemplateData, asciiTimelineToTemplateData, autoTemplatePreservesContent, bigText, buildPageCss, buildPageCssVars, buildRegistry, canvasToAsciiCell, clipEndpoints, clipPoint, coerceTemplateParams, comparisonBar, computeDiagramLayout, computeDrawingLayout, computeLayoutLayers, connectorPath, contentBlock, countBlocks, coverBlock, createAccentLayers, cssFilterForTreatment, dataTable, dateEvent, definitionCard, deriveTemplateInputs, detectAsciiDiagram, detectAsciiTimeline, detectTree, diagramBlock, docToMarkdown, drawingBlock, expandCoverBlock, expandDocBlocks, expandPersistentLayers, extractBlockquoteText, extractBodyPlainText, extractEmbeddedVideos, extractFirstEmbeddedVideo, extractFirstImage, extractImages, extractListItems, extractRichListItems, extractTableData, extractTableFromContents, factCard, fallbackBlockLayers, findFirstList, findFirstTable, fitBigTextSize, fitDiagramLabel, flattenBlocks, flattenRenderableBlocks, fullBleedQuote, getAccentLayout, getAnimationProgress, getAnimationStyle, getAvailableTemplates, getBlockBodyText, getBlockDepth, getBlockMediaLayoutPolicy, getDefaultAnimation, getDefaultAnimationDuration, getOverlayOpacity, getPersistentLayersFromTheme, getPinnedBlockMeta, getTemplateHint, getThemeFont, getTransitionClass, hasTemplate, imageWithCaption, isAsciiDiagramFence, isAsciiTimelineFence, isContainerTemplate, isDataFence, isEligibleAsciiFenceLang, isEligibleAsciiTimelineFenceLang, isEligibleTreeFenceLang, isExplicitDiagramLang, isExplicitTimelineLang, isExplicitTreeLang, isRepairableDiagram, isShapeName, isTemplatedPageBlock, isTreeFence, isWrappedFlowTimelineSource, layoutBlock, leftFeature, lineStyleDasharray, lintTemplateParams, listBlock, mapBlock, markdownToDoc, markerPath, materializeBlockLayers, nearestSnapPoint, normalizeShapeKind, pageStyleDataAttributes, parseAsciiDiagram, parseAsciiTimeline, parseAsciiTimelineWithStats, parseDataFence, parseTree, parseWrappedFlowTimeline, parseYamlSubset, photoGrid, pullQuote, quoteBlock, readCustomTemplatesFromFrontmatter, readCustomThemesFromFrontmatter, renderAsciiDiagram, renderAsciiTimeline, renderTree, repairAsciiDiagram, replaceDataFence, resolveAudioMapping, resolveColorScheme, resolveCoverSlideSettings, resolvePageBlock, resolvePersistentLayers, resolveTemplateName, resolveThemeForDoc, rightFeature, scaleAnimationDuration, scoreTextSimilarity, sectionExtractors, sectionHeader, shapePath, shouldUseShadow, snapEndpoints, snapPoints, statHighlight, templateRegistry, themeWantsAmbientMotion, themedEntrance, themedFontSize, themedImageTreatment, themedScrim, themedSurfaceGradient, timelineBlock, titleBlock, treeBlock, treeFromMarkdownList, treeFromTemplateData, treeToTemplateData, twoColumn, validateMarkdownDoc, validateMarkdownSource, videoPullQuote, videoWithCaption, wrapWithPersistentLayers, writeCustomTemplatesToFrontmatter, writeCustomThemesToFrontmatter };
3836
+ export { ASCII_CHAR_H, ASCII_CHAR_W, ASCII_DIAGRAM_FENCE_LANGS, ASCII_TIMELINE_FENCE_LANGS, type AccentLayout, type AsciiDiagram, type AsciiDiagramDetection, type AsciiDiagramEdge, type AsciiDiagramNode, type AsciiTimeline, type AsciiTimelineDetection, type AsciiTimelineEvent, type AsciiTimelineLink, type AsciiTimelineMarker, type AsciiTimelineSide, type AsciiTimelineStats, type AsciiTimelineStyle, type AsciiTimelineTrack, type AudioSegmentTiming, BASE_INPUT_DESCRIPTORS, BLOCK_MEDIA_LAYOUT_POLICIES, BUILTIN_DASHBOARD_LAYOUTS, type BlockLayerMaterialization, type BlockMediaLayoutPolicy, type BuildPreviewDocOptions, type BuiltInTemplateName, CONTAINER_TEMPLATES, COVER_SLIDE_FRONTMATTER_KEYS, COVER_SLIDE_TEMPLATE_OPTIONS, type ClipBox, type ConnectorAnchor, type ConnectorPort, type ConnectorRouting, type ConnectorSnapPoint, type CoverBlockInput, type CoverSlidePlayback, type CoverSlideSettings, type CoverSlideTemplate, type CoverSlideTemplateOption, DASHBOARD_AUTO_LAYOUT_ID, DASHBOARD_FRONTMATTER_KEYS, DASHBOARD_STYLES, DASHBOARD_STYLE_IDS, DASHBOARD_ZOOM_LEVELS, DEFAULT_COVER_SLIDE_SETTINGS, DEFAULT_DASHBOARD_SETTINGS, DEFAULT_DASHBOARD_STYLE, DEFAULT_LAYOUT, DIAGRAM_LABEL_HORIZONTAL_PADDING, DIAGRAM_LABEL_LINE_HEIGHT, DIAGRAM_LABEL_MIN_FONT_SIZE, DIAGRAM_LABEL_VERTICAL_PADDING, type DashboardCell, type DashboardCellChrome, type DashboardCellDefinition, type DashboardCellFrame, type DashboardDiagnostic, type DashboardLayoutDefinition, type DashboardLayoutSummary, type DashboardLayoutValidationError, type DashboardLayoutValidationResult, type DashboardMaterialization, type DashboardRectPct, type DashboardSettings, type DashboardSettingsOverrides, type DashboardStyleId, type DashboardStyleSummary, type DashboardTitle, type DashboardTitleSlotDefinition, type DashboardZoomCandidate, type DashboardZoomLevel, type DashboardZoomMode, type DataFenceParseResult, type DeriveTemplateInputsOptions, type DetectAsciiTimelineOptions, type DiagramEdge, type DiagramLabelFit, type DiagramLayout, type DiagramLayoutOptions, type DiagramNodePosition, DocBlock, type DrawingConnector, type DrawingLayout, type DrawingLayoutOptions, type DrawingShape, type DrawingShapeKind, type EmbeddedVideo, type ExpandDocBlocksOptions, type ExtractedTableData, FRONTMATTER_DASHBOARD_LAYOUTS_KEY, type FirstImage, type InputCoercion, type LayerMaterializationDiagnostic, type LayerMaterializationFailureMode, type LayerMaterializationSource, type LayoutLayerDefaults, type LayoutLayersResult, MAX_COVER_SLIDE_DURATION_SECONDS, type MarkdownToDocOptions, type MarkdownValidationResult, type MaterializeBlockLayersOptions, type MaterializeDashboardOptions, type NarrationResolution, type NativeMediaLayout, type NoMediaLayout, PAGE_BASE_CSS, PATH_SHAPE_KINDS, PageSection, type PageSectionContext, type PageSectionDraft, PersistentLayerConfig, type RenderAsciiDiagramOptions, type RenderAsciiTimelineOptions, type RenderTreeOptions, type RepairResult, type ResolvedDashboardCell, type ResolvedPageBlock, type RichListItem, type RuntimeTemplateRegistry, SHAPE_NAMES, type SectionExtractor, type SupplementalMediaLayoutVariant, type SupplementalMediaShape, type SupplementalMediaVariantMatrix, TABLE_FED_TEMPLATES, TEMPLATE_AUTHORING_METADATA, TEMPLATE_INPUT_DESCRIPTORS, TEMPLATE_METADATA, TREE_FENCE_LANGS, type TemplateAuthoringMetadata, type TemplateAuthoringRole, TemplateBlock, type TemplateBodyPolicy, TemplateContext, type TemplateInputDescriptor, type TemplateMediaOwnership, type TemplateMetadata, type TemplateParamFinding, Theme, ThemeColorScheme, type Tree, type TreeDetection, type TreeItem, type TreeNode, type UnconsumedMediaBehavior, type ValidateOptions, ViewportConfig, ViewportOrientation, adjustY, anchorPoint, applyNarrationTiming, applyRenderStyleToLayers, asciiCellToCanvas, asciiDiagramFromBlocks, asciiDiagramFromTemplateData, asciiDiagramToTemplateData, asciiTimelineToTemplateData, autoTemplatePreservesContent, bigText, buildDashboardCellChrome, buildPageCss, buildPageCssVars, buildPreviewDoc, buildRegistry, canvasToAsciiCell, chooseDashboardLayout, clipEndpoints, clipPoint, coerceTemplateParams, comparisonBar, composeDashboardLayers, computeDiagramLayout, computeDrawingLayout, computeLayoutLayers, connectorPath, contentBlock, countBlocks, coverBlock, createAccentLayers, cssFilterForTreatment, dashboardCanvasFill, dashboardCellAccent, dataTable, dateEvent, definitionCard, deriveTemplateInputs, desiredCellZoom, detectAsciiDiagram, detectAsciiTimeline, detectTree, diagramBlock, docToMarkdown, documentTitleFromFileName, drawingBlock, expandCoverBlock, expandDocBlocks, expandPersistentLayers, extractBlockquoteText, extractBodyPlainText, extractEmbeddedVideos, extractFirstEmbeddedVideo, extractFirstImage, extractImages, extractListItems, extractRichListItems, extractTableData, extractTableFromContents, factCard, fallbackBlockLayers, findFirstList, findFirstTable, fitBigTextSize, fitDiagramLabel, flattenBlocks, flattenRenderableBlocks, fullBleedQuote, getAccentLayout, getAnimationProgress, getAnimationStyle, getAvailableTemplates, getBlockBodyText, getBlockDepth, getBlockMediaLayoutPolicy, getDashboardLayoutSummaries, getDefaultAnimation, getDefaultAnimationDuration, getOverlayOpacity, getPersistentLayersFromTheme, getPinnedBlockMeta, getTemplateHint, getThemeFont, getTransitionClass, hasTemplate, imageWithCaption, isAsciiDiagramFence, isAsciiTimelineFence, isContainerTemplate, isDataFence, isEligibleAsciiFenceLang, isEligibleAsciiTimelineFenceLang, isEligibleTreeFenceLang, isExplicitDiagramLang, isExplicitTimelineLang, isExplicitTreeLang, isRepairableDiagram, isShapeName, isTemplatedPageBlock, isTreeFence, isWrappedFlowTimelineSource, layoutBlock, layoutCapacity, leftFeature, lineStyleDasharray, lintTemplateParams, listBlock, listDashboardLayouts, mapBlock, markdownToDoc, markerPath, materializeBlockLayers, materializeDashboard, nearestSnapPoint, normalizeDashboardZoom, normalizeShapeKind, pageStyleDataAttributes, parseAsciiDiagram, parseAsciiTimeline, parseAsciiTimelineWithStats, parseDataFence, parseTree, parseWrappedFlowTimeline, parseYamlSubset, photoGrid, pullQuote, quoteBlock, readCustomTemplatesFromFrontmatter, readCustomThemesFromFrontmatter, readDashboardLayoutsFromFrontmatter, renderAsciiDiagram, renderAsciiTimeline, renderTree, repairAsciiDiagram, replaceDataFence, resolveAudioMapping, resolveColorScheme, resolveCoverSlideSettings, resolveDashboardLayoutDefinition, resolveDashboardSettings, resolveDashboardStyleId, resolveDashboardZooms, resolveLayoutCells, resolvePageBlock, resolvePersistentLayers, resolveTemplateName, resolveThemeForDoc, rightFeature, scaleAnimationDuration, scoreTextSimilarity, sectionExtractors, sectionHeader, shapePath, shouldUseShadow, snapEndpoints, snapPoints, statHighlight, stripBlockBackdropLayer, stripsBlockBackdrop, templateRegistry, themeWantsAmbientMotion, themedEntrance, themedFontSize, themedImageTreatment, themedScrim, themedSurfaceGradient, timelineBlock, titleBlock, transposeCells, treeBlock, treeFromMarkdownList, treeFromTemplateData, treeToTemplateData, twoColumn, validateDashboardLayoutDefinition, validateMarkdownDoc, validateMarkdownSource, videoPullQuote, videoWithCaption, wrapWithPersistentLayers, writeCustomTemplatesToFrontmatter, writeCustomThemesToFrontmatter, writeDashboardLayoutsToFrontmatter };