explico 0.7.0 → 0.11.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.
- package/CHANGELOG.md +1409 -1
- package/README.md +60 -15
- package/dist/compiler/astro.d.ts +6 -1
- package/dist/compiler/cli.d.ts +54 -3
- package/dist/compiler/cli.js +80 -6
- package/dist/compiler/collections.d.ts +35 -2
- package/dist/compiler/collections.js +84 -8
- package/dist/compiler/course-config.d.ts +3 -194
- package/dist/compiler/course-config.js +78 -5
- package/dist/compiler/exports/standalone-html.d.ts +6 -1
- package/dist/compiler/knowledge-version.js +1 -1
- package/dist/compiler/lesson-derivation.d.ts +27 -10
- package/dist/compiler/lesson-derivation.js +23 -8
- package/dist/compiler/logging.d.ts +14 -1
- package/dist/compiler/logging.js +6 -2
- package/dist/compiler/manifest.d.ts +204 -31
- package/dist/compiler/manifest.js +270 -55
- package/dist/compiler/resolution-report.d.ts +6 -1
- package/dist/course-config-Dsnri9Tk.d.ts +464 -0
- package/dist/reference/base-accents.d.mts +26 -0
- package/dist/reference/base-accents.mjs +31 -0
- package/dist/reference/base-roman-labels.d.mts +2 -2
- package/dist/reference/base-roman-labels.mjs +2 -2
- package/dist/reference/consistency.d.ts +14 -2
- package/dist/reference/consistency.js +108 -4
- package/dist/reference/delimiter-size.d.ts +21 -11
- package/dist/reference/delimiter-size.js +15 -39
- package/dist/reference/diagrams-validate.d.ts +7 -2
- package/dist/reference/diagrams-validate.js +9 -1
- package/dist/reference/equations-validate.d.ts +8 -5
- package/dist/reference/equations-validate.js +1 -0
- package/dist/reference/equations.d.mts +69 -34
- package/dist/reference/equations.mjs +90 -44
- package/dist/reference/examples-validate.d.ts +31 -0
- package/dist/reference/examples-validate.js +48 -0
- package/dist/reference/figures-validate.d.ts +1 -1
- package/dist/reference/figures-validate.js +4 -1
- package/dist/reference/folds-validate.d.ts +33 -0
- package/dist/reference/folds-validate.js +32 -0
- package/dist/reference/gate-abbreviations.d.ts +3 -1
- package/dist/reference/gate-abbreviations.js +3 -2
- package/dist/reference/gate-course-rules.d.ts +32 -0
- package/dist/reference/gate-course-rules.js +85 -0
- package/dist/reference/gate-heading-length.d.ts +5 -2
- package/dist/reference/gate-heading-length.js +47 -23
- package/dist/reference/gate-heading-structure.d.ts +41 -0
- package/dist/reference/gate-heading-structure.js +113 -0
- package/dist/reference/gate-math-punctuation.d.ts +71 -0
- package/dist/reference/gate-math-punctuation.js +251 -0
- package/dist/reference/gate-math.d.ts +44 -6
- package/dist/reference/gate-math.js +63 -10
- package/dist/reference/gate-part-pages.d.ts +50 -0
- package/dist/reference/gate-part-pages.js +118 -0
- package/dist/reference/gate-prose-notation.d.ts +32 -11
- package/dist/reference/gate-prose-notation.js +30 -8
- package/dist/reference/katex-delimiters.d.mts +15 -0
- package/dist/reference/katex-delimiters.mjs +138 -0
- package/dist/reference/katex-options.mjs +4 -0
- package/dist/reference/keyed-float-validate.d.ts +27 -10
- package/dist/reference/keyed-float-validate.js +15 -1
- package/dist/reference/keyed-jsx-floats.d.mts +11 -5
- package/dist/reference/keyed-jsx-floats.mjs +73 -20
- package/dist/reference/knowledge-checks-validate.d.ts +1 -1
- package/dist/reference/knowledge-checks.d.mts +3 -1
- package/dist/reference/knowledge-checks.mjs +9 -4
- package/dist/reference/lab-math-scope.d.ts +1 -0
- package/dist/reference/lab-math-slot.d.ts +34 -0
- package/dist/reference/lab-math-slot.js +6 -0
- package/dist/reference/math-glyphs.d.mts +80 -4
- package/dist/reference/math-glyphs.mjs +588 -39
- package/dist/reference/page-notation.d.ts +6 -1
- package/dist/reference/raw-floats-validate.js +1 -1
- package/dist/reference/raw-floats.mjs +1 -1
- package/dist/reference/rehype-heading-anchors.d.mts +14 -0
- package/dist/reference/rehype-heading-anchors.mjs +116 -17
- package/dist/reference/rehype-table-header-labels.d.mts +6 -1
- package/dist/reference/rehype-table-header-labels.mjs +21 -3
- package/dist/reference/remark-asides.d.mts +3 -0
- package/dist/reference/remark-asides.mjs +180 -0
- package/dist/reference/remark-memo.d.mts +3 -1
- package/dist/reference/remark-memo.mjs +42 -11
- package/dist/reference/remark-notation.d.mts +60 -10
- package/dist/reference/remark-notation.mjs +387 -36
- package/dist/reference/render-lab-math.d.ts +4 -26
- package/dist/reference/render-lab-math.js +5 -5
- package/dist/reference/sections-validate.d.ts +27 -0
- package/dist/reference/sections-validate.js +41 -0
- package/dist/reference/sections.d.mts +97 -0
- package/dist/reference/sections.mjs +306 -0
- package/dist/reference/tables-validate.d.ts +1 -1
- package/dist/reference/types.d.ts +24 -1
- package/dist/reference/unit-words.d.ts +37 -0
- package/dist/reference/unit-words.js +170 -0
- package/dist/rules/catalog.d.ts +176 -0
- package/dist/rules/catalog.js +983 -0
- package/dist/rules/course-rules.d.ts +115 -0
- package/dist/rules/course-rules.js +292 -0
- package/dist/rules/course-rules.schema.json +138 -0
- package/dist/rules/in-effect.d.ts +53 -0
- package/dist/rules/in-effect.js +142 -0
- package/dist/rules/rules.schema.json +1072 -0
- package/dist/rules/settings.d.ts +3 -0
- package/dist/rules/settings.js +290 -0
- package/dist/rules/waivers.d.ts +53 -0
- package/dist/rules/waivers.js +132 -0
- package/dist/session/PreferenceStore.d.ts +5 -0
- package/dist/session/PreferenceStore.js +9 -0
- package/docs/VERSIONING.md +2 -2
- package/docs/authoring/README.md +232 -40
- package/docs/authoring/agents.md +55 -9
- package/docs/authoring/components.md +178 -22
- package/docs/authoring/migrating.md +1324 -2
- package/docs/authoring/notation.md +616 -344
- package/docs/authoring/prose.md +551 -0
- package/docs/authoring/retired.md +35 -0
- package/docs/authoring/structure-rules.md +422 -40
- package/docs/authoring/structure.md +445 -62
- package/docs/authoring/versioning.md +20 -28
- package/docs/authoring/visualizations.md +142 -20
- package/docs/katex-bracket-scaling.md +191 -0
- package/package.json +3 -2
- package/src/compiler/cli.ts +139 -6
- package/src/compiler/collections.ts +144 -10
- package/src/compiler/course-config.ts +273 -34
- package/src/compiler/knowledge-version.ts +1 -1
- package/src/compiler/lesson-derivation.ts +54 -15
- package/src/compiler/logging.ts +21 -4
- package/src/compiler/manifest.ts +573 -104
- package/src/components/BlockHeading.astro +113 -0
- package/src/components/CourseContents.astro +221 -0
- package/src/components/CurriculumMap.astro +5 -6
- package/src/components/FloatIndex.astro +200 -0
- package/src/components/HoverPanel.astro +431 -79
- package/src/components/PartBridge.astro +27 -0
- package/src/components/PartOverview.astro +401 -0
- package/src/components/PartScope.astro +27 -0
- package/src/components/abbreviation/AbbreviationLayer.astro +49 -51
- package/src/components/assessments/AssessmentRunner.tsx +8 -5
- package/src/components/assessments/AssessmentSet.astro +23 -26
- package/src/components/block-heading.ts +146 -0
- package/src/components/card-arrow.ts +243 -0
- package/src/components/card-drag.ts +631 -0
- package/src/components/card-jump.ts +45 -0
- package/src/components/card-manager.ts +1589 -0
- package/src/components/card-memory.ts +177 -0
- package/src/components/card-placement.ts +504 -0
- package/src/components/card-side.ts +336 -0
- package/src/components/card-travel.ts +197 -0
- package/src/components/citation/CitationLayer.astro +77 -76
- package/src/components/diagram/Diagram.astro +161 -316
- package/src/components/disclosure/course-disclosure.ts +24 -0
- package/src/components/disclosure/hover-preview.ts +122 -42
- package/src/components/disclosure/persisted-disclosure.ts +3 -3
- package/src/components/disclosure/print-as-shown.ts +252 -0
- package/src/components/examples/CompactExample.astro +3 -1
- package/src/components/examples/CompactExamples.astro +101 -94
- package/src/components/figure/Figure.astro +174 -274
- package/src/components/figure/FloatCaption.astro +87 -0
- package/src/components/figure/figure-state.ts +58 -0
- package/src/components/figure/figure-tools.ts +87 -0
- package/src/components/float-name.ts +101 -0
- package/src/components/fold/Fold.astro +125 -0
- package/src/components/fold/fold-id.ts +40 -0
- package/src/components/memo/Memo.astro +162 -231
- package/src/components/memo/ShortNote.astro +6 -6
- package/src/components/notation/NotationFormula.astro +5 -1
- package/src/components/notation/NotationGlossary.astro +24 -14
- package/src/components/notation/NotationLayer.astro +169 -162
- package/src/components/notation/NotationMath.astro +10 -1
- package/src/components/notation/render-notation-math.ts +111 -10
- package/src/components/reference/FloatRefLayer.astro +485 -423
- package/src/components/starlight/AboutPanel.astro +22 -6
- package/src/components/starlight/CollapsibleSections.astro +207 -93
- package/src/components/starlight/DiagramEnhancer.astro +15 -138
- package/src/components/starlight/HeadingAnchorEnhancer.astro +193 -1
- package/src/components/starlight/KeyedFloatEnhancer.astro +100 -9
- package/src/components/starlight/LayoutHeader.astro +298 -19
- package/src/components/starlight/LayoutPageSidebar.astro +99 -12
- package/src/components/starlight/LayoutPageTitle.astro +120 -0
- package/src/components/starlight/LayoutSidebar.astro +229 -11
- package/src/components/starlight/LessonExportActions.astro +53 -72
- package/src/components/starlight/LessonFooter.astro +26 -4
- package/src/components/starlight/section-parts.ts +15 -2
- package/src/components/starlight/section-summary.ts +181 -0
- package/src/components/table/Table.astro +95 -76
- package/src/components/table/TableOverflowExpander.astro +65 -28
- package/src/content-config.ts +40 -4
- package/src/reference/base-accents.mjs +31 -0
- package/src/reference/base-roman-labels.mjs +2 -2
- package/src/reference/consistency.ts +176 -5
- package/src/reference/delimiter-size.ts +40 -61
- package/src/reference/diagrams-validate.ts +17 -1
- package/src/reference/equations-validate.ts +10 -5
- package/src/reference/equations.mjs +90 -44
- package/src/reference/examples-validate.ts +97 -0
- package/src/reference/figures-validate.ts +6 -1
- package/src/reference/folds-validate.ts +65 -0
- package/src/reference/gate-abbreviations.ts +3 -2
- package/src/reference/gate-course-rules.ts +134 -0
- package/src/reference/gate-heading-length.ts +68 -37
- package/src/reference/gate-heading-structure.ts +193 -0
- package/src/reference/gate-math-punctuation.ts +381 -0
- package/src/reference/gate-math.ts +119 -12
- package/src/reference/gate-part-pages.ts +217 -0
- package/src/reference/gate-prose-notation.ts +74 -13
- package/src/reference/katex-delimiters.mjs +138 -0
- package/src/reference/katex-options.mjs +4 -0
- package/src/reference/keyed-float-validate.ts +45 -11
- package/src/reference/keyed-jsx-floats.mjs +73 -20
- package/src/reference/knowledge-checks-validate.ts +1 -1
- package/src/reference/knowledge-checks.mjs +9 -4
- package/src/reference/lab-math-slot.ts +36 -0
- package/src/reference/math-glyphs.mjs +588 -39
- package/src/reference/raw-floats-validate.ts +1 -1
- package/src/reference/raw-floats.mjs +1 -1
- package/src/reference/rehype-heading-anchors.mjs +116 -17
- package/src/reference/rehype-table-header-labels.mjs +21 -3
- package/src/reference/remark-asides.mjs +180 -0
- package/src/reference/remark-memo.mjs +42 -11
- package/src/reference/remark-notation.mjs +387 -36
- package/src/reference/render-lab-math.ts +17 -32
- package/src/reference/sections-validate.ts +81 -0
- package/src/reference/sections.mjs +306 -0
- package/src/reference/tables-validate.ts +2 -1
- package/src/reference/types.ts +24 -0
- package/src/reference/unit-words.ts +233 -0
- package/src/rules/catalog.ts +1298 -0
- package/src/rules/course-rules.ts +456 -0
- package/src/rules/in-effect.ts +235 -0
- package/src/rules/settings.ts +448 -0
- package/src/rules/waivers.ts +249 -0
- package/src/session/PreferenceStore.ts +15 -0
- package/src/styles/global.css +1471 -163
- package/src/styles/surfaces.css +182 -0
- package/src/components/hover-panel.ts +0 -339
- package/src/components/popup-stack.ts +0 -345
package/src/styles/global.css
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
@import 'katex/dist/katex.min.css';
|
|
2
|
+
@import './surfaces.css';
|
|
2
3
|
|
|
3
4
|
:root {
|
|
4
5
|
--sl-color-accent-low: #132f2a;
|
|
@@ -13,6 +14,57 @@
|
|
|
13
14
|
--sl-color-accent-high: #123c32;
|
|
14
15
|
}
|
|
15
16
|
|
|
17
|
+
/* Heading sizes, one even step (about 1.25) apart. Starlight's defaults are
|
|
18
|
+
sized for a wide docs column: from 50em up an h2 is 35px, which fits some
|
|
19
|
+
25 characters of a lesson column. Everything that sizes itself from a
|
|
20
|
+
heading reads these tokens — the section chevron's centring, a folded bar,
|
|
21
|
+
the `1.5em` above a section — so it all follows. Both breakpoints are set
|
|
22
|
+
here: Starlight's own values are layered, so this unlayered block would
|
|
23
|
+
otherwise beat its wide-screen step too. */
|
|
24
|
+
:root {
|
|
25
|
+
--sl-text-h1: 1.875rem;
|
|
26
|
+
--sl-text-h2: 1.5rem;
|
|
27
|
+
--sl-text-h3: 1.25rem;
|
|
28
|
+
--sl-text-h4: 1.0625rem;
|
|
29
|
+
--sl-text-h5: 1rem;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@media (min-width: 50em) {
|
|
33
|
+
:root {
|
|
34
|
+
--sl-text-h1: 2.25rem;
|
|
35
|
+
--sl-text-h2: 1.75rem;
|
|
36
|
+
--sl-text-h3: 1.375rem;
|
|
37
|
+
--sl-text-h4: 1.125rem;
|
|
38
|
+
--sl-text-h5: 1rem;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* Previous / Next under a lesson: side by side down to a 26rem column.
|
|
43
|
+
Starlight stacks them below 2 × 18rem, and a lesson column between both
|
|
44
|
+
sidebars is already narrower than that, so every page ended in two
|
|
45
|
+
full-width cards. Their titles are one step smaller. Starlight's footer
|
|
46
|
+
also keeps a 3rem top margin for its "last updated" and edit links; a
|
|
47
|
+
course that shows neither keeps only the footer's own gap. Starlight's
|
|
48
|
+
rules are layered, so these unlayered ones win. */
|
|
49
|
+
.pagination-links {
|
|
50
|
+
grid-template-columns: repeat(auto-fit, minmax(min(12.5rem, 100%), 1fr));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.pagination-links .link-title {
|
|
54
|
+
font-size: var(--sl-text-lg);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
footer .meta:not(:has(*)) {
|
|
58
|
+
margin-top: 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* The first block under the title keeps only the content panel's own
|
|
62
|
+
padding; a card's or a section's top margin on top of it doubled the gap
|
|
63
|
+
under the title rule. */
|
|
64
|
+
.sl-markdown-content > :first-child {
|
|
65
|
+
margin-block-start: 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
16
68
|
/* Every intentionally wide surface owns a local horizontal scroller. Keep a
|
|
17
69
|
replaced element (notably an SVG containing `foreignObject`) from widening
|
|
18
70
|
iOS WebKit's layout viewport before that local overflow rule takes effect.
|
|
@@ -25,31 +77,32 @@ body {
|
|
|
25
77
|
|
|
26
78
|
.lab-shell {
|
|
27
79
|
margin-block: 1.5rem;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
is defined in both. */
|
|
36
|
-
background: color-mix(in srgb, var(--sl-color-bg) 94%, var(--sl-color-accent) 6%);
|
|
37
|
-
box-shadow: 0 1rem 2.6rem rgba(0, 0, 0, 0.13);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/* A lab already wrapped in a `<Figure>` sits inside `.keyed-figure__details`,
|
|
41
|
-
which draws this exact same card (border, thick top line, tinted
|
|
42
|
-
background) around the title *and* the lab together — a nested
|
|
43
|
-
`.lab-shell` drawing its own copy of that card again would stack two
|
|
44
|
-
borders/backgrounds/lines instead of one. Strip it back to plain spacing
|
|
45
|
-
here; a `.lab-shell` used on its own (not inside a figure) is unaffected. */
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* A lab is figure material, and a figure is the plain tier (`surfaces.css`):
|
|
83
|
+
no card of its own, only spacing. Inside a `<Figure>` the figure's own
|
|
84
|
+
margin already spaces it. A lab that should read as set apart goes in a
|
|
85
|
+
`### … [card]` section instead (docs/plans/titles-and-containers.md,
|
|
86
|
+
settled decision 7). */
|
|
46
87
|
.keyed-figure__body .lab-shell {
|
|
47
88
|
margin-block: 0;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/* A lab's tools, in the tray after its figure's caption line
|
|
92
|
+
(`Figure.astro`'s `tools` slot): the tray pads them, so they bring no
|
|
93
|
+
margin of their own. Their first line says what to do. */
|
|
94
|
+
.keyed-figure__tools .lab-shell {
|
|
95
|
+
margin-block: 0;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.lab-tools > :last-child {
|
|
99
|
+
margin-block-end: 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.lab-instruction {
|
|
103
|
+
margin-block: 0 0.75rem;
|
|
104
|
+
font-size: var(--sl-text-sm);
|
|
105
|
+
color: var(--sl-color-gray-2);
|
|
53
106
|
}
|
|
54
107
|
|
|
55
108
|
.lab-shell label,
|
|
@@ -113,21 +166,25 @@ body {
|
|
|
113
166
|
|
|
114
167
|
/* Long lesson equations must scroll inside the content column instead of
|
|
115
168
|
widening the entire page. This also contains KaTeX's visually hidden MathML
|
|
116
|
-
tree, whose intrinsic width can otherwise affect narrow viewports.
|
|
169
|
+
tree, whose intrinsic width can otherwise affect narrow viewports.
|
|
170
|
+
`overflow-y: hidden` clips at the padding edge, and with no padding that
|
|
171
|
+
edge is KaTeX's metric strut — but glyph ink overshoots its metrics (a
|
|
172
|
+
denominator's `g` descender, a stretched `\right]`), so the bottom of the
|
|
173
|
+
equation was cut off. The padding is the room that ink needs; em-based so
|
|
174
|
+
it scales with the math. */
|
|
117
175
|
.sl-markdown-content .katex-display {
|
|
118
176
|
max-width: 100%;
|
|
119
177
|
overflow-x: auto;
|
|
120
178
|
overflow-y: hidden;
|
|
179
|
+
padding-block: 0.25em;
|
|
121
180
|
}
|
|
122
181
|
|
|
123
|
-
.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
font-size: 0.85rem;
|
|
130
|
-
color: var(--sl-color-gray-2);
|
|
182
|
+
/* Focusable only while it overflows (`KeyedFloatEnhancer.astro`), so it can
|
|
183
|
+
be scrolled from the keyboard. */
|
|
184
|
+
.sl-markdown-content .katex-display:focus-visible {
|
|
185
|
+
outline: 2px solid var(--sl-color-accent);
|
|
186
|
+
outline-offset: 2px;
|
|
187
|
+
border-radius: 0.2rem;
|
|
131
188
|
}
|
|
132
189
|
|
|
133
190
|
.lab-controls {
|
|
@@ -236,12 +293,11 @@ body {
|
|
|
236
293
|
margin: 0;
|
|
237
294
|
}
|
|
238
295
|
|
|
296
|
+
/* A knowledge check is one accent card around its heading and this shell
|
|
297
|
+
together (`AssessmentSet.astro` marks the heading `data-card="accent"`,
|
|
298
|
+
`CollapsibleSections.astro` draws the card), so the shell itself is plain. */
|
|
239
299
|
.assessment-shell {
|
|
240
|
-
margin-block: 0.75rem
|
|
241
|
-
padding: clamp(1rem, 3vw, 1.5rem);
|
|
242
|
-
border: 1px solid var(--sl-color-gray-5);
|
|
243
|
-
border-radius: 0.75rem;
|
|
244
|
-
background: var(--sl-color-gray-7);
|
|
300
|
+
margin-block: 0.75rem 0;
|
|
245
301
|
}
|
|
246
302
|
|
|
247
303
|
.assessment-shell :focus-visible {
|
|
@@ -249,23 +305,22 @@ body {
|
|
|
249
305
|
outline-offset: 2px;
|
|
250
306
|
}
|
|
251
307
|
|
|
252
|
-
.assessment-heading-number {
|
|
253
|
-
color: var(--sl-color-text-accent);
|
|
254
|
-
white-space: nowrap;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
308
|
.assessment-shell > h3 {
|
|
258
309
|
margin-block: 0 0.75rem;
|
|
259
310
|
}
|
|
260
311
|
|
|
261
312
|
.assessment-progress {
|
|
262
|
-
margin: 0 0 0
|
|
313
|
+
margin: 0.75rem 0 0;
|
|
263
314
|
font-size: 0.85rem;
|
|
264
315
|
font-variant-numeric: tabular-nums;
|
|
265
316
|
text-align: end;
|
|
266
317
|
color: var(--sl-color-gray-2);
|
|
267
318
|
}
|
|
268
319
|
|
|
320
|
+
.assessment-progress:empty {
|
|
321
|
+
margin: 0;
|
|
322
|
+
}
|
|
323
|
+
|
|
269
324
|
.assessment-list {
|
|
270
325
|
list-style: none;
|
|
271
326
|
margin: 0;
|
|
@@ -275,8 +330,8 @@ body {
|
|
|
275
330
|
}
|
|
276
331
|
|
|
277
332
|
.assessment-item {
|
|
278
|
-
border:
|
|
279
|
-
border-radius:
|
|
333
|
+
border: var(--ex-edge-border);
|
|
334
|
+
border-radius: var(--ex-radius-accent);
|
|
280
335
|
background: var(--sl-color-bg);
|
|
281
336
|
}
|
|
282
337
|
|
|
@@ -413,12 +468,12 @@ body {
|
|
|
413
468
|
|
|
414
469
|
.assessment-feedback.is-correct {
|
|
415
470
|
border-left-color: var(--sl-color-accent);
|
|
416
|
-
background: var(--
|
|
471
|
+
background: var(--ex-surface-tint-neutral);
|
|
417
472
|
}
|
|
418
473
|
|
|
419
474
|
.assessment-feedback.is-incorrect {
|
|
420
475
|
border-left-color: var(--sl-color-gray-3);
|
|
421
|
-
background: var(--
|
|
476
|
+
background: var(--ex-surface-tint-neutral);
|
|
422
477
|
}
|
|
423
478
|
|
|
424
479
|
/* Reader-controlled desktop layout. Collapsed panels remain as narrow edge
|
|
@@ -433,33 +488,247 @@ body {
|
|
|
433
488
|
display: none !important;
|
|
434
489
|
}
|
|
435
490
|
|
|
491
|
+
/* The drag handle that sets a panel's width. It does nothing without the
|
|
492
|
+
script that wires it, so it ships hidden and that script reveals it. */
|
|
493
|
+
.layout-edge-resizer {
|
|
494
|
+
display: none;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
.layout-edge-resizer[hidden] {
|
|
498
|
+
display: none !important;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/* A part's own page is reachable two ways, because the two answer different
|
|
502
|
+
questions. The `Overview` row is part of the chapter list and is there in
|
|
503
|
+
the HTML, so it is keyboard-reachable, crawlable, and obvious to a reader
|
|
504
|
+
who has never used this sidebar before; the control in the part's header is
|
|
505
|
+
the shortcut for one who has. Both point at `/<part>/`. */
|
|
506
|
+
.sidebar-content a.explico-part-overview,
|
|
507
|
+
.layout-navigation-content a.explico-part-overview {
|
|
508
|
+
display: flex;
|
|
509
|
+
align-items: center;
|
|
510
|
+
gap: 0.45rem;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/* Two stacked sheets: the part, rather than one of its chapters. Drawn from a
|
|
514
|
+
border and a shadow so it inherits the link's colour in every state and
|
|
515
|
+
needs no icon font. The sliver between the sheets is the row's background,
|
|
516
|
+
so it has to follow the row when that background changes. */
|
|
517
|
+
a.explico-part-overview {
|
|
518
|
+
--explico-overview-gap: var(--sl-color-bg-sidebar);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
a.explico-part-overview[aria-current='page'] {
|
|
522
|
+
--explico-overview-gap: var(--sl-color-text-accent);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
a.explico-part-overview::before {
|
|
526
|
+
content: '';
|
|
527
|
+
flex: none;
|
|
528
|
+
width: 0.55rem;
|
|
529
|
+
height: 0.68rem;
|
|
530
|
+
border: 1.5px solid currentColor;
|
|
531
|
+
border-radius: 0.12rem;
|
|
532
|
+
box-shadow:
|
|
533
|
+
0.16rem 0.16rem 0 -0.1rem var(--explico-overview-gap),
|
|
534
|
+
0.16rem 0.16rem 0 0 currentColor;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/* The caret leads its part, the way a disclosure triangle leads the thing it
|
|
538
|
+
opens: `>` collapsed, `v` open, in the reading direction before the name it
|
|
539
|
+
applies to. Starlight parks it at the far end of the row instead, where it
|
|
540
|
+
reads as a separate control that happens to share the line. */
|
|
541
|
+
.layout-navigation-content summary {
|
|
542
|
+
justify-content: flex-start;
|
|
543
|
+
gap: 0.25rem;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
.layout-navigation-content summary > .caret {
|
|
547
|
+
order: -1;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
.layout-navigation-content summary > .group-label {
|
|
551
|
+
flex: 1;
|
|
552
|
+
min-width: 0;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/* The part header's own control. The caret having moved to the front, this
|
|
556
|
+
takes the row's end; the label's click still collapses, exactly as before.
|
|
557
|
+
|
|
558
|
+
It is a sibling of `<summary>`, not a child — a link inside a summary is a
|
|
559
|
+
nested interactive control — so it is lifted into the header row from
|
|
560
|
+
outside it, and the label reserves the width it needs. */
|
|
561
|
+
details.layout-part-has-open {
|
|
562
|
+
position: relative;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
details.layout-part-has-open > summary > .group-label {
|
|
566
|
+
padding-inline-end: 1.4rem;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
.layout-part-open {
|
|
570
|
+
position: absolute;
|
|
571
|
+
inset-block-start: 0.3rem;
|
|
572
|
+
inset-inline-end: 0.3rem;
|
|
573
|
+
z-index: 1;
|
|
574
|
+
display: grid;
|
|
575
|
+
place-items: center;
|
|
576
|
+
width: 1.4rem;
|
|
577
|
+
height: 1.4rem;
|
|
578
|
+
border-radius: 0.25rem;
|
|
579
|
+
color: var(--sl-color-gray-3);
|
|
580
|
+
font-size: var(--sl-text-sm);
|
|
581
|
+
line-height: 1;
|
|
582
|
+
text-decoration: none;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
.layout-part-open:hover,
|
|
586
|
+
.layout-part-open:focus-visible {
|
|
587
|
+
color: var(--sl-color-text-accent);
|
|
588
|
+
background: var(--sl-color-accent-low);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
@media print {
|
|
592
|
+
.layout-part-open {
|
|
593
|
+
display: none;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/* Both rails answer a pointer. Starlight changes only the text colour on
|
|
598
|
+
hover, which on a list of 20 chapters is easy to lose track of; a filled row
|
|
599
|
+
says which line the pointer is actually on. */
|
|
600
|
+
.layout-navigation-content a:not(.layout-part-open):hover,
|
|
601
|
+
.layout-navigation-content a:not(.layout-part-open):focus-visible,
|
|
602
|
+
.layout-page-sidebar-content a:hover,
|
|
603
|
+
.layout-page-sidebar-content a:focus-visible {
|
|
604
|
+
color: var(--sl-color-white);
|
|
605
|
+
background: var(--sl-color-gray-6);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/* The part header answers a pointer like the rows under it — it is a control,
|
|
609
|
+
and it was the one row in the panel that looked inert. */
|
|
610
|
+
.layout-navigation-content summary {
|
|
611
|
+
border-radius: 0.25rem;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/* …and it says, quietly and all the time, which part the open page belongs
|
|
615
|
+
to. Three weights, so the states never read as the same thing: the current
|
|
616
|
+
chapter is a solid accent row, the part holding it is tinted, a hovered row
|
|
617
|
+
is a neutral fill that goes away again. `:has()` keeps this in CSS, which
|
|
618
|
+
means it is right in the first painted frame. */
|
|
619
|
+
.layout-navigation-content details:has(a[aria-current='page']) > summary {
|
|
620
|
+
background: var(--sl-color-accent-low);
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
.layout-navigation-content summary:hover,
|
|
624
|
+
.layout-navigation-content summary:focus-visible {
|
|
625
|
+
background: var(--sl-color-gray-6);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
.layout-page-sidebar-content a:hover,
|
|
629
|
+
.layout-page-sidebar-content a:focus-visible {
|
|
630
|
+
color: var(--sl-color-text-accent);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/* How far the reader has come, drawn as the rail itself: the segment beside
|
|
634
|
+
every chapter already read is accent, the rest is the hairline it always
|
|
635
|
+
was, so the boundary between them is the reader's position in the course.
|
|
636
|
+
`data-covered` is set by the panel's own script; without it the rail is
|
|
637
|
+
simply the hairline throughout. */
|
|
638
|
+
.layout-navigation-content ul ul li {
|
|
639
|
+
border-inline-start-color: var(--sl-color-hairline-light);
|
|
640
|
+
transition: border-color 120ms ease;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
.layout-navigation-content ul ul li[data-covered] {
|
|
644
|
+
border-inline-start-color: var(--sl-color-text-accent);
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/* The contents rail has no such line of its own; covered headings give it
|
|
648
|
+
one, so a long page shows how much of itself is behind the reader. */
|
|
649
|
+
.layout-page-sidebar-content nav ul li {
|
|
650
|
+
border-inline-start: 2px solid transparent;
|
|
651
|
+
padding-inline-start: 0.35rem;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
.layout-page-sidebar-content nav ul li[data-covered] {
|
|
655
|
+
border-inline-start-color: var(--sl-color-text-accent);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
.layout-page-sidebar-content nav ul li[data-current] {
|
|
659
|
+
border-inline-start-color: var(--sl-color-text-accent);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
@media (prefers-reduced-motion: reduce) {
|
|
663
|
+
.layout-navigation-content ul ul li {
|
|
664
|
+
transition: none;
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
|
|
436
668
|
@media (min-width: 50rem) {
|
|
437
669
|
:root {
|
|
438
670
|
--layout-edge-rail-width: 2.5rem;
|
|
439
|
-
|
|
671
|
+
/* The collapse control is a rectangle docked into the corner the header
|
|
672
|
+
and the panel's separator line make, not a round button floating near
|
|
673
|
+
it. One gap sets both of those edges; the radius rounds only the
|
|
674
|
+
corner that is free of them. */
|
|
675
|
+
--layout-edge-toggle-width: 1.875rem;
|
|
676
|
+
--layout-edge-toggle-height: 1.125rem;
|
|
677
|
+
--layout-edge-toggle-gap: 2px;
|
|
678
|
+
--layout-edge-toggle-radius: 0.4375rem;
|
|
679
|
+
/* What a panel keeps clear at its top so the control never lands on the
|
|
680
|
+
first chapter's own expand caret, which sits at the same edge. */
|
|
681
|
+
--layout-edge-toggle-reserve: calc(
|
|
682
|
+
var(--layout-edge-toggle-height) + var(--layout-edge-toggle-gap) * 2
|
|
683
|
+
);
|
|
684
|
+
/* The navigation panel's width as it currently stands: the reader's own
|
|
685
|
+
if they resized it, the edge rail's while it is collapsed. The control
|
|
686
|
+
and the drag handle both dock against whichever is in force, so
|
|
687
|
+
neither needs a second rule for the collapsed state. */
|
|
688
|
+
--layout-navigation-width: var(--sl-sidebar-width);
|
|
689
|
+
/* How long the pointer rests on a collapsed rail before it peeks open.
|
|
690
|
+
Long enough that crossing the rail on the way somewhere else never
|
|
691
|
+
opens anything, short enough that meaning to look never feels like
|
|
692
|
+
waiting. `LayoutHeader.astro` reads this and arms the peek; the CSS
|
|
693
|
+
below stays keyed off `:hover`, with the armed attribute as its
|
|
694
|
+
gate. */
|
|
695
|
+
--layout-peek-delay: 40ms;
|
|
440
696
|
}
|
|
441
697
|
|
|
442
698
|
.layout-edge-toggle:not([hidden]) {
|
|
443
699
|
display: grid;
|
|
444
700
|
place-items: center;
|
|
445
|
-
width: var(--layout-edge-toggle-
|
|
446
|
-
height: var(--layout-edge-toggle-
|
|
701
|
+
width: var(--layout-edge-toggle-width);
|
|
702
|
+
height: var(--layout-edge-toggle-height);
|
|
447
703
|
border: 1px solid var(--sl-color-gray-5);
|
|
448
|
-
border-radius: 999px;
|
|
449
704
|
padding: 0;
|
|
450
705
|
color: var(--sl-color-text-accent);
|
|
451
706
|
background: var(--sl-color-bg-nav);
|
|
452
707
|
box-shadow: var(--sl-shadow-sm);
|
|
453
|
-
font:
|
|
708
|
+
font-family: var(--sl-font-system-mono);
|
|
709
|
+
font-size: 0.68rem;
|
|
710
|
+
font-weight: 600;
|
|
454
711
|
line-height: 1;
|
|
712
|
+
letter-spacing: -0.09em;
|
|
455
713
|
cursor: pointer;
|
|
456
714
|
}
|
|
457
715
|
|
|
458
|
-
.layout-edge-
|
|
716
|
+
.layout-edge-glyph {
|
|
459
717
|
display: block;
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
718
|
+
/* A box the width of the resting control, minus its border. Centred here
|
|
719
|
+
rather than by the button's own `place-items`, so that when the control
|
|
720
|
+
grows during a peek (below) the glyph's box can be pinned to the end
|
|
721
|
+
the pointer is on and the glyph itself does not move at all. */
|
|
722
|
+
width: calc(var(--layout-edge-toggle-width) - 2px);
|
|
723
|
+
/* The tracking above also trims the run's trailing side bearing; put that
|
|
724
|
+
much back so the three glyphs sit centred in that box. */
|
|
725
|
+
padding-inline-start: 0.09em;
|
|
726
|
+
text-align: center;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
/* The glyphs point the way the panel travels, which mirrors with the page. */
|
|
730
|
+
[dir='rtl'] .layout-edge-glyph {
|
|
731
|
+
transform: scaleX(-1);
|
|
463
732
|
}
|
|
464
733
|
|
|
465
734
|
.layout-edge-toggle:hover {
|
|
@@ -472,17 +741,23 @@ body {
|
|
|
472
741
|
outline-offset: 2px;
|
|
473
742
|
}
|
|
474
743
|
|
|
475
|
-
.layout-edge-toggle .layout-edge-
|
|
476
|
-
.layout-edge-toggle[aria-expanded='false'] .layout-edge-
|
|
744
|
+
.layout-edge-toggle .layout-edge-glyph-restore,
|
|
745
|
+
.layout-edge-toggle[aria-expanded='false'] .layout-edge-glyph-hide {
|
|
477
746
|
display: none;
|
|
478
747
|
}
|
|
479
748
|
|
|
480
|
-
.layout-edge-toggle[aria-expanded='false'] .layout-edge-
|
|
749
|
+
.layout-edge-toggle[aria-expanded='false'] .layout-edge-glyph-restore {
|
|
481
750
|
display: block;
|
|
482
751
|
}
|
|
483
752
|
|
|
484
753
|
.layout-navigation-panel {
|
|
485
754
|
min-height: auto;
|
|
755
|
+
/* Starlight's own `.sidebar-content` already pads 1rem above this panel,
|
|
756
|
+
so reserve only the rest of what the docked control covers. */
|
|
757
|
+
padding-block-start: max(
|
|
758
|
+
0px,
|
|
759
|
+
calc(var(--layout-edge-toggle-reserve) - 1rem)
|
|
760
|
+
);
|
|
486
761
|
}
|
|
487
762
|
|
|
488
763
|
/* A compact chapter remains useful as a row of lesson icons. The
|
|
@@ -602,6 +877,29 @@ body {
|
|
|
602
877
|
transform: translateY(-50%) translateX(0);
|
|
603
878
|
}
|
|
604
879
|
|
|
880
|
+
/* The panel that holds this tooltip is a scroll container
|
|
881
|
+
(`.sidebar-pane` is `overflow-y: auto`, which forces `overflow-x` to
|
|
882
|
+
match), so an absolutely positioned child cannot leave it: a lesson
|
|
883
|
+
title longer than the panel is wide simply ended at the panel's edge.
|
|
884
|
+
While one is showing, `LayoutSidebar.astro` marks its link and writes the
|
|
885
|
+
anchor's own viewport coordinates here — `position: fixed` takes the
|
|
886
|
+
tooltip out of that scroll container entirely, and the explicit physical
|
|
887
|
+
insets replace the `inset-inline-start: calc(100% + …)` above, which
|
|
888
|
+
means something different once the containing block is the viewport. */
|
|
889
|
+
.layout-compact-sidebar
|
|
890
|
+
details[data-compact]
|
|
891
|
+
> ul:not(.top-level)
|
|
892
|
+
> li
|
|
893
|
+
> a[data-tooltip-open]
|
|
894
|
+
> span {
|
|
895
|
+
position: fixed;
|
|
896
|
+
z-index: calc(var(--sl-z-index-menu) + 2);
|
|
897
|
+
inset-inline: auto;
|
|
898
|
+
top: var(--layout-tooltip-y, 50%);
|
|
899
|
+
left: var(--layout-tooltip-x, 0px);
|
|
900
|
+
max-width: min(22rem, 45vw);
|
|
901
|
+
}
|
|
902
|
+
|
|
605
903
|
.layout-compact-sidebar details[data-compact] > summary .caret {
|
|
606
904
|
transform: rotateZ(0);
|
|
607
905
|
}
|
|
@@ -614,17 +912,164 @@ body {
|
|
|
614
912
|
transform: rotateZ(180deg);
|
|
615
913
|
}
|
|
616
914
|
|
|
915
|
+
/* Compact mode turns every chapter into the same outlined page, so the
|
|
916
|
+
overview row would be indistinguishable from chapter one. Fill its sheets
|
|
917
|
+
and give it the accent: the part itself, not a page in it. */
|
|
918
|
+
.layout-compact-sidebar
|
|
919
|
+
details[data-compact]
|
|
920
|
+
> ul:not(.top-level)
|
|
921
|
+
> li
|
|
922
|
+
> a.explico-part-overview {
|
|
923
|
+
color: var(--sl-color-text-accent);
|
|
924
|
+
border-color: var(--sl-color-text-accent);
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
.layout-compact-sidebar
|
|
928
|
+
details[data-compact]
|
|
929
|
+
> ul:not(.top-level)
|
|
930
|
+
> li
|
|
931
|
+
> a.explico-part-overview::before {
|
|
932
|
+
background: currentColor;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
/* On the part's own page the tile is already accent-filled, so filled
|
|
936
|
+
accent sheets on top of it are one green shape. Invert the glyph and
|
|
937
|
+
hollow it out: an outline reads at 28px where a fill does not, and it is
|
|
938
|
+
the same reversal Starlight gives a current chapter's text. */
|
|
939
|
+
.layout-compact-sidebar
|
|
940
|
+
details[data-compact]
|
|
941
|
+
> ul:not(.top-level)
|
|
942
|
+
> li
|
|
943
|
+
> a.explico-part-overview[aria-current='page'] {
|
|
944
|
+
color: var(--sl-color-text-invert);
|
|
945
|
+
border-color: var(--sl-color-text-accent);
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
.layout-compact-sidebar
|
|
949
|
+
details[data-compact]
|
|
950
|
+
> ul:not(.top-level)
|
|
951
|
+
> li
|
|
952
|
+
> a.explico-part-overview[aria-current='page']::before {
|
|
953
|
+
background: transparent;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
/* Compact mode has no rail to colour, so a covered chapter's tile carries
|
|
957
|
+
the progress instead of the line beside it. */
|
|
958
|
+
.layout-compact-sidebar
|
|
959
|
+
details[data-compact]
|
|
960
|
+
> ul:not(.top-level)
|
|
961
|
+
> li[data-covered]
|
|
962
|
+
> a:not([aria-current='page']) {
|
|
963
|
+
border-color: var(--sl-color-accent-low);
|
|
964
|
+
background: var(--sl-color-accent-low);
|
|
965
|
+
}
|
|
966
|
+
|
|
617
967
|
.layout-navigation-toggle {
|
|
618
968
|
position: fixed;
|
|
619
969
|
z-index: calc(var(--sl-z-index-menu) + 1);
|
|
620
|
-
|
|
970
|
+
/* Both panels' controls take this same block start, so the pair reads as
|
|
971
|
+
one row under the header instead of two separately placed buttons. */
|
|
972
|
+
inset-block-start: calc(
|
|
973
|
+
var(--sl-nav-height) + var(--layout-edge-toggle-gap)
|
|
974
|
+
);
|
|
975
|
+
/* The 1px is the panel's own separator border: the gap is measured from
|
|
976
|
+
the line the reader sees, not from the border box behind it. */
|
|
621
977
|
inset-inline-start: calc(
|
|
622
|
-
var(--
|
|
978
|
+
var(--layout-navigation-width) - var(--layout-edge-toggle-width) -
|
|
979
|
+
var(--layout-edge-toggle-gap) - 1px
|
|
623
980
|
);
|
|
981
|
+
border-radius: 0 0 0 var(--layout-edge-toggle-radius);
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
[dir='rtl'] .layout-navigation-toggle {
|
|
985
|
+
border-radius: 0 0 var(--layout-edge-toggle-radius) 0;
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
/* The handle that sets the panel's width straddles that same separator. */
|
|
989
|
+
/* The handle covers the separator line and reaches outward from it, into
|
|
990
|
+
the article. It deliberately does not reach inward: the navigation panel
|
|
991
|
+
scrolls, and its scrollbar sits exactly there — a handle straddling the
|
|
992
|
+
line evenly would take the outer few pixels of that scrollbar with it. */
|
|
993
|
+
.layout-navigation-resizer {
|
|
994
|
+
position: fixed;
|
|
995
|
+
z-index: calc(var(--sl-z-index-menu) + 1);
|
|
996
|
+
inset-block: var(--sl-nav-height) 0;
|
|
997
|
+
inset-inline-start: calc(var(--layout-navigation-width) - 1px);
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
.layout-edge-resizer:not([hidden]) {
|
|
1001
|
+
display: block;
|
|
1002
|
+
width: 0.375rem;
|
|
1003
|
+
border: 0;
|
|
1004
|
+
padding: 0;
|
|
1005
|
+
background: transparent;
|
|
1006
|
+
cursor: col-resize;
|
|
1007
|
+
touch-action: none;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
.layout-edge-resizer::after {
|
|
1011
|
+
content: '';
|
|
1012
|
+
display: block;
|
|
1013
|
+
position: absolute;
|
|
1014
|
+
inset-block: 0;
|
|
1015
|
+
width: 1px;
|
|
1016
|
+
background: transparent;
|
|
1017
|
+
transition: background 120ms ease;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
/* Land the lit line on the separator itself, at whichever end of the
|
|
1021
|
+
handle that panel's separator falls. */
|
|
1022
|
+
.layout-navigation-resizer::after {
|
|
1023
|
+
inset-inline-start: 0;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
.layout-contents-resizer::after {
|
|
1027
|
+
inset-inline-end: 0;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
.layout-edge-resizer:is(:hover, [data-resizing])::after {
|
|
1031
|
+
background: var(--sl-color-accent);
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
.layout-edge-resizer:focus-visible {
|
|
1035
|
+
outline: 3px solid var(--sl-color-accent-high);
|
|
1036
|
+
outline-offset: -3px;
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
/* A collapsed panel has no width for the reader to set; its control does
|
|
1040
|
+
that job instead. */
|
|
1041
|
+
html[data-navigation-hidden] .layout-navigation-resizer,
|
|
1042
|
+
html[data-page-sidebar-hidden] .layout-contents-resizer {
|
|
1043
|
+
display: none;
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
/* A panel the reader narrowed past its own labels scrolls sideways rather
|
|
1047
|
+
than wrapping every chapter title into a column of single words. */
|
|
1048
|
+
html[data-navigation-resized] .layout-navigation-content :is(a, summary) {
|
|
1049
|
+
white-space: nowrap;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
html[data-navigation-resized] .sidebar-pane {
|
|
1053
|
+
overflow-x: auto;
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
/* A compact chapter's tooltip is a child of one of those links, and it is
|
|
1057
|
+
the one label that must still wrap — it is sized by its own max-width,
|
|
1058
|
+
not by the panel, so inheriting `nowrap` would run its text straight out
|
|
1059
|
+
of its own background. */
|
|
1060
|
+
html[data-navigation-resized]
|
|
1061
|
+
.layout-compact-sidebar
|
|
1062
|
+
details[data-compact]
|
|
1063
|
+
> ul:not(.top-level)
|
|
1064
|
+
> li
|
|
1065
|
+
> a
|
|
1066
|
+
> span {
|
|
1067
|
+
white-space: normal;
|
|
624
1068
|
}
|
|
625
1069
|
|
|
626
1070
|
html[data-navigation-hidden] {
|
|
627
1071
|
--sl-content-inline-start: var(--layout-edge-rail-width);
|
|
1072
|
+
--layout-navigation-width: var(--layout-edge-rail-width);
|
|
628
1073
|
}
|
|
629
1074
|
|
|
630
1075
|
html[data-navigation-hidden] .sidebar-pane {
|
|
@@ -633,12 +1078,6 @@ body {
|
|
|
633
1078
|
transition: width 140ms ease;
|
|
634
1079
|
}
|
|
635
1080
|
|
|
636
|
-
html[data-navigation-hidden] .layout-navigation-toggle {
|
|
637
|
-
inset-inline-start: calc(
|
|
638
|
-
(var(--layout-edge-rail-width) - var(--layout-edge-toggle-size)) / 2
|
|
639
|
-
);
|
|
640
|
-
}
|
|
641
|
-
|
|
642
1081
|
html[data-navigation-hidden] .layout-navigation-content {
|
|
643
1082
|
visibility: hidden;
|
|
644
1083
|
opacity: 0;
|
|
@@ -646,7 +1085,9 @@ body {
|
|
|
646
1085
|
transition: opacity 100ms ease;
|
|
647
1086
|
}
|
|
648
1087
|
|
|
649
|
-
html[data-navigation-hidden]
|
|
1088
|
+
html[data-navigation-hidden][data-navigation-peek-armed]:not(
|
|
1089
|
+
[data-navigation-peek-suppressed]
|
|
1090
|
+
)
|
|
650
1091
|
.sidebar-pane:hover {
|
|
651
1092
|
width: var(--sl-sidebar-width);
|
|
652
1093
|
overflow-y: auto;
|
|
@@ -654,13 +1095,37 @@ body {
|
|
|
654
1095
|
box-shadow: var(--sl-shadow-lg);
|
|
655
1096
|
}
|
|
656
1097
|
|
|
657
|
-
html[data-navigation-hidden]
|
|
1098
|
+
html[data-navigation-hidden][data-navigation-peek-armed]:not(
|
|
1099
|
+
[data-navigation-peek-suppressed]
|
|
1100
|
+
)
|
|
658
1101
|
.sidebar-pane:hover
|
|
659
1102
|
.layout-navigation-content {
|
|
660
1103
|
visibility: visible;
|
|
661
1104
|
opacity: 1;
|
|
662
1105
|
pointer-events: auto;
|
|
663
1106
|
}
|
|
1107
|
+
|
|
1108
|
+
/* While the panel peeks open over the article, the control reaches across
|
|
1109
|
+
to the separator the open panel would put there — it does not travel to
|
|
1110
|
+
it. A reader aiming at the control is hovering the rail, which is what
|
|
1111
|
+
triggers the peek in the first place; moving the control at that moment
|
|
1112
|
+
takes it out from under the pointer that was coming for it, and the
|
|
1113
|
+
reader has to chase it across the panel. Growing instead keeps its outer
|
|
1114
|
+
edge, and the glyph inside it, exactly where the pointer found them,
|
|
1115
|
+
while its inner end still shows where the control will settle. The width
|
|
1116
|
+
is a length, like the panel's own, so the two animate in step. */
|
|
1117
|
+
html[data-navigation-hidden][data-navigation-peek-armed]:not(
|
|
1118
|
+
[data-navigation-peek-suppressed]
|
|
1119
|
+
)
|
|
1120
|
+
.sidebar-pane:hover
|
|
1121
|
+
.layout-navigation-toggle {
|
|
1122
|
+
place-items: center start;
|
|
1123
|
+
width: calc(
|
|
1124
|
+
var(--sl-sidebar-width) - var(--layout-edge-rail-width) +
|
|
1125
|
+
var(--layout-edge-toggle-width)
|
|
1126
|
+
);
|
|
1127
|
+
transition: width 140ms ease;
|
|
1128
|
+
}
|
|
664
1129
|
}
|
|
665
1130
|
|
|
666
1131
|
@media (min-width: 72rem) {
|
|
@@ -746,14 +1211,53 @@ body {
|
|
|
746
1211
|
.layout-page-sidebar {
|
|
747
1212
|
position: relative;
|
|
748
1213
|
min-height: 100%;
|
|
749
|
-
padding-block-start:
|
|
1214
|
+
padding-block-start: var(--layout-edge-toggle-reserve);
|
|
750
1215
|
}
|
|
751
1216
|
|
|
1217
|
+
/* `.right-sidebar` is `position: fixed` with `padding-top:
|
|
1218
|
+
var(--sl-nav-height)`, so this panel's own top edge is already the
|
|
1219
|
+
underside of the header: the same gap here puts this control at exactly
|
|
1220
|
+
the block start the navigation's fixed control computes. */
|
|
752
1221
|
.layout-contents-toggle {
|
|
753
1222
|
position: absolute;
|
|
754
1223
|
z-index: 1;
|
|
755
|
-
inset-block-start:
|
|
756
|
-
inset-inline-start:
|
|
1224
|
+
inset-block-start: var(--layout-edge-toggle-gap);
|
|
1225
|
+
inset-inline-start: var(--layout-edge-toggle-gap);
|
|
1226
|
+
border-radius: 0 0 var(--layout-edge-toggle-radius) 0;
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
[dir='rtl'] .layout-contents-toggle {
|
|
1230
|
+
border-radius: 0 0 0 var(--layout-edge-toggle-radius);
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
.layout-contents-resizer {
|
|
1234
|
+
position: fixed;
|
|
1235
|
+
z-index: calc(var(--sl-z-index-toc) + 1);
|
|
1236
|
+
inset-block: var(--sl-nav-height) 0;
|
|
1237
|
+
inset-inline-end: calc(
|
|
1238
|
+
var(--layout-contents-width, var(--toc-actual-width, 0px)) - 1px
|
|
1239
|
+
);
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
/* A width the reader set replaces the shrink-to-fit rail above. The
|
|
1243
|
+
`:not()` keeps this out of the collapsed state's way, which owns the
|
|
1244
|
+
same declaration at the same specificity. */
|
|
1245
|
+
html[data-contents-resized]:not([data-page-sidebar-hidden])
|
|
1246
|
+
.right-sidebar-container,
|
|
1247
|
+
html[data-contents-resized]:not([data-page-sidebar-hidden]) .right-sidebar {
|
|
1248
|
+
width: var(--layout-contents-width);
|
|
1249
|
+
max-width: none;
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
/* Starlight hides this panel's scrollbar (`scrollbar-width: none`), which
|
|
1253
|
+
would quietly cut a heading the reader narrowed the panel past. */
|
|
1254
|
+
html[data-contents-resized]:not([data-page-sidebar-hidden]) .right-sidebar {
|
|
1255
|
+
overflow-x: auto;
|
|
1256
|
+
scrollbar-width: thin;
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
html[data-contents-resized] .layout-page-sidebar-content :is(a, h2) {
|
|
1260
|
+
white-space: nowrap;
|
|
757
1261
|
}
|
|
758
1262
|
|
|
759
1263
|
html[data-page-sidebar-hidden] {
|
|
@@ -764,15 +1268,6 @@ body {
|
|
|
764
1268
|
width: var(--layout-edge-rail-width);
|
|
765
1269
|
}
|
|
766
1270
|
|
|
767
|
-
html[data-page-sidebar-hidden] .layout-contents-toggle {
|
|
768
|
-
position: fixed;
|
|
769
|
-
inset-block-start: calc(var(--sl-nav-height) + 0.5rem);
|
|
770
|
-
inset-inline-start: auto;
|
|
771
|
-
inset-inline-end: calc(
|
|
772
|
-
(var(--layout-edge-rail-width) - var(--layout-edge-toggle-size)) / 2
|
|
773
|
-
);
|
|
774
|
-
}
|
|
775
|
-
|
|
776
1271
|
html[data-page-sidebar-hidden] .right-sidebar {
|
|
777
1272
|
z-index: var(--sl-z-index-toc);
|
|
778
1273
|
inset-inline-start: auto;
|
|
@@ -794,7 +1289,9 @@ body {
|
|
|
794
1289
|
transition: opacity 100ms ease;
|
|
795
1290
|
}
|
|
796
1291
|
|
|
797
|
-
html[data-page-sidebar-hidden]
|
|
1292
|
+
html[data-page-sidebar-hidden][data-page-sidebar-peek-armed]:not(
|
|
1293
|
+
[data-page-sidebar-peek-suppressed]
|
|
1294
|
+
)
|
|
798
1295
|
.right-sidebar:hover {
|
|
799
1296
|
width: max-content;
|
|
800
1297
|
max-width: 80ch;
|
|
@@ -802,13 +1299,32 @@ body {
|
|
|
802
1299
|
box-shadow: var(--sl-shadow-lg);
|
|
803
1300
|
}
|
|
804
1301
|
|
|
805
|
-
html[data-page-sidebar-hidden]
|
|
1302
|
+
html[data-page-sidebar-hidden][data-page-sidebar-peek-armed]:not(
|
|
1303
|
+
[data-page-sidebar-peek-suppressed]
|
|
1304
|
+
)
|
|
806
1305
|
.right-sidebar:hover
|
|
807
1306
|
.layout-page-sidebar-content {
|
|
808
1307
|
visibility: visible;
|
|
809
1308
|
opacity: 1;
|
|
810
1309
|
pointer-events: auto;
|
|
811
1310
|
}
|
|
1311
|
+
|
|
1312
|
+
/* The same growth, mirrored. This control is positioned inside its panel,
|
|
1313
|
+
so a peek drags it inward with the panel's own edge unless its outer edge
|
|
1314
|
+
is pinned to where the rail put it; with both insets set, the box grows
|
|
1315
|
+
to meet the separator on its own. */
|
|
1316
|
+
html[data-page-sidebar-hidden][data-page-sidebar-peek-armed]:not(
|
|
1317
|
+
[data-page-sidebar-peek-suppressed]
|
|
1318
|
+
)
|
|
1319
|
+
.right-sidebar:hover
|
|
1320
|
+
.layout-contents-toggle {
|
|
1321
|
+
place-items: center end;
|
|
1322
|
+
inset-inline-end: calc(
|
|
1323
|
+
var(--layout-edge-rail-width) - var(--layout-edge-toggle-width) -
|
|
1324
|
+
var(--layout-edge-toggle-gap) - 1px
|
|
1325
|
+
);
|
|
1326
|
+
width: auto;
|
|
1327
|
+
}
|
|
812
1328
|
}
|
|
813
1329
|
|
|
814
1330
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -820,6 +1336,162 @@ body {
|
|
|
820
1336
|
}
|
|
821
1337
|
}
|
|
822
1338
|
|
|
1339
|
+
/* The side column's room (rule S3 of docs/plans/hover-card-consistency.md):
|
|
1340
|
+
while explanation cards sit to the right of the article, the article
|
|
1341
|
+
slides left through its own start margin, which `card-side.ts` computes
|
|
1342
|
+
and hands over as `--explico-article-start`. `.main-pane` keeps its width
|
|
1343
|
+
and the rail stays where it is. `:root` outranks the `html[…] .main-pane`
|
|
1344
|
+
rules above that centre the article; `screen` keeps the slide off paper.
|
|
1345
|
+
The slide's animation is a transform the card manager runs, so this
|
|
1346
|
+
margin is always the final one. */
|
|
1347
|
+
@media screen and (min-width: 72rem) {
|
|
1348
|
+
:root[data-article-slid] .main-pane {
|
|
1349
|
+
--sl-content-margin-inline: var(--explico-article-start, 0px) auto;
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
/* Both side panels sit above the explanation cards, whose layer takes the
|
|
1354
|
+
header's level just before `.page` (`card-placement.ts`): an open panel is
|
|
1355
|
+
never covered — a reader who needs its room collapses it — and a collapsed
|
|
1356
|
+
one peeks open over the cards. Each panel's controls live inside it, so
|
|
1357
|
+
they rise with it. The header outranks both: the rail's box starts at the
|
|
1358
|
+
window's top, under the header. An expanded table or diagram covers the
|
|
1359
|
+
panels, and the cards opened from inside it must cover it, so while one is
|
|
1360
|
+
open the panels drop back to Starlight's own levels. */
|
|
1361
|
+
.header {
|
|
1362
|
+
z-index: calc(var(--sl-z-index-navbar) + 1);
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
/* A slimmer site header: 3rem at every width, where Starlight's is 3.5rem
|
|
1366
|
+
and 4rem from 50rem up. The title, the logo (sized from the height and
|
|
1367
|
+
padding) and the search box scale with it, so more of the window goes to
|
|
1368
|
+
the lesson, and to the cards and side column under the header.
|
|
1369
|
+
Everything that sits under the header reads `--sl-nav-height`. */
|
|
1370
|
+
:root {
|
|
1371
|
+
--sl-nav-height: 3rem;
|
|
1372
|
+
--sl-nav-pad-y: 0.5rem;
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
.site-title {
|
|
1376
|
+
font-size: var(--sl-text-xl);
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
@media (min-width: 50rem) {
|
|
1380
|
+
button[data-open-modal] {
|
|
1381
|
+
height: 2rem;
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
@media (min-width: 50rem) {
|
|
1386
|
+
:root .sidebar-pane {
|
|
1387
|
+
z-index: var(--sl-z-index-navbar);
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
@media (min-width: 72rem) {
|
|
1392
|
+
:root .right-sidebar,
|
|
1393
|
+
:root[data-page-sidebar-hidden] .right-sidebar {
|
|
1394
|
+
z-index: var(--sl-z-index-navbar);
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
:root:has(.table-overflow-expanded, .diagram-is-expanded) .sidebar-pane {
|
|
1399
|
+
z-index: var(--sl-z-index-menu);
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
:root:has(.table-overflow-expanded, .diagram-is-expanded) .right-sidebar {
|
|
1403
|
+
z-index: var(--sl-z-index-toc);
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
/* S9: "Keep the article left", fixed at the top of the side column just
|
|
1407
|
+
under the header, over the cards scrolling past it. `card-side.ts` sets
|
|
1408
|
+
its `left`. */
|
|
1409
|
+
.explico-keep-left {
|
|
1410
|
+
position: fixed;
|
|
1411
|
+
z-index: var(--sl-z-index-navbar);
|
|
1412
|
+
top: calc(var(--sl-nav-height) + 0.5rem);
|
|
1413
|
+
display: inline-flex;
|
|
1414
|
+
align-items: center;
|
|
1415
|
+
gap: 0.45rem;
|
|
1416
|
+
margin: 0;
|
|
1417
|
+
padding: 0.2rem 0.65rem 0.2rem 0.4rem;
|
|
1418
|
+
border: var(--ex-edge-border);
|
|
1419
|
+
border-radius: 999px;
|
|
1420
|
+
font: inherit;
|
|
1421
|
+
font-size: var(--sl-text-xs);
|
|
1422
|
+
line-height: 1.4;
|
|
1423
|
+
color: var(--sl-color-gray-2);
|
|
1424
|
+
background: var(--sl-color-bg);
|
|
1425
|
+
box-shadow: var(--sl-shadow-sm);
|
|
1426
|
+
cursor: pointer;
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
.explico-keep-left[hidden] {
|
|
1430
|
+
display: none;
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
.explico-keep-left:hover {
|
|
1434
|
+
color: var(--sl-color-text);
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
.explico-keep-left:focus-visible {
|
|
1438
|
+
outline: 3px solid var(--sl-color-accent);
|
|
1439
|
+
outline-offset: 2px;
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
.explico-keep-left-switch {
|
|
1443
|
+
position: relative;
|
|
1444
|
+
flex: none;
|
|
1445
|
+
width: 1.75em;
|
|
1446
|
+
height: 1em;
|
|
1447
|
+
border-radius: 999px;
|
|
1448
|
+
background: var(--sl-color-gray-4);
|
|
1449
|
+
transition: background-color 100ms ease;
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
.explico-keep-left-switch::after {
|
|
1453
|
+
content: '';
|
|
1454
|
+
position: absolute;
|
|
1455
|
+
top: 0.125em;
|
|
1456
|
+
left: 0.125em;
|
|
1457
|
+
width: 0.75em;
|
|
1458
|
+
height: 0.75em;
|
|
1459
|
+
border-radius: 50%;
|
|
1460
|
+
background: var(--sl-color-bg);
|
|
1461
|
+
transition: transform 100ms ease;
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
.explico-keep-left[aria-pressed='true'] .explico-keep-left-switch {
|
|
1465
|
+
background: var(--sl-color-accent);
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
.explico-keep-left[aria-pressed='true'] .explico-keep-left-switch::after {
|
|
1469
|
+
transform: translateX(0.75em);
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1473
|
+
.explico-keep-left-switch,
|
|
1474
|
+
.explico-keep-left-switch::after {
|
|
1475
|
+
transition: none;
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
@media (forced-colors: active) {
|
|
1480
|
+
.explico-keep-left-switch {
|
|
1481
|
+
border: 1px solid ButtonText;
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
.explico-keep-left[aria-pressed='true'] .explico-keep-left-switch {
|
|
1485
|
+
background: Highlight;
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
@media print {
|
|
1490
|
+
.explico-keep-left {
|
|
1491
|
+
display: none !important;
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
|
|
823
1495
|
/* Source citations: inline `[n]` markers and the end-of-page reference list
|
|
824
1496
|
emitted by the remark-citation adapter. The hover/pin panel is styled in
|
|
825
1497
|
the CitationLayer island. */
|
|
@@ -1270,61 +1942,217 @@ body {
|
|
|
1270
1942
|
}
|
|
1271
1943
|
}
|
|
1272
1944
|
|
|
1273
|
-
.sl-markdown-content .keyed-equation:target {
|
|
1274
|
-
animation: eq-flash 5s ease-out both;
|
|
1945
|
+
.sl-markdown-content .keyed-equation:target {
|
|
1946
|
+
animation: eq-flash 5s ease-out both;
|
|
1947
|
+
}
|
|
1948
|
+
|
|
1949
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1950
|
+
.sl-markdown-content .keyed-equation:target {
|
|
1951
|
+
animation: none;
|
|
1952
|
+
background: var(--sl-color-accent-low);
|
|
1953
|
+
outline: 2px solid var(--sl-color-accent);
|
|
1954
|
+
outline-offset: 0.2rem;
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1958
|
+
@media (forced-colors: active) {
|
|
1959
|
+
.sl-markdown-content .keyed-equation:target {
|
|
1960
|
+
animation: none;
|
|
1961
|
+
outline: 2px solid Highlight;
|
|
1962
|
+
outline-offset: 0.2rem;
|
|
1963
|
+
}
|
|
1964
|
+
.sl-markdown-content a.equation-ref:hover,
|
|
1965
|
+
.sl-markdown-content a.equation-ref:focus-visible {
|
|
1966
|
+
outline: 2px solid Highlight;
|
|
1967
|
+
}
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
@media print {
|
|
1971
|
+
.sl-markdown-content .keyed-equation__controls {
|
|
1972
|
+
position: static;
|
|
1973
|
+
display: block;
|
|
1974
|
+
transform: none;
|
|
1975
|
+
text-align: end;
|
|
1976
|
+
}
|
|
1977
|
+
.sl-markdown-content a.keyed-equation__number {
|
|
1978
|
+
color: inherit;
|
|
1979
|
+
opacity: 1;
|
|
1980
|
+
}
|
|
1981
|
+
/* A clipboard button means nothing on paper. */
|
|
1982
|
+
.sl-markdown-content .keyed-equation__copy {
|
|
1983
|
+
display: none;
|
|
1984
|
+
}
|
|
1985
|
+
.sl-markdown-content .keyed-equation {
|
|
1986
|
+
padding-inline-end: 0;
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
/* One caption line for every float (docs/plans/titles-and-containers.md
|
|
1991
|
+
Part 3): `Figure 2.2.1 [chain] ‹caption›` — the number links to the float,
|
|
1992
|
+
the chain icon copies that link (`HeadingAnchorEnhancer.astro`), the
|
|
1993
|
+
caption is the float's one long caption. A figure and a diagram put it
|
|
1994
|
+
below the picture (`FloatCaption.astro`), a table above it, the LaTeX
|
|
1995
|
+
convention. The line never hides (docs/plans/figures-and-short-captions.md,
|
|
1996
|
+
decision 1); its buttons sit at its end (`.float-tools`, below). */
|
|
1997
|
+
.sl-markdown-content .float-caption {
|
|
1998
|
+
/* Anchors the button row (`.float-tools`) to the line's end. */
|
|
1999
|
+
position: relative;
|
|
2000
|
+
margin-block: 0.5rem 0;
|
|
2001
|
+
font-size: var(--sl-text-sm);
|
|
2002
|
+
line-height: 1.5;
|
|
2003
|
+
color: var(--sl-color-gray-3);
|
|
2004
|
+
break-before: avoid-page;
|
|
2005
|
+
}
|
|
2006
|
+
|
|
2007
|
+
.sl-markdown-content .keyed-table > .float-caption {
|
|
2008
|
+
margin-block: 0 0.5rem;
|
|
2009
|
+
break-before: auto;
|
|
2010
|
+
break-after: avoid-page;
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
/* A float's buttons sit together at the top right of its caption line, in
|
|
2014
|
+
one boxed style, always visible: a table's widen ↔ (the same action as
|
|
2015
|
+
the column at its right edge) and its fold ⌃ / ⌄, a diagram's widen ↔.
|
|
2016
|
+
The caption's text keeps clear of a shown one. A table's scripts add the
|
|
2017
|
+
row (`Table.astro`, `TableOverflowExpander.astro`), whichever runs first;
|
|
2018
|
+
a figure's or a diagram's is rendered by `FloatCaption.astro`. */
|
|
2019
|
+
.sl-markdown-content .float-tools {
|
|
2020
|
+
position: absolute;
|
|
2021
|
+
inset-block-start: 0;
|
|
2022
|
+
inset-inline-end: 0;
|
|
2023
|
+
display: inline-flex;
|
|
2024
|
+
gap: 0.25rem;
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2027
|
+
.sl-markdown-content .float-caption:has(> .float-tools > .float-tool:not([hidden])) {
|
|
2028
|
+
padding-inline-end: 2.25rem;
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
.sl-markdown-content
|
|
2032
|
+
.float-caption:has(> .float-tools > .float-tool:not([hidden]) ~ .float-tool:not([hidden])) {
|
|
2033
|
+
padding-inline-end: 4.25rem;
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
.sl-markdown-content .float-tool {
|
|
2037
|
+
display: inline-grid;
|
|
2038
|
+
place-items: center;
|
|
2039
|
+
width: 1.75rem;
|
|
2040
|
+
height: 1.5rem;
|
|
2041
|
+
margin: 0;
|
|
2042
|
+
padding: 0;
|
|
2043
|
+
border: 1px solid var(--sl-color-gray-5);
|
|
2044
|
+
border-radius: 0.3rem;
|
|
2045
|
+
background: var(--sl-color-bg);
|
|
2046
|
+
color: var(--sl-color-gray-2);
|
|
2047
|
+
cursor: pointer;
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2050
|
+
.sl-markdown-content .float-tool[hidden] {
|
|
2051
|
+
display: none;
|
|
2052
|
+
}
|
|
2053
|
+
|
|
2054
|
+
.sl-markdown-content .float-tool svg {
|
|
2055
|
+
width: 0.875rem;
|
|
2056
|
+
height: 0.875rem;
|
|
2057
|
+
fill: none;
|
|
2058
|
+
stroke: currentColor;
|
|
2059
|
+
stroke-width: 2.2;
|
|
2060
|
+
stroke-linecap: round;
|
|
2061
|
+
stroke-linejoin: round;
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
.sl-markdown-content .float-tool:hover {
|
|
2065
|
+
color: var(--sl-color-text-accent);
|
|
2066
|
+
border-color: var(--sl-color-text-accent);
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
.sl-markdown-content .float-tool:focus-visible {
|
|
2070
|
+
outline: 2px solid var(--sl-color-accent);
|
|
2071
|
+
outline-offset: 1px;
|
|
2072
|
+
}
|
|
2073
|
+
|
|
2074
|
+
/* The widen button's two faces: ↔ widens, →← brings the float back. */
|
|
2075
|
+
.sl-markdown-content .float-tool[aria-expanded='true'] .float-tool__widen,
|
|
2076
|
+
.sl-markdown-content .float-tool[aria-expanded='false'] .float-tool__narrow {
|
|
2077
|
+
display: none;
|
|
1275
2078
|
}
|
|
1276
2079
|
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
outline-offset: 0.2rem;
|
|
1283
|
-
}
|
|
2080
|
+
/* The fold button's two faces, for a lab's tools (`Figure.astro`): ⌃ folds
|
|
2081
|
+
them away, ⌄ brings them back. A table's toggle swaps its icon instead. */
|
|
2082
|
+
.sl-markdown-content .float-tool[aria-expanded='true'] .float-tool__unfold,
|
|
2083
|
+
.sl-markdown-content .float-tool[aria-expanded='false'] .float-tool__fold {
|
|
2084
|
+
display: none;
|
|
1284
2085
|
}
|
|
1285
2086
|
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
outline-offset: 0.2rem;
|
|
1291
|
-
}
|
|
1292
|
-
.sl-markdown-content a.equation-ref:hover,
|
|
1293
|
-
.sl-markdown-content a.equation-ref:focus-visible {
|
|
1294
|
-
outline: 2px solid Highlight;
|
|
1295
|
-
}
|
|
2087
|
+
/* The caption line's live end: the case a lab's plot shows, after the long
|
|
2088
|
+
caption (`FloatCaption.astro`, `figure/figure-state.ts`). */
|
|
2089
|
+
.sl-markdown-content .float-caption__state:not(:empty) {
|
|
2090
|
+
margin-inline-start: 0.25em;
|
|
1296
2091
|
}
|
|
1297
2092
|
|
|
1298
2093
|
@media print {
|
|
1299
|
-
.sl-markdown-content .
|
|
1300
|
-
position: static;
|
|
1301
|
-
display: block;
|
|
1302
|
-
transform: none;
|
|
1303
|
-
text-align: end;
|
|
1304
|
-
}
|
|
1305
|
-
.sl-markdown-content a.keyed-equation__number {
|
|
1306
|
-
color: inherit;
|
|
1307
|
-
opacity: 1;
|
|
1308
|
-
}
|
|
1309
|
-
/* A clipboard button means nothing on paper. */
|
|
1310
|
-
.sl-markdown-content .keyed-equation__copy {
|
|
2094
|
+
.sl-markdown-content .float-tools {
|
|
1311
2095
|
display: none;
|
|
1312
2096
|
}
|
|
1313
|
-
|
|
2097
|
+
|
|
2098
|
+
.sl-markdown-content .float-caption:has(> .float-tools) {
|
|
1314
2099
|
padding-inline-end: 0;
|
|
1315
2100
|
}
|
|
1316
2101
|
}
|
|
1317
2102
|
|
|
1318
|
-
/*
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
2103
|
+
/* A short caption opens the line as its bold title, the journal-legend
|
|
2104
|
+
style: "**Sampled flight data.** Position, …" (`FloatCaption.astro`,
|
|
2105
|
+
`Table.astro`; docs/plans/figures-and-short-captions.md, decision 9.1). */
|
|
2106
|
+
.sl-markdown-content .float-caption__title {
|
|
2107
|
+
color: var(--sl-color-text);
|
|
2108
|
+
font-weight: 600;
|
|
1324
2109
|
}
|
|
1325
2110
|
|
|
1326
|
-
.sl-markdown-content .
|
|
1327
|
-
|
|
2111
|
+
.sl-markdown-content .float-caption__number {
|
|
2112
|
+
font-weight: 600;
|
|
2113
|
+
font-variant-numeric: tabular-nums;
|
|
2114
|
+
color: var(--sl-color-text-accent);
|
|
2115
|
+
text-decoration: none;
|
|
2116
|
+
}
|
|
2117
|
+
|
|
2118
|
+
.sl-markdown-content .float-caption__number:hover,
|
|
2119
|
+
.sl-markdown-content .float-caption__number:focus-visible {
|
|
2120
|
+
text-decoration: underline;
|
|
2121
|
+
}
|
|
2122
|
+
|
|
2123
|
+
.sl-markdown-content .float-caption__anchor {
|
|
2124
|
+
display: inline-flex;
|
|
2125
|
+
width: 1.15em;
|
|
2126
|
+
height: 1.15em;
|
|
2127
|
+
margin-inline: 0.15em 0.3em;
|
|
2128
|
+
vertical-align: -0.2em;
|
|
2129
|
+
align-items: center;
|
|
2130
|
+
justify-content: center;
|
|
2131
|
+
color: var(--sl-color-gray-4);
|
|
2132
|
+
text-decoration: none;
|
|
2133
|
+
-webkit-user-select: none;
|
|
2134
|
+
user-select: none;
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
.sl-markdown-content .float-caption__anchor svg {
|
|
2138
|
+
width: 0.85em;
|
|
2139
|
+
height: 0.85em;
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2142
|
+
.sl-markdown-content .float-caption__anchor:hover,
|
|
2143
|
+
.sl-markdown-content .float-caption__anchor:focus-visible {
|
|
2144
|
+
color: var(--sl-color-text-accent);
|
|
2145
|
+
}
|
|
2146
|
+
|
|
2147
|
+
.sl-markdown-content :is(.float-caption__number, .float-caption__anchor):focus-visible {
|
|
2148
|
+
outline: 2px solid var(--sl-color-accent);
|
|
2149
|
+
outline-offset: 0.15rem;
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2152
|
+
@media print {
|
|
2153
|
+
.sl-markdown-content .float-caption__number {
|
|
2154
|
+
color: inherit;
|
|
2155
|
+
}
|
|
1328
2156
|
}
|
|
1329
2157
|
|
|
1330
2158
|
/* `<Table>`/`<Figure>`/`<Diagram>` keyed floats — the same deep-link
|
|
@@ -1346,12 +2174,36 @@ body {
|
|
|
1346
2174
|
white-space: nowrap;
|
|
1347
2175
|
}
|
|
1348
2176
|
|
|
2177
|
+
/* `[[sec-…]]` reads the same, but may print a section's title rather than
|
|
2178
|
+
`§ 1.1.2` (an unnumbered heading, or a course that hides section numbers),
|
|
2179
|
+
so it wraps like prose; the no-break space inside `§ 1.1.2` keeps that one
|
|
2180
|
+
whole. `[[check-…]]` and `[[ex-…]]` follow the section rules too
|
|
2181
|
+
(docs/plans/titles-and-containers.md Q11): a course that hides section
|
|
2182
|
+
numbers gets "Example “‹title›”". */
|
|
2183
|
+
.sl-markdown-content a.section-ref,
|
|
2184
|
+
.sl-markdown-content a.knowledge-check-ref,
|
|
2185
|
+
.sl-markdown-content a.example-ref {
|
|
2186
|
+
font-variant-numeric: tabular-nums;
|
|
2187
|
+
font-weight: 600;
|
|
2188
|
+
text-decoration: underline;
|
|
2189
|
+
text-underline-offset: 0.15em;
|
|
2190
|
+
padding-inline: 0.1em;
|
|
2191
|
+
border-radius: 0.2em;
|
|
2192
|
+
color: var(--sl-color-text-accent);
|
|
2193
|
+
}
|
|
2194
|
+
|
|
1349
2195
|
.sl-markdown-content a.table-ref:hover,
|
|
1350
2196
|
.sl-markdown-content a.table-ref:focus-visible,
|
|
1351
2197
|
.sl-markdown-content a.figure-ref:hover,
|
|
1352
2198
|
.sl-markdown-content a.figure-ref:focus-visible,
|
|
1353
2199
|
.sl-markdown-content a.diagram-ref:hover,
|
|
1354
|
-
.sl-markdown-content a.diagram-ref:focus-visible
|
|
2200
|
+
.sl-markdown-content a.diagram-ref:focus-visible,
|
|
2201
|
+
.sl-markdown-content a.section-ref:hover,
|
|
2202
|
+
.sl-markdown-content a.section-ref:focus-visible,
|
|
2203
|
+
.sl-markdown-content a.knowledge-check-ref:hover,
|
|
2204
|
+
.sl-markdown-content a.knowledge-check-ref:focus-visible,
|
|
2205
|
+
.sl-markdown-content a.example-ref:hover,
|
|
2206
|
+
.sl-markdown-content a.example-ref:focus-visible {
|
|
1355
2207
|
background: var(--sl-color-accent-low);
|
|
1356
2208
|
}
|
|
1357
2209
|
|
|
@@ -1373,13 +2225,34 @@ body {
|
|
|
1373
2225
|
}
|
|
1374
2226
|
}
|
|
1375
2227
|
|
|
2228
|
+
/* A reference whose target sits inside a closed memo or section opens a
|
|
2229
|
+
preview card, as if the target were off screen; while that card is open,
|
|
2230
|
+
the fold's bar is marked the same way, so the reader sees where the
|
|
2231
|
+
target lives (`FloatRefLayer.astro`). */
|
|
2232
|
+
.sl-markdown-content .float-ref-fold-hint {
|
|
2233
|
+
background: var(--sl-color-accent-low);
|
|
2234
|
+
outline: 2px solid var(--sl-color-accent);
|
|
2235
|
+
outline-offset: 0.2rem;
|
|
2236
|
+
border-radius: 0.3rem;
|
|
2237
|
+
transition:
|
|
2238
|
+
background 120ms ease-out,
|
|
2239
|
+
outline-color 120ms ease-out;
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2242
|
+
@media (forced-colors: active) {
|
|
2243
|
+
.sl-markdown-content .float-ref-fold-hint {
|
|
2244
|
+
outline-color: Highlight;
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
|
|
1376
2248
|
/* A referencing `[[tab-key]]`/`[[fig-key]]` link elsewhere in the prose was
|
|
1377
2249
|
hovered/focused and the float it points to is already fully on screen:
|
|
1378
2250
|
highlight it in place instead of opening a preview card
|
|
1379
2251
|
(`FloatRefLayer.astro` decides which) — mirrors `.eq-ref-highlight`. */
|
|
1380
2252
|
.sl-markdown-content .keyed-table.tab-ref-highlight,
|
|
1381
2253
|
.sl-markdown-content .keyed-figure.fig-ref-highlight,
|
|
1382
|
-
.sl-markdown-content .diagram.dia-ref-highlight
|
|
2254
|
+
.sl-markdown-content .diagram.dia-ref-highlight,
|
|
2255
|
+
.sl-markdown-content :is(h2, h3, h4, h5, h6).sec-ref-highlight {
|
|
1383
2256
|
background: var(--sl-color-accent-low);
|
|
1384
2257
|
outline: 2px solid var(--sl-color-accent);
|
|
1385
2258
|
outline-offset: 0.2rem;
|
|
@@ -1395,7 +2268,8 @@ body {
|
|
|
1395
2268
|
.sl-markdown-content .diagram:target,
|
|
1396
2269
|
.sl-markdown-content .keyed-table.tab-ref-highlight,
|
|
1397
2270
|
.sl-markdown-content .keyed-figure.fig-ref-highlight,
|
|
1398
|
-
.sl-markdown-content .diagram.dia-ref-highlight
|
|
2271
|
+
.sl-markdown-content .diagram.dia-ref-highlight,
|
|
2272
|
+
.sl-markdown-content :is(h2, h3, h4, h5, h6).sec-ref-highlight {
|
|
1399
2273
|
animation: none;
|
|
1400
2274
|
outline: 2px solid Highlight;
|
|
1401
2275
|
outline-offset: 0.2rem;
|
|
@@ -1405,7 +2279,13 @@ body {
|
|
|
1405
2279
|
.sl-markdown-content a.figure-ref:hover,
|
|
1406
2280
|
.sl-markdown-content a.figure-ref:focus-visible,
|
|
1407
2281
|
.sl-markdown-content a.diagram-ref:hover,
|
|
1408
|
-
.sl-markdown-content a.diagram-ref:focus-visible
|
|
2282
|
+
.sl-markdown-content a.diagram-ref:focus-visible,
|
|
2283
|
+
.sl-markdown-content a.section-ref:hover,
|
|
2284
|
+
.sl-markdown-content a.section-ref:focus-visible,
|
|
2285
|
+
.sl-markdown-content a.knowledge-check-ref:hover,
|
|
2286
|
+
.sl-markdown-content a.knowledge-check-ref:focus-visible,
|
|
2287
|
+
.sl-markdown-content a.example-ref:hover,
|
|
2288
|
+
.sl-markdown-content a.example-ref:focus-visible {
|
|
1409
2289
|
outline: 2px solid Highlight;
|
|
1410
2290
|
}
|
|
1411
2291
|
}
|
|
@@ -1463,6 +2343,197 @@ body {
|
|
|
1463
2343
|
}
|
|
1464
2344
|
}
|
|
1465
2345
|
|
|
2346
|
+
/* Outline numbers (docs/plans/titles-and-containers.md Part 1). A lesson's
|
|
2347
|
+
numbered heading carries `data-sec-number="1.1.2"` (`remark-notation.mjs`,
|
|
2348
|
+
from the manifest), printed here ahead of the title as generated content —
|
|
2349
|
+
so the heading's own text, its anchor and the "On this page" entry stay the
|
|
2350
|
+
title alone. The number shows on a wide screen and in print; on a narrow one
|
|
2351
|
+
only on a collapsed section's bar, which says what is folded away, and in
|
|
2352
|
+
the chain icon's "Link copied · § 1.1.2". The en space is part of the
|
|
2353
|
+
content, not a margin, so a screen reader hears "1.1.2 Title", not
|
|
2354
|
+
"1.1.2Title". */
|
|
2355
|
+
.sl-markdown-content [data-sec-number]::before {
|
|
2356
|
+
content: attr(data-sec-number) '\2002';
|
|
2357
|
+
color: var(--sl-color-text-accent);
|
|
2358
|
+
font-variant-numeric: tabular-nums;
|
|
2359
|
+
}
|
|
2360
|
+
|
|
2361
|
+
@media screen and (width < 50em) {
|
|
2362
|
+
.sl-markdown-content [data-sec-number]::before {
|
|
2363
|
+
content: none;
|
|
2364
|
+
}
|
|
2365
|
+
|
|
2366
|
+
.sl-markdown-content
|
|
2367
|
+
details.sl-section-collapsible:not([data-state='open'])
|
|
2368
|
+
> .sl-section-summary
|
|
2369
|
+
> [data-sec-number]::before {
|
|
2370
|
+
content: attr(data-sec-number) '\2002';
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
|
|
2374
|
+
@media print {
|
|
2375
|
+
.sl-markdown-content [data-sec-number]::before {
|
|
2376
|
+
color: inherit;
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
|
|
2380
|
+
/* Kind badges (Part 6): the `<h2>` a knowledge check and a worked-example set
|
|
2381
|
+
draw (`BlockHeading.astro`). The kind's icon leads the author's title, as
|
|
2382
|
+
it does in "On this page"; the kind's word and the block's number are a
|
|
2383
|
+
small label in the card's top-right corner, inside its top padding. The
|
|
2384
|
+
label is out of the text flow, so the title keeps the whole line at every
|
|
2385
|
+
width and still wraps word by word, and the number reads as the block's
|
|
2386
|
+
label rather than as a section number. `data-labels="icon"` keeps the word
|
|
2387
|
+
for a screen reader only (`sr-only`). The card's padding is set for it
|
|
2388
|
+
below; `--block-label-lift` is how far the label sits above the title's
|
|
2389
|
+
line box, measured from the card's inner top edge. */
|
|
2390
|
+
.sl-markdown-content .ex-section-card:has(> .block-heading-wrapper) {
|
|
2391
|
+
--block-label-lift: 1.25rem;
|
|
2392
|
+
padding-block-start: var(--block-label-lift);
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
.sl-markdown-content .block-heading-wrapper {
|
|
2396
|
+
position: relative;
|
|
2397
|
+
}
|
|
2398
|
+
|
|
2399
|
+
.sl-markdown-content .block-heading {
|
|
2400
|
+
/* A wrapped title's later lines start under its first word, not under
|
|
2401
|
+
the icon. */
|
|
2402
|
+
padding-inline-start: 1.1em;
|
|
2403
|
+
text-indent: -1.1em;
|
|
2404
|
+
}
|
|
2405
|
+
|
|
2406
|
+
.sl-markdown-content .block-heading__icon {
|
|
2407
|
+
display: inline-block;
|
|
2408
|
+
width: 0.8em;
|
|
2409
|
+
height: 0.8em;
|
|
2410
|
+
margin-inline-end: 0.3em;
|
|
2411
|
+
vertical-align: -0.06em;
|
|
2412
|
+
color: var(--sl-color-text-accent);
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
.sl-markdown-content .block-badge {
|
|
2416
|
+
position: absolute;
|
|
2417
|
+
inset-block-start: calc(0.3rem - var(--block-label-lift, 1.25rem));
|
|
2418
|
+
inset-inline-end: 0;
|
|
2419
|
+
color: var(--sl-color-text-accent);
|
|
2420
|
+
font-size: 0.75rem;
|
|
2421
|
+
font-weight: 600;
|
|
2422
|
+
letter-spacing: 0.05em;
|
|
2423
|
+
line-height: 1.2;
|
|
2424
|
+
text-indent: 0;
|
|
2425
|
+
text-transform: uppercase;
|
|
2426
|
+
white-space: nowrap;
|
|
2427
|
+
}
|
|
2428
|
+
|
|
2429
|
+
/* Narrow and touch screens set the heading inline beside the section's
|
|
2430
|
+
chevron, with the summary's own hanging indent (below); the heading's
|
|
2431
|
+
indent above would double it. */
|
|
2432
|
+
@media screen and (width < 50em), screen and (hover: none) {
|
|
2433
|
+
.sl-markdown-content .block-heading {
|
|
2434
|
+
padding-inline-start: 0;
|
|
2435
|
+
text-indent: 0;
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
|
|
2439
|
+
/* The number follows the section numbers' rules above (Q11): shown on a wide
|
|
2440
|
+
screen and in print; on a narrow one only on a folded bar, and in the chain
|
|
2441
|
+
icon's "Link copied · Example 1.1.1". Real text, so the heading's name reads
|
|
2442
|
+
"Example 1.1.1 ‹title›" wherever it shows. */
|
|
2443
|
+
.sl-markdown-content .block-heading__number {
|
|
2444
|
+
color: var(--sl-color-text-accent);
|
|
2445
|
+
font-variant-numeric: tabular-nums;
|
|
2446
|
+
}
|
|
2447
|
+
|
|
2448
|
+
@media screen and (width < 50em) {
|
|
2449
|
+
.sl-markdown-content .block-heading__number {
|
|
2450
|
+
display: none;
|
|
2451
|
+
}
|
|
2452
|
+
|
|
2453
|
+
.sl-markdown-content
|
|
2454
|
+
details.sl-section-collapsible:not([data-state='open'])
|
|
2455
|
+
> .sl-section-summary
|
|
2456
|
+
> .block-heading
|
|
2457
|
+
.block-heading__number {
|
|
2458
|
+
display: inline;
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2462
|
+
@media print {
|
|
2463
|
+
.sl-markdown-content .block-heading__number {
|
|
2464
|
+
color: inherit;
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
|
|
2468
|
+
/* "On this page" lists a check and an example set by its title alone, as it
|
|
2469
|
+
lists a section; the badge's icon before the title says which kind it is
|
|
2470
|
+
(`LayoutPageSidebar.astro` marks the link `data-block-kind`). A mask, so
|
|
2471
|
+
the icon takes the link's colour, current and hovered alike. */
|
|
2472
|
+
:is(starlight-toc, mobile-starlight-toc) a[data-block-kind]::before {
|
|
2473
|
+
content: '';
|
|
2474
|
+
display: inline-block;
|
|
2475
|
+
width: 0.95em;
|
|
2476
|
+
height: 0.95em;
|
|
2477
|
+
margin-inline-end: 0.35em;
|
|
2478
|
+
vertical-align: -0.12em;
|
|
2479
|
+
background-color: currentColor;
|
|
2480
|
+
mask: var(--block-kind-icon) center / contain no-repeat;
|
|
2481
|
+
}
|
|
2482
|
+
|
|
2483
|
+
:is(starlight-toc, mobile-starlight-toc) a[data-block-kind='check'] {
|
|
2484
|
+
--block-kind-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 8.5l4 4 8-9'/%3E%3C/svg%3E");
|
|
2485
|
+
}
|
|
2486
|
+
|
|
2487
|
+
:is(starlight-toc, mobile-starlight-toc) a[data-block-kind='example'] {
|
|
2488
|
+
--block-kind-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round'%3E%3Crect x='2' y='2' width='12' height='12' rx='2'/%3E%3Cpath d='M5 8h6M8 5v6'/%3E%3C/svg%3E");
|
|
2489
|
+
}
|
|
2490
|
+
|
|
2491
|
+
/* "Link copied · § 1.1.2" — `HeadingAnchorEnhancer.astro` places it under the
|
|
2492
|
+
title in page coordinates, clamped to the text column, and removes it
|
|
2493
|
+
after a moment; the same accent chip as an equation's "Copied!", with an
|
|
2494
|
+
edge and a shadow because the section behind it is flashing the same
|
|
2495
|
+
accent tint. */
|
|
2496
|
+
.sl-anchor-copied {
|
|
2497
|
+
position: absolute;
|
|
2498
|
+
z-index: 30;
|
|
2499
|
+
padding: 0.15rem 0.5rem;
|
|
2500
|
+
border: 1px solid var(--sl-color-accent);
|
|
2501
|
+
border-radius: 0.35rem;
|
|
2502
|
+
box-shadow: 0 0.2rem 0.6rem rgba(0, 0, 0, 0.15);
|
|
2503
|
+
background: var(--sl-color-accent-low);
|
|
2504
|
+
color: var(--sl-color-text-accent);
|
|
2505
|
+
font-size: var(--sl-text-xs);
|
|
2506
|
+
line-height: 1.5;
|
|
2507
|
+
/* One line for a short name; a long title wraps inside the cap, never
|
|
2508
|
+
wider than the column (the script keeps it inside the column). */
|
|
2509
|
+
width: max-content;
|
|
2510
|
+
max-width: min(28rem, calc(100vw - 2rem));
|
|
2511
|
+
pointer-events: none;
|
|
2512
|
+
animation: sl-anchor-copied 1.8s ease both;
|
|
2513
|
+
}
|
|
2514
|
+
|
|
2515
|
+
@keyframes sl-anchor-copied {
|
|
2516
|
+
0%,
|
|
2517
|
+
75% {
|
|
2518
|
+
opacity: 1;
|
|
2519
|
+
}
|
|
2520
|
+
100% {
|
|
2521
|
+
opacity: 0;
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2524
|
+
|
|
2525
|
+
@media (prefers-reduced-motion: reduce) {
|
|
2526
|
+
.sl-anchor-copied {
|
|
2527
|
+
animation: none;
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
|
|
2531
|
+
@media print {
|
|
2532
|
+
.sl-anchor-copied {
|
|
2533
|
+
display: none;
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
|
|
1466
2537
|
/* Collapsible sections (docs/plans/collapsible-disclosure.md Part 3),
|
|
1467
2538
|
wrapped at runtime by `CollapsibleSections.astro` around headings an
|
|
1468
2539
|
author opted in with `{collapsible}`. Starlight's own `markdown.css` gives
|
|
@@ -1535,13 +2606,21 @@ body {
|
|
|
1535
2606
|
never satisfies this selector. Both rules are unlayered, so they win over
|
|
1536
2607
|
`anchor-links.css`'s `@layer starlight.content` version regardless of
|
|
1537
2608
|
specificity — this replaces that default behavior for sections rather
|
|
1538
|
-
than adding to it.
|
|
2609
|
+
than adding to it. Like Starlight's own rule, the icon hides only where a
|
|
2610
|
+
hover can reveal it: on a touch screen it stays visible, since it is a
|
|
2611
|
+
real tap target at the end of the title line either way (an invisible one
|
|
2612
|
+
used to take a tap meant for the title and change the URL instead). */
|
|
1539
2613
|
.sl-markdown-content .sl-heading-wrapper.sl-section-titlebar > .sl-anchor-link {
|
|
1540
2614
|
position: absolute;
|
|
1541
2615
|
top: 0.2em;
|
|
1542
2616
|
inset-inline-end: 0;
|
|
1543
2617
|
margin-inline-start: 0;
|
|
1544
|
-
|
|
2618
|
+
}
|
|
2619
|
+
|
|
2620
|
+
@media (hover: hover) {
|
|
2621
|
+
.sl-markdown-content .sl-heading-wrapper.sl-section-titlebar > .sl-anchor-link {
|
|
2622
|
+
opacity: 0;
|
|
2623
|
+
}
|
|
1545
2624
|
}
|
|
1546
2625
|
|
|
1547
2626
|
.sl-markdown-content .sl-heading-wrapper.sl-section-titlebar:has(> .sl-section-collapsible > summary:hover)
|
|
@@ -1553,24 +2632,72 @@ body {
|
|
|
1553
2632
|
opacity: 1;
|
|
1554
2633
|
}
|
|
1555
2634
|
|
|
2635
|
+
/* A narrow screen shows no section number and, often, has no hover to reveal
|
|
2636
|
+
the chain icon — yet the icon is the way to the section's link and, in its
|
|
2637
|
+
"Link copied · § 1.1.2", its number (docs/plans/titles-and-containers.md
|
|
2638
|
+
Q3). So it is always shown there, smaller and in the muted text colour.
|
|
2639
|
+
The size variable also sets the room `anchor-links.css` reserves for it at
|
|
2640
|
+
the end of the title. After the hover rules above, which it overrides. */
|
|
2641
|
+
@media screen and (width < 50em) {
|
|
2642
|
+
.sl-markdown-content .sl-heading-wrapper {
|
|
2643
|
+
--sl-anchor-icon-size: 0.7em;
|
|
2644
|
+
}
|
|
2645
|
+
|
|
2646
|
+
.sl-markdown-content .sl-heading-wrapper > .sl-anchor-link,
|
|
2647
|
+
.sl-markdown-content .sl-heading-wrapper.sl-section-titlebar > .sl-anchor-link {
|
|
2648
|
+
opacity: 1;
|
|
2649
|
+
color: var(--sl-color-gray-3);
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2652
|
+
|
|
1556
2653
|
/* The chevron sits to the *left* of the title without shifting the title's
|
|
1557
2654
|
own position: `markdown.css`'s default marker is inline, right before the
|
|
1558
2655
|
text, pushed left slightly by a negative margin — meaning the title
|
|
1559
2656
|
itself sits further right than an ordinary (non-collapsible) heading.
|
|
1560
2657
|
Taking the marker fully out of flow with `position: absolute` and a
|
|
1561
2658
|
negative `left` puts it in the gutter instead, so `.sl-section-summary`'s
|
|
1562
|
-
own text always starts at the same position a plain heading's would.
|
|
2659
|
+
own text always starts at the same position a plain heading's would.
|
|
2660
|
+
That gutter is only `--sl-content-pad-x` wide (16–24px) and ends at the
|
|
2661
|
+
sidebar's border, so the marker is centred in it — a fixed `-1.6em` once
|
|
2662
|
+
put the glyph right on that border line. Inside a `[card]` section the
|
|
2663
|
+
gutter is the card's own padding (`--ex-section-gutter`, `surfaces.css`).
|
|
2664
|
+
Narrow and touch screens have no usable gutter at all; the marker moves
|
|
2665
|
+
into the title line there (below). */
|
|
1563
2666
|
.sl-markdown-content .sl-section-summary {
|
|
1564
2667
|
position: relative;
|
|
1565
|
-
/* Room for the absolutely-positioned anchor icon at the end of the line
|
|
1566
|
-
same reasoning as `.keyed-figure__summary` in `Figure.astro`. */
|
|
2668
|
+
/* Room for the absolutely-positioned anchor icon at the end of the line. */
|
|
1567
2669
|
padding-inline-end: 1.5em;
|
|
2670
|
+
/* The title's own font size, so the gutter chevron can centre on the
|
|
2671
|
+
title's first line — not on the whole summary, which also holds the
|
|
2672
|
+
"Hidden here" line while closed. */
|
|
2673
|
+
--sl-section-title-size: var(--sl-text-h2);
|
|
2674
|
+
}
|
|
2675
|
+
|
|
2676
|
+
.sl-markdown-content .sl-section-summary:has(> h3) {
|
|
2677
|
+
--sl-section-title-size: var(--sl-text-h3);
|
|
2678
|
+
}
|
|
2679
|
+
|
|
2680
|
+
.sl-markdown-content .sl-section-summary:has(> h4) {
|
|
2681
|
+
--sl-section-title-size: var(--sl-text-h4);
|
|
2682
|
+
}
|
|
2683
|
+
|
|
2684
|
+
.sl-markdown-content .sl-section-summary:has(> h5) {
|
|
2685
|
+
--sl-section-title-size: var(--sl-text-h5);
|
|
2686
|
+
}
|
|
2687
|
+
|
|
2688
|
+
.sl-markdown-content .sl-section-summary:has(> h6) {
|
|
2689
|
+
--sl-section-title-size: var(--sl-text-h6, var(--sl-text-base));
|
|
1568
2690
|
}
|
|
1569
2691
|
|
|
1570
2692
|
.sl-markdown-content .sl-section-summary::before {
|
|
1571
2693
|
position: absolute;
|
|
1572
|
-
left
|
|
1573
|
-
|
|
2694
|
+
/* `<summary>` starts 0.5rem left of the text (`markdown.css`), so this
|
|
2695
|
+
centres the marker box on the middle of the gutter. */
|
|
2696
|
+
left: calc(
|
|
2697
|
+
0.5rem - var(--ex-section-gutter, var(--sl-content-pad-x, 1rem)) / 2 -
|
|
2698
|
+
var(--sl-details-marker-size, 1.25rem) / 2
|
|
2699
|
+
);
|
|
2700
|
+
top: calc(var(--sl-section-title-size) * var(--sl-line-height-headings) / 2);
|
|
1574
2701
|
margin: 0; /* cancel `markdown.css`'s inline-flow margin trick */
|
|
1575
2702
|
transform: translateY(-50%);
|
|
1576
2703
|
opacity: 0;
|
|
@@ -1602,6 +2729,109 @@ body {
|
|
|
1602
2729
|
transition: opacity 100ms ease;
|
|
1603
2730
|
}
|
|
1604
2731
|
|
|
2732
|
+
/* A closed section's cues beyond the chevron — the two `aria-hidden` spans
|
|
2733
|
+
`CollapsibleSections.astro` appends to `<summary>` after the heading.
|
|
2734
|
+
`.sl-section-hint` ("(click to expand)", "(tap to expand)" on touch) is
|
|
2735
|
+
for narrow/touch screens only (enabled in the block below);
|
|
2736
|
+
`.sl-section-stub` ("Hidden here: 2 paragraphs, 1 equation") shows on
|
|
2737
|
+
every screen. Both vanish once the section is `open` — the stub by
|
|
2738
|
+
collapsing its grid row, so a peek grown into a real expand slides the
|
|
2739
|
+
body up smoothly instead of jumping by a line. */
|
|
2740
|
+
.sl-markdown-content .sl-section-hint {
|
|
2741
|
+
display: none;
|
|
2742
|
+
margin-inline-start: 0.4em;
|
|
2743
|
+
font-size: var(--sl-text-sm);
|
|
2744
|
+
font-weight: 400;
|
|
2745
|
+
color: var(--sl-color-gray-3);
|
|
2746
|
+
white-space: nowrap;
|
|
2747
|
+
}
|
|
2748
|
+
|
|
2749
|
+
.sl-markdown-content .sl-section-hint::before {
|
|
2750
|
+
content: '(click to expand)';
|
|
2751
|
+
}
|
|
2752
|
+
|
|
2753
|
+
@media (hover: none) {
|
|
2754
|
+
.sl-markdown-content .sl-section-hint::before {
|
|
2755
|
+
content: '(tap to expand)';
|
|
2756
|
+
}
|
|
2757
|
+
}
|
|
2758
|
+
|
|
2759
|
+
.sl-markdown-content .sl-section-stub {
|
|
2760
|
+
display: grid;
|
|
2761
|
+
grid-template-rows: 0fr;
|
|
2762
|
+
opacity: 0;
|
|
2763
|
+
margin-block-start: 0;
|
|
2764
|
+
padding-block-end: 0;
|
|
2765
|
+
border-block-end: 0 dashed var(--sl-color-gray-5);
|
|
2766
|
+
text-indent: 0; /* the narrow-screen hanging indent is for the title only */
|
|
2767
|
+
font-size: var(--sl-text-sm);
|
|
2768
|
+
font-weight: 400;
|
|
2769
|
+
line-height: 1.5;
|
|
2770
|
+
color: var(--sl-color-gray-3);
|
|
2771
|
+
transition:
|
|
2772
|
+
grid-template-rows 220ms ease,
|
|
2773
|
+
opacity 150ms ease,
|
|
2774
|
+
margin-block-start 220ms ease,
|
|
2775
|
+
padding-block-end 220ms ease,
|
|
2776
|
+
border-block-end-width 220ms ease;
|
|
2777
|
+
}
|
|
2778
|
+
|
|
2779
|
+
.sl-markdown-content .sl-section-stub > span {
|
|
2780
|
+
overflow: hidden;
|
|
2781
|
+
min-height: 0;
|
|
2782
|
+
}
|
|
2783
|
+
|
|
2784
|
+
.sl-markdown-content details.sl-section-collapsible:not([data-state='open'])
|
|
2785
|
+
> .sl-section-summary
|
|
2786
|
+
> .sl-section-stub {
|
|
2787
|
+
grid-template-rows: 1fr;
|
|
2788
|
+
opacity: 1;
|
|
2789
|
+
margin-block-start: 0.3rem;
|
|
2790
|
+
padding-block-end: 0.45rem;
|
|
2791
|
+
border-block-end-width: 1px;
|
|
2792
|
+
}
|
|
2793
|
+
|
|
2794
|
+
/* Narrow and touch screens: there is no gutter to hold the chevron (on a
|
|
2795
|
+
phone it used to render off-screen), and no hover to reveal it on an open
|
|
2796
|
+
section. It moves into the title line and stays visible in both states —
|
|
2797
|
+
`›` closed, `⌄` open, so it also tells a reader the section can fold —
|
|
2798
|
+
with a hanging indent that keeps a wrapped title's later lines under its
|
|
2799
|
+
text, not under the chevron. The room reserved is the marker's own box
|
|
2800
|
+
minus its negative start margin plus its end gap (`markdown.css`).
|
|
2801
|
+
`screen` only: a printer reports `hover: none` too, and an inline heading
|
|
2802
|
+
would lose the print stylesheet's `break-after: avoid`. */
|
|
2803
|
+
@media screen and (width < 50em), screen and (hover: none) {
|
|
2804
|
+
.sl-markdown-content .sl-section-summary {
|
|
2805
|
+
--sl-section-marker-room: calc(
|
|
2806
|
+
var(--sl-details-marker-size, 1.25rem) * 0.75 + 0.25rem
|
|
2807
|
+
);
|
|
2808
|
+
padding-inline-start: calc(0.5rem + var(--sl-section-marker-room));
|
|
2809
|
+
text-indent: calc(-1 * var(--sl-section-marker-room));
|
|
2810
|
+
}
|
|
2811
|
+
|
|
2812
|
+
.sl-markdown-content .sl-section-summary > :is(h1, h2, h3, h4, h5, h6) {
|
|
2813
|
+
display: inline;
|
|
2814
|
+
}
|
|
2815
|
+
|
|
2816
|
+
.sl-markdown-content .sl-section-summary::before {
|
|
2817
|
+
position: static;
|
|
2818
|
+
vertical-align: -0.15em;
|
|
2819
|
+
transform: none;
|
|
2820
|
+
opacity: 1;
|
|
2821
|
+
transition: transform 150ms ease;
|
|
2822
|
+
}
|
|
2823
|
+
|
|
2824
|
+
.sl-markdown-content details.sl-section-collapsible[open] > .sl-section-summary::before {
|
|
2825
|
+
transform: rotateZ(90deg);
|
|
2826
|
+
}
|
|
2827
|
+
|
|
2828
|
+
.sl-markdown-content details.sl-section-collapsible:not([data-state='open'])
|
|
2829
|
+
> .sl-section-summary
|
|
2830
|
+
> .sl-section-hint {
|
|
2831
|
+
display: inline;
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2834
|
+
|
|
1605
2835
|
/* The section body: normally native `<details>` hiding/showing is all that's
|
|
1606
2836
|
needed (nothing renders while closed), but `peeking` (a collapsed section
|
|
1607
2837
|
hovered/focused — see `CollapsibleSections.astro`) has to force the
|
|
@@ -1650,13 +2880,16 @@ body {
|
|
|
1650
2880
|
|
|
1651
2881
|
@media (prefers-reduced-motion: reduce) {
|
|
1652
2882
|
.sl-markdown-content .sl-section-summary::before,
|
|
1653
|
-
.sl-markdown-content .sl-section-body
|
|
2883
|
+
.sl-markdown-content .sl-section-body,
|
|
2884
|
+
.sl-markdown-content .sl-section-stub {
|
|
1654
2885
|
transition: none;
|
|
1655
2886
|
}
|
|
1656
2887
|
}
|
|
1657
2888
|
|
|
1658
2889
|
@media print {
|
|
1659
|
-
.sl-markdown-content .sl-section-summary::before
|
|
2890
|
+
.sl-markdown-content .sl-section-summary::before,
|
|
2891
|
+
.sl-markdown-content .sl-section-hint,
|
|
2892
|
+
.sl-markdown-content .sl-section-stub {
|
|
1660
2893
|
display: none !important;
|
|
1661
2894
|
}
|
|
1662
2895
|
|
|
@@ -1664,14 +2897,13 @@ body {
|
|
|
1664
2897
|
display: none;
|
|
1665
2898
|
}
|
|
1666
2899
|
|
|
1667
|
-
/*
|
|
1668
|
-
has the browser skip rendering a closed <details>'s
|
|
1669
|
-
children outright — a rule no author CSS can override
|
|
1670
|
-
`content-visibility`, `!important` included).
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
`afterprint`. */
|
|
2900
|
+
/* Print follows the screen, and CSS couldn't do otherwise anyway: the
|
|
2901
|
+
HTML spec has the browser skip rendering a closed <details>'s
|
|
2902
|
+
non-summary children outright — a rule no author CSS can override
|
|
2903
|
+
(`display`, `content-visibility`, `!important` included). What JS does
|
|
2904
|
+
at print time (`src/components/disclosure/print-as-shown.ts`) is settle
|
|
2905
|
+
a peeking or mid-animation section to the state it reads as, and add a
|
|
2906
|
+
"(content collapsed …)" note after each closed one. */
|
|
1675
2907
|
}
|
|
1676
2908
|
|
|
1677
2909
|
/* Table column narrowing + expand-on-overflow
|
|
@@ -1702,10 +2934,10 @@ body {
|
|
|
1702
2934
|
`TableOverflowExpander.astro`'s script, and to every table on the site,
|
|
1703
2935
|
not just ones wide enough to overflow. `color-mix` against `--sl-color-bg`
|
|
1704
2936
|
(not a fixed gray token) keeps the stripe theme-correct automatically —
|
|
1705
|
-
the same technique
|
|
1706
|
-
reason: a token like
|
|
1707
|
-
|
|
1708
|
-
|
|
2937
|
+
the same technique `surfaces.css`'s accent tint uses, and for the same
|
|
2938
|
+
reason: a token like `--sl-color-gray-7` is only defined for one theme.
|
|
2939
|
+
The hover rule is unlayered and comes after the stripe rule, so it wins
|
|
2940
|
+
over an even/odd row's own stripe regardless of specificity. */
|
|
1709
2941
|
.sl-markdown-content table:not(:where(.not-content *)) tbody tr:nth-child(even) {
|
|
1710
2942
|
background: color-mix(in srgb, var(--sl-color-bg) 85%, var(--sl-color-gray-5) 15%);
|
|
1711
2943
|
}
|
|
@@ -1731,6 +2963,19 @@ body {
|
|
|
1731
2963
|
flex: 1 1 auto;
|
|
1732
2964
|
min-width: 0;
|
|
1733
2965
|
overflow-x: auto;
|
|
2966
|
+
/* A size container, so a row spanning the whole table (the "… N more
|
|
2967
|
+
rows …" separator, `Table.astro`) can size its label to the part of
|
|
2968
|
+
the table on screen (`100cqi`), not to its whole scrolled width. It
|
|
2969
|
+
takes its width from the flex row, never from its content, so the
|
|
2970
|
+
inline-size containment this implies changes nothing else. */
|
|
2971
|
+
container-type: inline-size;
|
|
2972
|
+
}
|
|
2973
|
+
|
|
2974
|
+
/* A preview card sizes itself to its content, and a size container has no
|
|
2975
|
+
width of its own to give it: in a card the table's width sizes the card,
|
|
2976
|
+
as it always did (`FloatRefLayer.astro`). */
|
|
2977
|
+
.hover-panel .table-overflow-scroll {
|
|
2978
|
+
container-type: normal;
|
|
1734
2979
|
}
|
|
1735
2980
|
|
|
1736
2981
|
/* A scrollable region must be reachable by keyboard (WCAG 2.1.1) — the
|
|
@@ -1898,6 +3143,7 @@ body {
|
|
|
1898
3143
|
.right-sidebar-container,
|
|
1899
3144
|
.pagination-links,
|
|
1900
3145
|
.layout-edge-toggle,
|
|
3146
|
+
.layout-edge-resizer,
|
|
1901
3147
|
[data-explico-export-chrome],
|
|
1902
3148
|
[data-popup-root],
|
|
1903
3149
|
[data-citation-panel],
|
|
@@ -1909,11 +3155,8 @@ body {
|
|
|
1909
3155
|
.table-overflow-expand-btn,
|
|
1910
3156
|
.keyed-table__pagination-links,
|
|
1911
3157
|
.keyed-table__more-row,
|
|
1912
|
-
.diagram-toolbar,
|
|
1913
3158
|
.sl-anchor-link,
|
|
1914
|
-
.
|
|
1915
|
-
.diagram__title-anchor,
|
|
1916
|
-
.memo-block__title-anchor,
|
|
3159
|
+
.float-caption__anchor,
|
|
1917
3160
|
.short-note__collapse,
|
|
1918
3161
|
.assessment-actions,
|
|
1919
3162
|
.assessment-chevron,
|
|
@@ -1956,9 +3199,6 @@ body {
|
|
|
1956
3199
|
}
|
|
1957
3200
|
|
|
1958
3201
|
.sl-markdown-content :is(h1, h2, h3, h4, h5, h6),
|
|
1959
|
-
.keyed-figure__summary,
|
|
1960
|
-
.diagram__summary,
|
|
1961
|
-
.memo-block__summary,
|
|
1962
3202
|
.assessment-item-heading {
|
|
1963
3203
|
break-after: avoid-page;
|
|
1964
3204
|
page-break-after: avoid;
|
|
@@ -1978,7 +3218,7 @@ body {
|
|
|
1978
3218
|
.compact-example,
|
|
1979
3219
|
.assessment-item,
|
|
1980
3220
|
.lab-result,
|
|
1981
|
-
.lab-chart
|
|
3221
|
+
.lab-chart,
|
|
1982
3222
|
.sl-markdown-content pre,
|
|
1983
3223
|
.sl-markdown-content blockquote {
|
|
1984
3224
|
break-inside: avoid-page;
|
|
@@ -2038,15 +3278,15 @@ body {
|
|
|
2038
3278
|
display: table-row !important;
|
|
2039
3279
|
}
|
|
2040
3280
|
|
|
2041
|
-
|
|
2042
|
-
|
|
3281
|
+
/* An open example set's inactive tabs are hidden only to save screen
|
|
3282
|
+
space. A closed question panel or short note is the reader's own
|
|
3283
|
+
disclosure, and print follows the screen for those — it stays closed
|
|
3284
|
+
and gets a `.explico-collapsed-note` (below) instead. */
|
|
2043
3285
|
.compact-example[hidden] {
|
|
2044
3286
|
display: block !important;
|
|
2045
3287
|
}
|
|
2046
3288
|
|
|
2047
3289
|
.diagram,
|
|
2048
|
-
.diagram__titlebar,
|
|
2049
|
-
.diagram__details,
|
|
2050
3290
|
.diagram__body,
|
|
2051
3291
|
.diagram-stage,
|
|
2052
3292
|
.diagram-scroll {
|
|
@@ -2077,6 +3317,32 @@ body {
|
|
|
2077
3317
|
height: 100% !important;
|
|
2078
3318
|
}
|
|
2079
3319
|
|
|
3320
|
+
/* WebKit (Safari, every iOS browser) paints a `foreignObject` descendant
|
|
3321
|
+
with its own render layer — every KaTeX `position: relative` span —
|
|
3322
|
+
without the SVG's internal transforms, the `viewBox` scale above
|
|
3323
|
+
included, so a printed diagram loses its formulas. Where CSS can divide
|
|
3324
|
+
lengths, keep the SVG at its build-time size and scale the HTML canvas
|
|
3325
|
+
instead; the negative block margin gives the layout box the scaled
|
|
3326
|
+
height. Without that support the `viewBox` scaling above stays. */
|
|
3327
|
+
@supports (transform: scale(calc(100cqw / 1px))) {
|
|
3328
|
+
.diagram-scroll {
|
|
3329
|
+
container-type: inline-size;
|
|
3330
|
+
}
|
|
3331
|
+
|
|
3332
|
+
.diagram-canvas {
|
|
3333
|
+
width: calc(var(--diagram-width) * 1px) !important;
|
|
3334
|
+
max-width: none !important;
|
|
3335
|
+
height: calc(var(--diagram-height) * 1px) !important;
|
|
3336
|
+
aspect-ratio: auto;
|
|
3337
|
+
margin-block-end: calc(
|
|
3338
|
+
100cqw * var(--diagram-height) / var(--diagram-width) -
|
|
3339
|
+
var(--diagram-height) * 1px
|
|
3340
|
+
);
|
|
3341
|
+
transform: scale(calc(100cqw / (var(--diagram-width) * 1px)));
|
|
3342
|
+
transform-origin: 0 0;
|
|
3343
|
+
}
|
|
3344
|
+
}
|
|
3345
|
+
|
|
2080
3346
|
.lab-chart,
|
|
2081
3347
|
.lab-math,
|
|
2082
3348
|
.katex-display {
|
|
@@ -2085,10 +3351,14 @@ body {
|
|
|
2085
3351
|
overflow: visible !important;
|
|
2086
3352
|
}
|
|
2087
3353
|
|
|
3354
|
+
/* Not KaTeX's own SVGs: a `\sqrt` radical (and stretchy arrows/accents)
|
|
3355
|
+
is a deliberately oversized SVG clipped by its parent, and its height
|
|
3356
|
+
comes from KaTeX's `height` attribute — `height: auto` resolved it to
|
|
3357
|
+
0, so every printed square root lost its radical sign. */
|
|
2088
3358
|
.lab-chart svg,
|
|
2089
3359
|
.keyed-figure img,
|
|
2090
3360
|
.sl-markdown-content img,
|
|
2091
|
-
.sl-markdown-content svg {
|
|
3361
|
+
.sl-markdown-content svg:not(.katex *) {
|
|
2092
3362
|
max-width: 100% !important;
|
|
2093
3363
|
height: auto;
|
|
2094
3364
|
}
|
|
@@ -2108,14 +3378,18 @@ body {
|
|
|
2108
3378
|
}
|
|
2109
3379
|
|
|
2110
3380
|
:is(
|
|
3381
|
+
.ex-tier-meta,
|
|
3382
|
+
.ex-tier-accent,
|
|
3383
|
+
.ex-tier-aside,
|
|
3384
|
+
.starlight-aside,
|
|
3385
|
+
.sl-markdown-content article.card,
|
|
2111
3386
|
.lab-shell,
|
|
2112
3387
|
.lab-result,
|
|
2113
3388
|
.assessment-shell,
|
|
2114
3389
|
.assessment-item,
|
|
2115
3390
|
.memo-block-frame,
|
|
2116
|
-
.keyed-figure__details,
|
|
2117
3391
|
.compact-examples,
|
|
2118
|
-
.
|
|
3392
|
+
.block-badge
|
|
2119
3393
|
) {
|
|
2120
3394
|
color: #111 !important;
|
|
2121
3395
|
border-color: #777 !important;
|
|
@@ -2130,4 +3404,38 @@ body {
|
|
|
2130
3404
|
-webkit-print-color-adjust: exact;
|
|
2131
3405
|
}
|
|
2132
3406
|
|
|
3407
|
+
/* "(content collapsed — full text: …)" under a disclosure the reader left
|
|
3408
|
+
closed (`src/components/disclosure/print-as-shown.ts`). Sized in `rem`:
|
|
3409
|
+
a section's note sits inside its heading-sized title bar. */
|
|
3410
|
+
.explico-collapsed-note {
|
|
3411
|
+
display: block;
|
|
3412
|
+
margin-block: 0.15rem 0.75rem;
|
|
3413
|
+
font-size: 0.8rem;
|
|
3414
|
+
font-style: italic;
|
|
3415
|
+
font-weight: 400;
|
|
3416
|
+
line-height: 1.4;
|
|
3417
|
+
color: #444;
|
|
3418
|
+
overflow-wrap: anywhere;
|
|
3419
|
+
text-indent: 0;
|
|
3420
|
+
}
|
|
3421
|
+
|
|
3422
|
+
.explico-collapsed-note a[href] {
|
|
3423
|
+
color: #08775b !important;
|
|
3424
|
+
text-decoration: underline;
|
|
3425
|
+
print-color-adjust: exact;
|
|
3426
|
+
-webkit-print-color-adjust: exact;
|
|
3427
|
+
}
|
|
3428
|
+
|
|
3429
|
+
.memo-block-frame .explico-collapsed-note {
|
|
3430
|
+
margin: 0;
|
|
3431
|
+
padding-block-end: 0.25rem;
|
|
3432
|
+
}
|
|
3433
|
+
}
|
|
3434
|
+
|
|
3435
|
+
/* The note exists only while a print is being prepared, and never shows on
|
|
3436
|
+
screen even then (the print button prepares before the dialog opens). */
|
|
3437
|
+
@media not print {
|
|
3438
|
+
.explico-collapsed-note {
|
|
3439
|
+
display: none;
|
|
3440
|
+
}
|
|
2133
3441
|
}
|