explico 0.8.0 → 0.11.1
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 +1257 -1
- package/README.md +60 -15
- package/dist/compiler/astro.d.ts +6 -1
- package/dist/compiler/cli.d.ts +46 -2
- package/dist/compiler/cli.js +70 -4
- package/dist/compiler/collections.d.ts +35 -2
- package/dist/compiler/collections.js +68 -5
- 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 +4 -1
- package/dist/compiler/logging.js +4 -1
- 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 +3 -2
- 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 +60 -31
- package/dist/reference/equations.mjs +83 -43
- 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 +1 -0
- 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 +45 -21
- 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 +22 -6
- package/dist/reference/gate-math.js +42 -8
- 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 +21 -11
- package/dist/reference/gate-prose-notation.js +25 -7
- package/dist/reference/katex-delimiters.mjs +20 -7
- 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 +572 -37
- 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 +4 -4
- 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 +17 -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 +5 -3
- 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 +1152 -2
- package/docs/authoring/notation.md +576 -322
- 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/package.json +2 -2
- package/src/compiler/cli.ts +116 -6
- package/src/compiler/collections.ts +111 -7
- 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 +8 -2
- 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 +3 -4
- package/src/components/notation/NotationLayer.astro +169 -162
- package/src/components/notation/NotationMath.astro +10 -1
- package/src/components/reference/FloatRefLayer.astro +485 -423
- package/src/components/starlight/AboutPanel.astro +5 -4
- 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 +3 -2
- package/src/reference/diagrams-validate.ts +17 -1
- package/src/reference/equations-validate.ts +10 -5
- package/src/reference/equations.mjs +83 -43
- 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 +1 -0
- package/src/reference/gate-course-rules.ts +134 -0
- package/src/reference/gate-heading-length.ts +66 -35
- package/src/reference/gate-heading-structure.ts +193 -0
- package/src/reference/gate-math-punctuation.ts +381 -0
- package/src/reference/gate-math.ts +69 -10
- package/src/reference/gate-part-pages.ts +217 -0
- package/src/reference/gate-prose-notation.ts +59 -12
- package/src/reference/katex-delimiters.mjs +20 -7
- 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 +572 -37
- 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 +16 -31
- 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 +17 -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 +1467 -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,160 @@ 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 label that does not fit wraps onto more lines, and the side panels
|
|
1047
|
+
never scroll sideways: a word longer than the panel is wide is
|
|
1048
|
+
hyphenated where the language allows, else broken. Starlight's
|
|
1049
|
+
`overflow-wrap: anywhere` on the contents links broke words at any
|
|
1050
|
+
letter before hyphenation got a chance. */
|
|
1051
|
+
.layout-navigation-content,
|
|
1052
|
+
.layout-page-sidebar-content,
|
|
1053
|
+
.layout-page-sidebar-content a {
|
|
1054
|
+
overflow-wrap: break-word;
|
|
1055
|
+
hyphens: auto;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
/* With every label wrapping, what still reaches past the navigation's
|
|
1059
|
+
edge is a compact chapter's resting tooltip (absolutely placed, and
|
|
1060
|
+
invisible): it would only add a sideways scrollbar. A showing tooltip is
|
|
1061
|
+
`position: fixed` (below), so this clip never cuts it. */
|
|
1062
|
+
.sidebar-pane {
|
|
1063
|
+
overflow-x: hidden;
|
|
624
1064
|
}
|
|
625
1065
|
|
|
626
1066
|
html[data-navigation-hidden] {
|
|
627
1067
|
--sl-content-inline-start: var(--layout-edge-rail-width);
|
|
1068
|
+
--layout-navigation-width: var(--layout-edge-rail-width);
|
|
628
1069
|
}
|
|
629
1070
|
|
|
630
1071
|
html[data-navigation-hidden] .sidebar-pane {
|
|
@@ -633,12 +1074,6 @@ body {
|
|
|
633
1074
|
transition: width 140ms ease;
|
|
634
1075
|
}
|
|
635
1076
|
|
|
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
1077
|
html[data-navigation-hidden] .layout-navigation-content {
|
|
643
1078
|
visibility: hidden;
|
|
644
1079
|
opacity: 0;
|
|
@@ -646,7 +1081,9 @@ body {
|
|
|
646
1081
|
transition: opacity 100ms ease;
|
|
647
1082
|
}
|
|
648
1083
|
|
|
649
|
-
html[data-navigation-hidden]
|
|
1084
|
+
html[data-navigation-hidden][data-navigation-peek-armed]:not(
|
|
1085
|
+
[data-navigation-peek-suppressed]
|
|
1086
|
+
)
|
|
650
1087
|
.sidebar-pane:hover {
|
|
651
1088
|
width: var(--sl-sidebar-width);
|
|
652
1089
|
overflow-y: auto;
|
|
@@ -654,13 +1091,37 @@ body {
|
|
|
654
1091
|
box-shadow: var(--sl-shadow-lg);
|
|
655
1092
|
}
|
|
656
1093
|
|
|
657
|
-
html[data-navigation-hidden]
|
|
1094
|
+
html[data-navigation-hidden][data-navigation-peek-armed]:not(
|
|
1095
|
+
[data-navigation-peek-suppressed]
|
|
1096
|
+
)
|
|
658
1097
|
.sidebar-pane:hover
|
|
659
1098
|
.layout-navigation-content {
|
|
660
1099
|
visibility: visible;
|
|
661
1100
|
opacity: 1;
|
|
662
1101
|
pointer-events: auto;
|
|
663
1102
|
}
|
|
1103
|
+
|
|
1104
|
+
/* While the panel peeks open over the article, the control reaches across
|
|
1105
|
+
to the separator the open panel would put there — it does not travel to
|
|
1106
|
+
it. A reader aiming at the control is hovering the rail, which is what
|
|
1107
|
+
triggers the peek in the first place; moving the control at that moment
|
|
1108
|
+
takes it out from under the pointer that was coming for it, and the
|
|
1109
|
+
reader has to chase it across the panel. Growing instead keeps its outer
|
|
1110
|
+
edge, and the glyph inside it, exactly where the pointer found them,
|
|
1111
|
+
while its inner end still shows where the control will settle. The width
|
|
1112
|
+
is a length, like the panel's own, so the two animate in step. */
|
|
1113
|
+
html[data-navigation-hidden][data-navigation-peek-armed]:not(
|
|
1114
|
+
[data-navigation-peek-suppressed]
|
|
1115
|
+
)
|
|
1116
|
+
.sidebar-pane:hover
|
|
1117
|
+
.layout-navigation-toggle {
|
|
1118
|
+
place-items: center start;
|
|
1119
|
+
width: calc(
|
|
1120
|
+
var(--sl-sidebar-width) - var(--layout-edge-rail-width) +
|
|
1121
|
+
var(--layout-edge-toggle-width)
|
|
1122
|
+
);
|
|
1123
|
+
transition: width 140ms ease;
|
|
1124
|
+
}
|
|
664
1125
|
}
|
|
665
1126
|
|
|
666
1127
|
@media (min-width: 72rem) {
|
|
@@ -746,14 +1207,53 @@ body {
|
|
|
746
1207
|
.layout-page-sidebar {
|
|
747
1208
|
position: relative;
|
|
748
1209
|
min-height: 100%;
|
|
749
|
-
padding-block-start:
|
|
1210
|
+
padding-block-start: var(--layout-edge-toggle-reserve);
|
|
750
1211
|
}
|
|
751
1212
|
|
|
1213
|
+
/* `.right-sidebar` is `position: fixed` with `padding-top:
|
|
1214
|
+
var(--sl-nav-height)`, so this panel's own top edge is already the
|
|
1215
|
+
underside of the header: the same gap here puts this control at exactly
|
|
1216
|
+
the block start the navigation's fixed control computes. */
|
|
752
1217
|
.layout-contents-toggle {
|
|
753
1218
|
position: absolute;
|
|
754
1219
|
z-index: 1;
|
|
755
|
-
inset-block-start:
|
|
756
|
-
inset-inline-start:
|
|
1220
|
+
inset-block-start: var(--layout-edge-toggle-gap);
|
|
1221
|
+
inset-inline-start: var(--layout-edge-toggle-gap);
|
|
1222
|
+
border-radius: 0 0 var(--layout-edge-toggle-radius) 0;
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
[dir='rtl'] .layout-contents-toggle {
|
|
1226
|
+
border-radius: 0 0 0 var(--layout-edge-toggle-radius);
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
.layout-contents-resizer {
|
|
1230
|
+
position: fixed;
|
|
1231
|
+
z-index: calc(var(--sl-z-index-toc) + 1);
|
|
1232
|
+
inset-block: var(--sl-nav-height) 0;
|
|
1233
|
+
inset-inline-end: calc(
|
|
1234
|
+
var(--layout-contents-width, var(--toc-actual-width, 0px)) - 1px
|
|
1235
|
+
);
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
/* A width the reader set replaces the shrink-to-fit rail above. The
|
|
1239
|
+
`:not()` keeps this out of the collapsed state's way, which owns the
|
|
1240
|
+
same declaration at the same specificity. */
|
|
1241
|
+
html[data-contents-resized]:not([data-page-sidebar-hidden])
|
|
1242
|
+
.right-sidebar-container,
|
|
1243
|
+
html[data-contents-resized]:not([data-page-sidebar-hidden]) .right-sidebar {
|
|
1244
|
+
width: var(--layout-contents-width);
|
|
1245
|
+
max-width: none;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
/* Starlight sizes the column inside from the navigation's width
|
|
1249
|
+
(`--sl-sidebar-width`), not from this panel: in a panel the reader set,
|
|
1250
|
+
it fills the panel, so its headings wrap at the panel's edge instead of
|
|
1251
|
+
running past it. */
|
|
1252
|
+
html[data-contents-resized]:not([data-page-sidebar-hidden])
|
|
1253
|
+
.right-sidebar-panel
|
|
1254
|
+
.sl-container {
|
|
1255
|
+
width: auto;
|
|
1256
|
+
max-width: none;
|
|
757
1257
|
}
|
|
758
1258
|
|
|
759
1259
|
html[data-page-sidebar-hidden] {
|
|
@@ -764,15 +1264,6 @@ body {
|
|
|
764
1264
|
width: var(--layout-edge-rail-width);
|
|
765
1265
|
}
|
|
766
1266
|
|
|
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
1267
|
html[data-page-sidebar-hidden] .right-sidebar {
|
|
777
1268
|
z-index: var(--sl-z-index-toc);
|
|
778
1269
|
inset-inline-start: auto;
|
|
@@ -794,7 +1285,9 @@ body {
|
|
|
794
1285
|
transition: opacity 100ms ease;
|
|
795
1286
|
}
|
|
796
1287
|
|
|
797
|
-
html[data-page-sidebar-hidden]
|
|
1288
|
+
html[data-page-sidebar-hidden][data-page-sidebar-peek-armed]:not(
|
|
1289
|
+
[data-page-sidebar-peek-suppressed]
|
|
1290
|
+
)
|
|
798
1291
|
.right-sidebar:hover {
|
|
799
1292
|
width: max-content;
|
|
800
1293
|
max-width: 80ch;
|
|
@@ -802,13 +1295,32 @@ body {
|
|
|
802
1295
|
box-shadow: var(--sl-shadow-lg);
|
|
803
1296
|
}
|
|
804
1297
|
|
|
805
|
-
html[data-page-sidebar-hidden]
|
|
1298
|
+
html[data-page-sidebar-hidden][data-page-sidebar-peek-armed]:not(
|
|
1299
|
+
[data-page-sidebar-peek-suppressed]
|
|
1300
|
+
)
|
|
806
1301
|
.right-sidebar:hover
|
|
807
1302
|
.layout-page-sidebar-content {
|
|
808
1303
|
visibility: visible;
|
|
809
1304
|
opacity: 1;
|
|
810
1305
|
pointer-events: auto;
|
|
811
1306
|
}
|
|
1307
|
+
|
|
1308
|
+
/* The same growth, mirrored. This control is positioned inside its panel,
|
|
1309
|
+
so a peek drags it inward with the panel's own edge unless its outer edge
|
|
1310
|
+
is pinned to where the rail put it; with both insets set, the box grows
|
|
1311
|
+
to meet the separator on its own. */
|
|
1312
|
+
html[data-page-sidebar-hidden][data-page-sidebar-peek-armed]:not(
|
|
1313
|
+
[data-page-sidebar-peek-suppressed]
|
|
1314
|
+
)
|
|
1315
|
+
.right-sidebar:hover
|
|
1316
|
+
.layout-contents-toggle {
|
|
1317
|
+
place-items: center end;
|
|
1318
|
+
inset-inline-end: calc(
|
|
1319
|
+
var(--layout-edge-rail-width) - var(--layout-edge-toggle-width) -
|
|
1320
|
+
var(--layout-edge-toggle-gap) - 1px
|
|
1321
|
+
);
|
|
1322
|
+
width: auto;
|
|
1323
|
+
}
|
|
812
1324
|
}
|
|
813
1325
|
|
|
814
1326
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -820,6 +1332,162 @@ body {
|
|
|
820
1332
|
}
|
|
821
1333
|
}
|
|
822
1334
|
|
|
1335
|
+
/* The side column's room (rule S3 of docs/plans/hover-card-consistency.md):
|
|
1336
|
+
while explanation cards sit to the right of the article, the article
|
|
1337
|
+
slides left through its own start margin, which `card-side.ts` computes
|
|
1338
|
+
and hands over as `--explico-article-start`. `.main-pane` keeps its width
|
|
1339
|
+
and the rail stays where it is. `:root` outranks the `html[…] .main-pane`
|
|
1340
|
+
rules above that centre the article; `screen` keeps the slide off paper.
|
|
1341
|
+
The slide's animation is a transform the card manager runs, so this
|
|
1342
|
+
margin is always the final one. */
|
|
1343
|
+
@media screen and (min-width: 72rem) {
|
|
1344
|
+
:root[data-article-slid] .main-pane {
|
|
1345
|
+
--sl-content-margin-inline: var(--explico-article-start, 0px) auto;
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
/* Both side panels sit above the explanation cards, whose layer takes the
|
|
1350
|
+
header's level just before `.page` (`card-placement.ts`): an open panel is
|
|
1351
|
+
never covered — a reader who needs its room collapses it — and a collapsed
|
|
1352
|
+
one peeks open over the cards. Each panel's controls live inside it, so
|
|
1353
|
+
they rise with it. The header outranks both: the rail's box starts at the
|
|
1354
|
+
window's top, under the header. An expanded table or diagram covers the
|
|
1355
|
+
panels, and the cards opened from inside it must cover it, so while one is
|
|
1356
|
+
open the panels drop back to Starlight's own levels. */
|
|
1357
|
+
.header {
|
|
1358
|
+
z-index: calc(var(--sl-z-index-navbar) + 1);
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
/* A slimmer site header: 3rem at every width, where Starlight's is 3.5rem
|
|
1362
|
+
and 4rem from 50rem up. The title, the logo (sized from the height and
|
|
1363
|
+
padding) and the search box scale with it, so more of the window goes to
|
|
1364
|
+
the lesson, and to the cards and side column under the header.
|
|
1365
|
+
Everything that sits under the header reads `--sl-nav-height`. */
|
|
1366
|
+
:root {
|
|
1367
|
+
--sl-nav-height: 3rem;
|
|
1368
|
+
--sl-nav-pad-y: 0.5rem;
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
.site-title {
|
|
1372
|
+
font-size: var(--sl-text-xl);
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
@media (min-width: 50rem) {
|
|
1376
|
+
button[data-open-modal] {
|
|
1377
|
+
height: 2rem;
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
@media (min-width: 50rem) {
|
|
1382
|
+
:root .sidebar-pane {
|
|
1383
|
+
z-index: var(--sl-z-index-navbar);
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
@media (min-width: 72rem) {
|
|
1388
|
+
:root .right-sidebar,
|
|
1389
|
+
:root[data-page-sidebar-hidden] .right-sidebar {
|
|
1390
|
+
z-index: var(--sl-z-index-navbar);
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
:root:has(.table-overflow-expanded, .diagram-is-expanded) .sidebar-pane {
|
|
1395
|
+
z-index: var(--sl-z-index-menu);
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
:root:has(.table-overflow-expanded, .diagram-is-expanded) .right-sidebar {
|
|
1399
|
+
z-index: var(--sl-z-index-toc);
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
/* S9: "Keep the article left", fixed at the top of the side column just
|
|
1403
|
+
under the header, over the cards scrolling past it. `card-side.ts` sets
|
|
1404
|
+
its `left`. */
|
|
1405
|
+
.explico-keep-left {
|
|
1406
|
+
position: fixed;
|
|
1407
|
+
z-index: var(--sl-z-index-navbar);
|
|
1408
|
+
top: calc(var(--sl-nav-height) + 0.5rem);
|
|
1409
|
+
display: inline-flex;
|
|
1410
|
+
align-items: center;
|
|
1411
|
+
gap: 0.45rem;
|
|
1412
|
+
margin: 0;
|
|
1413
|
+
padding: 0.2rem 0.65rem 0.2rem 0.4rem;
|
|
1414
|
+
border: var(--ex-edge-border);
|
|
1415
|
+
border-radius: 999px;
|
|
1416
|
+
font: inherit;
|
|
1417
|
+
font-size: var(--sl-text-xs);
|
|
1418
|
+
line-height: 1.4;
|
|
1419
|
+
color: var(--sl-color-gray-2);
|
|
1420
|
+
background: var(--sl-color-bg);
|
|
1421
|
+
box-shadow: var(--sl-shadow-sm);
|
|
1422
|
+
cursor: pointer;
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
.explico-keep-left[hidden] {
|
|
1426
|
+
display: none;
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
.explico-keep-left:hover {
|
|
1430
|
+
color: var(--sl-color-text);
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
.explico-keep-left:focus-visible {
|
|
1434
|
+
outline: 3px solid var(--sl-color-accent);
|
|
1435
|
+
outline-offset: 2px;
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
.explico-keep-left-switch {
|
|
1439
|
+
position: relative;
|
|
1440
|
+
flex: none;
|
|
1441
|
+
width: 1.75em;
|
|
1442
|
+
height: 1em;
|
|
1443
|
+
border-radius: 999px;
|
|
1444
|
+
background: var(--sl-color-gray-4);
|
|
1445
|
+
transition: background-color 100ms ease;
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
.explico-keep-left-switch::after {
|
|
1449
|
+
content: '';
|
|
1450
|
+
position: absolute;
|
|
1451
|
+
top: 0.125em;
|
|
1452
|
+
left: 0.125em;
|
|
1453
|
+
width: 0.75em;
|
|
1454
|
+
height: 0.75em;
|
|
1455
|
+
border-radius: 50%;
|
|
1456
|
+
background: var(--sl-color-bg);
|
|
1457
|
+
transition: transform 100ms ease;
|
|
1458
|
+
}
|
|
1459
|
+
|
|
1460
|
+
.explico-keep-left[aria-pressed='true'] .explico-keep-left-switch {
|
|
1461
|
+
background: var(--sl-color-accent);
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
.explico-keep-left[aria-pressed='true'] .explico-keep-left-switch::after {
|
|
1465
|
+
transform: translateX(0.75em);
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1469
|
+
.explico-keep-left-switch,
|
|
1470
|
+
.explico-keep-left-switch::after {
|
|
1471
|
+
transition: none;
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
@media (forced-colors: active) {
|
|
1476
|
+
.explico-keep-left-switch {
|
|
1477
|
+
border: 1px solid ButtonText;
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
.explico-keep-left[aria-pressed='true'] .explico-keep-left-switch {
|
|
1481
|
+
background: Highlight;
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
@media print {
|
|
1486
|
+
.explico-keep-left {
|
|
1487
|
+
display: none !important;
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
|
|
823
1491
|
/* Source citations: inline `[n]` markers and the end-of-page reference list
|
|
824
1492
|
emitted by the remark-citation adapter. The hover/pin panel is styled in
|
|
825
1493
|
the CitationLayer island. */
|
|
@@ -1270,61 +1938,217 @@ body {
|
|
|
1270
1938
|
}
|
|
1271
1939
|
}
|
|
1272
1940
|
|
|
1273
|
-
.sl-markdown-content .keyed-equation:target {
|
|
1274
|
-
animation: eq-flash 5s ease-out both;
|
|
1941
|
+
.sl-markdown-content .keyed-equation:target {
|
|
1942
|
+
animation: eq-flash 5s ease-out both;
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1945
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1946
|
+
.sl-markdown-content .keyed-equation:target {
|
|
1947
|
+
animation: none;
|
|
1948
|
+
background: var(--sl-color-accent-low);
|
|
1949
|
+
outline: 2px solid var(--sl-color-accent);
|
|
1950
|
+
outline-offset: 0.2rem;
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
@media (forced-colors: active) {
|
|
1955
|
+
.sl-markdown-content .keyed-equation:target {
|
|
1956
|
+
animation: none;
|
|
1957
|
+
outline: 2px solid Highlight;
|
|
1958
|
+
outline-offset: 0.2rem;
|
|
1959
|
+
}
|
|
1960
|
+
.sl-markdown-content a.equation-ref:hover,
|
|
1961
|
+
.sl-markdown-content a.equation-ref:focus-visible {
|
|
1962
|
+
outline: 2px solid Highlight;
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1966
|
+
@media print {
|
|
1967
|
+
.sl-markdown-content .keyed-equation__controls {
|
|
1968
|
+
position: static;
|
|
1969
|
+
display: block;
|
|
1970
|
+
transform: none;
|
|
1971
|
+
text-align: end;
|
|
1972
|
+
}
|
|
1973
|
+
.sl-markdown-content a.keyed-equation__number {
|
|
1974
|
+
color: inherit;
|
|
1975
|
+
opacity: 1;
|
|
1976
|
+
}
|
|
1977
|
+
/* A clipboard button means nothing on paper. */
|
|
1978
|
+
.sl-markdown-content .keyed-equation__copy {
|
|
1979
|
+
display: none;
|
|
1980
|
+
}
|
|
1981
|
+
.sl-markdown-content .keyed-equation {
|
|
1982
|
+
padding-inline-end: 0;
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
|
|
1986
|
+
/* One caption line for every float (docs/plans/titles-and-containers.md
|
|
1987
|
+
Part 3): `Figure 2.2.1 [chain] ‹caption›` — the number links to the float,
|
|
1988
|
+
the chain icon copies that link (`HeadingAnchorEnhancer.astro`), the
|
|
1989
|
+
caption is the float's one long caption. A figure and a diagram put it
|
|
1990
|
+
below the picture (`FloatCaption.astro`), a table above it, the LaTeX
|
|
1991
|
+
convention. The line never hides (docs/plans/figures-and-short-captions.md,
|
|
1992
|
+
decision 1); its buttons sit at its end (`.float-tools`, below). */
|
|
1993
|
+
.sl-markdown-content .float-caption {
|
|
1994
|
+
/* Anchors the button row (`.float-tools`) to the line's end. */
|
|
1995
|
+
position: relative;
|
|
1996
|
+
margin-block: 0.5rem 0;
|
|
1997
|
+
font-size: var(--sl-text-sm);
|
|
1998
|
+
line-height: 1.5;
|
|
1999
|
+
color: var(--sl-color-gray-3);
|
|
2000
|
+
break-before: avoid-page;
|
|
2001
|
+
}
|
|
2002
|
+
|
|
2003
|
+
.sl-markdown-content .keyed-table > .float-caption {
|
|
2004
|
+
margin-block: 0 0.5rem;
|
|
2005
|
+
break-before: auto;
|
|
2006
|
+
break-after: avoid-page;
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
/* A float's buttons sit together at the top right of its caption line, in
|
|
2010
|
+
one boxed style, always visible: a table's widen ↔ (the same action as
|
|
2011
|
+
the column at its right edge) and its fold ⌃ / ⌄, a diagram's widen ↔.
|
|
2012
|
+
The caption's text keeps clear of a shown one. A table's scripts add the
|
|
2013
|
+
row (`Table.astro`, `TableOverflowExpander.astro`), whichever runs first;
|
|
2014
|
+
a figure's or a diagram's is rendered by `FloatCaption.astro`. */
|
|
2015
|
+
.sl-markdown-content .float-tools {
|
|
2016
|
+
position: absolute;
|
|
2017
|
+
inset-block-start: 0;
|
|
2018
|
+
inset-inline-end: 0;
|
|
2019
|
+
display: inline-flex;
|
|
2020
|
+
gap: 0.25rem;
|
|
2021
|
+
}
|
|
2022
|
+
|
|
2023
|
+
.sl-markdown-content .float-caption:has(> .float-tools > .float-tool:not([hidden])) {
|
|
2024
|
+
padding-inline-end: 2.25rem;
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2027
|
+
.sl-markdown-content
|
|
2028
|
+
.float-caption:has(> .float-tools > .float-tool:not([hidden]) ~ .float-tool:not([hidden])) {
|
|
2029
|
+
padding-inline-end: 4.25rem;
|
|
2030
|
+
}
|
|
2031
|
+
|
|
2032
|
+
.sl-markdown-content .float-tool {
|
|
2033
|
+
display: inline-grid;
|
|
2034
|
+
place-items: center;
|
|
2035
|
+
width: 1.75rem;
|
|
2036
|
+
height: 1.5rem;
|
|
2037
|
+
margin: 0;
|
|
2038
|
+
padding: 0;
|
|
2039
|
+
border: 1px solid var(--sl-color-gray-5);
|
|
2040
|
+
border-radius: 0.3rem;
|
|
2041
|
+
background: var(--sl-color-bg);
|
|
2042
|
+
color: var(--sl-color-gray-2);
|
|
2043
|
+
cursor: pointer;
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2046
|
+
.sl-markdown-content .float-tool[hidden] {
|
|
2047
|
+
display: none;
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2050
|
+
.sl-markdown-content .float-tool svg {
|
|
2051
|
+
width: 0.875rem;
|
|
2052
|
+
height: 0.875rem;
|
|
2053
|
+
fill: none;
|
|
2054
|
+
stroke: currentColor;
|
|
2055
|
+
stroke-width: 2.2;
|
|
2056
|
+
stroke-linecap: round;
|
|
2057
|
+
stroke-linejoin: round;
|
|
2058
|
+
}
|
|
2059
|
+
|
|
2060
|
+
.sl-markdown-content .float-tool:hover {
|
|
2061
|
+
color: var(--sl-color-text-accent);
|
|
2062
|
+
border-color: var(--sl-color-text-accent);
|
|
2063
|
+
}
|
|
2064
|
+
|
|
2065
|
+
.sl-markdown-content .float-tool:focus-visible {
|
|
2066
|
+
outline: 2px solid var(--sl-color-accent);
|
|
2067
|
+
outline-offset: 1px;
|
|
2068
|
+
}
|
|
2069
|
+
|
|
2070
|
+
/* The widen button's two faces: ↔ widens, →← brings the float back. */
|
|
2071
|
+
.sl-markdown-content .float-tool[aria-expanded='true'] .float-tool__widen,
|
|
2072
|
+
.sl-markdown-content .float-tool[aria-expanded='false'] .float-tool__narrow {
|
|
2073
|
+
display: none;
|
|
1275
2074
|
}
|
|
1276
2075
|
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
outline-offset: 0.2rem;
|
|
1283
|
-
}
|
|
2076
|
+
/* The fold button's two faces, for a lab's tools (`Figure.astro`): ⌃ folds
|
|
2077
|
+
them away, ⌄ brings them back. A table's toggle swaps its icon instead. */
|
|
2078
|
+
.sl-markdown-content .float-tool[aria-expanded='true'] .float-tool__unfold,
|
|
2079
|
+
.sl-markdown-content .float-tool[aria-expanded='false'] .float-tool__fold {
|
|
2080
|
+
display: none;
|
|
1284
2081
|
}
|
|
1285
2082
|
|
|
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
|
-
}
|
|
2083
|
+
/* The caption line's live end: the case a lab's plot shows, after the long
|
|
2084
|
+
caption (`FloatCaption.astro`, `figure/figure-state.ts`). */
|
|
2085
|
+
.sl-markdown-content .float-caption__state:not(:empty) {
|
|
2086
|
+
margin-inline-start: 0.25em;
|
|
1296
2087
|
}
|
|
1297
2088
|
|
|
1298
2089
|
@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 {
|
|
2090
|
+
.sl-markdown-content .float-tools {
|
|
1311
2091
|
display: none;
|
|
1312
2092
|
}
|
|
1313
|
-
|
|
2093
|
+
|
|
2094
|
+
.sl-markdown-content .float-caption:has(> .float-tools) {
|
|
1314
2095
|
padding-inline-end: 0;
|
|
1315
2096
|
}
|
|
1316
2097
|
}
|
|
1317
2098
|
|
|
1318
|
-
/*
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
2099
|
+
/* A short caption opens the line as its bold title, the journal-legend
|
|
2100
|
+
style: "**Sampled flight data.** Position, …" (`FloatCaption.astro`,
|
|
2101
|
+
`Table.astro`; docs/plans/figures-and-short-captions.md, decision 9.1). */
|
|
2102
|
+
.sl-markdown-content .float-caption__title {
|
|
2103
|
+
color: var(--sl-color-text);
|
|
2104
|
+
font-weight: 600;
|
|
1324
2105
|
}
|
|
1325
2106
|
|
|
1326
|
-
.sl-markdown-content .
|
|
1327
|
-
|
|
2107
|
+
.sl-markdown-content .float-caption__number {
|
|
2108
|
+
font-weight: 600;
|
|
2109
|
+
font-variant-numeric: tabular-nums;
|
|
2110
|
+
color: var(--sl-color-text-accent);
|
|
2111
|
+
text-decoration: none;
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
.sl-markdown-content .float-caption__number:hover,
|
|
2115
|
+
.sl-markdown-content .float-caption__number:focus-visible {
|
|
2116
|
+
text-decoration: underline;
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
.sl-markdown-content .float-caption__anchor {
|
|
2120
|
+
display: inline-flex;
|
|
2121
|
+
width: 1.15em;
|
|
2122
|
+
height: 1.15em;
|
|
2123
|
+
margin-inline: 0.15em 0.3em;
|
|
2124
|
+
vertical-align: -0.2em;
|
|
2125
|
+
align-items: center;
|
|
2126
|
+
justify-content: center;
|
|
2127
|
+
color: var(--sl-color-gray-4);
|
|
2128
|
+
text-decoration: none;
|
|
2129
|
+
-webkit-user-select: none;
|
|
2130
|
+
user-select: none;
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
.sl-markdown-content .float-caption__anchor svg {
|
|
2134
|
+
width: 0.85em;
|
|
2135
|
+
height: 0.85em;
|
|
2136
|
+
}
|
|
2137
|
+
|
|
2138
|
+
.sl-markdown-content .float-caption__anchor:hover,
|
|
2139
|
+
.sl-markdown-content .float-caption__anchor:focus-visible {
|
|
2140
|
+
color: var(--sl-color-text-accent);
|
|
2141
|
+
}
|
|
2142
|
+
|
|
2143
|
+
.sl-markdown-content :is(.float-caption__number, .float-caption__anchor):focus-visible {
|
|
2144
|
+
outline: 2px solid var(--sl-color-accent);
|
|
2145
|
+
outline-offset: 0.15rem;
|
|
2146
|
+
}
|
|
2147
|
+
|
|
2148
|
+
@media print {
|
|
2149
|
+
.sl-markdown-content .float-caption__number {
|
|
2150
|
+
color: inherit;
|
|
2151
|
+
}
|
|
1328
2152
|
}
|
|
1329
2153
|
|
|
1330
2154
|
/* `<Table>`/`<Figure>`/`<Diagram>` keyed floats — the same deep-link
|
|
@@ -1346,12 +2170,36 @@ body {
|
|
|
1346
2170
|
white-space: nowrap;
|
|
1347
2171
|
}
|
|
1348
2172
|
|
|
2173
|
+
/* `[[sec-…]]` reads the same, but may print a section's title rather than
|
|
2174
|
+
`§ 1.1.2` (an unnumbered heading, or a course that hides section numbers),
|
|
2175
|
+
so it wraps like prose; the no-break space inside `§ 1.1.2` keeps that one
|
|
2176
|
+
whole. `[[check-…]]` and `[[ex-…]]` follow the section rules too
|
|
2177
|
+
(docs/plans/titles-and-containers.md Q11): a course that hides section
|
|
2178
|
+
numbers gets "Example “‹title›”". */
|
|
2179
|
+
.sl-markdown-content a.section-ref,
|
|
2180
|
+
.sl-markdown-content a.knowledge-check-ref,
|
|
2181
|
+
.sl-markdown-content a.example-ref {
|
|
2182
|
+
font-variant-numeric: tabular-nums;
|
|
2183
|
+
font-weight: 600;
|
|
2184
|
+
text-decoration: underline;
|
|
2185
|
+
text-underline-offset: 0.15em;
|
|
2186
|
+
padding-inline: 0.1em;
|
|
2187
|
+
border-radius: 0.2em;
|
|
2188
|
+
color: var(--sl-color-text-accent);
|
|
2189
|
+
}
|
|
2190
|
+
|
|
1349
2191
|
.sl-markdown-content a.table-ref:hover,
|
|
1350
2192
|
.sl-markdown-content a.table-ref:focus-visible,
|
|
1351
2193
|
.sl-markdown-content a.figure-ref:hover,
|
|
1352
2194
|
.sl-markdown-content a.figure-ref:focus-visible,
|
|
1353
2195
|
.sl-markdown-content a.diagram-ref:hover,
|
|
1354
|
-
.sl-markdown-content a.diagram-ref:focus-visible
|
|
2196
|
+
.sl-markdown-content a.diagram-ref:focus-visible,
|
|
2197
|
+
.sl-markdown-content a.section-ref:hover,
|
|
2198
|
+
.sl-markdown-content a.section-ref:focus-visible,
|
|
2199
|
+
.sl-markdown-content a.knowledge-check-ref:hover,
|
|
2200
|
+
.sl-markdown-content a.knowledge-check-ref:focus-visible,
|
|
2201
|
+
.sl-markdown-content a.example-ref:hover,
|
|
2202
|
+
.sl-markdown-content a.example-ref:focus-visible {
|
|
1355
2203
|
background: var(--sl-color-accent-low);
|
|
1356
2204
|
}
|
|
1357
2205
|
|
|
@@ -1373,13 +2221,34 @@ body {
|
|
|
1373
2221
|
}
|
|
1374
2222
|
}
|
|
1375
2223
|
|
|
2224
|
+
/* A reference whose target sits inside a closed memo or section opens a
|
|
2225
|
+
preview card, as if the target were off screen; while that card is open,
|
|
2226
|
+
the fold's bar is marked the same way, so the reader sees where the
|
|
2227
|
+
target lives (`FloatRefLayer.astro`). */
|
|
2228
|
+
.sl-markdown-content .float-ref-fold-hint {
|
|
2229
|
+
background: var(--sl-color-accent-low);
|
|
2230
|
+
outline: 2px solid var(--sl-color-accent);
|
|
2231
|
+
outline-offset: 0.2rem;
|
|
2232
|
+
border-radius: 0.3rem;
|
|
2233
|
+
transition:
|
|
2234
|
+
background 120ms ease-out,
|
|
2235
|
+
outline-color 120ms ease-out;
|
|
2236
|
+
}
|
|
2237
|
+
|
|
2238
|
+
@media (forced-colors: active) {
|
|
2239
|
+
.sl-markdown-content .float-ref-fold-hint {
|
|
2240
|
+
outline-color: Highlight;
|
|
2241
|
+
}
|
|
2242
|
+
}
|
|
2243
|
+
|
|
1376
2244
|
/* A referencing `[[tab-key]]`/`[[fig-key]]` link elsewhere in the prose was
|
|
1377
2245
|
hovered/focused and the float it points to is already fully on screen:
|
|
1378
2246
|
highlight it in place instead of opening a preview card
|
|
1379
2247
|
(`FloatRefLayer.astro` decides which) — mirrors `.eq-ref-highlight`. */
|
|
1380
2248
|
.sl-markdown-content .keyed-table.tab-ref-highlight,
|
|
1381
2249
|
.sl-markdown-content .keyed-figure.fig-ref-highlight,
|
|
1382
|
-
.sl-markdown-content .diagram.dia-ref-highlight
|
|
2250
|
+
.sl-markdown-content .diagram.dia-ref-highlight,
|
|
2251
|
+
.sl-markdown-content :is(h2, h3, h4, h5, h6).sec-ref-highlight {
|
|
1383
2252
|
background: var(--sl-color-accent-low);
|
|
1384
2253
|
outline: 2px solid var(--sl-color-accent);
|
|
1385
2254
|
outline-offset: 0.2rem;
|
|
@@ -1395,7 +2264,8 @@ body {
|
|
|
1395
2264
|
.sl-markdown-content .diagram:target,
|
|
1396
2265
|
.sl-markdown-content .keyed-table.tab-ref-highlight,
|
|
1397
2266
|
.sl-markdown-content .keyed-figure.fig-ref-highlight,
|
|
1398
|
-
.sl-markdown-content .diagram.dia-ref-highlight
|
|
2267
|
+
.sl-markdown-content .diagram.dia-ref-highlight,
|
|
2268
|
+
.sl-markdown-content :is(h2, h3, h4, h5, h6).sec-ref-highlight {
|
|
1399
2269
|
animation: none;
|
|
1400
2270
|
outline: 2px solid Highlight;
|
|
1401
2271
|
outline-offset: 0.2rem;
|
|
@@ -1405,7 +2275,13 @@ body {
|
|
|
1405
2275
|
.sl-markdown-content a.figure-ref:hover,
|
|
1406
2276
|
.sl-markdown-content a.figure-ref:focus-visible,
|
|
1407
2277
|
.sl-markdown-content a.diagram-ref:hover,
|
|
1408
|
-
.sl-markdown-content a.diagram-ref:focus-visible
|
|
2278
|
+
.sl-markdown-content a.diagram-ref:focus-visible,
|
|
2279
|
+
.sl-markdown-content a.section-ref:hover,
|
|
2280
|
+
.sl-markdown-content a.section-ref:focus-visible,
|
|
2281
|
+
.sl-markdown-content a.knowledge-check-ref:hover,
|
|
2282
|
+
.sl-markdown-content a.knowledge-check-ref:focus-visible,
|
|
2283
|
+
.sl-markdown-content a.example-ref:hover,
|
|
2284
|
+
.sl-markdown-content a.example-ref:focus-visible {
|
|
1409
2285
|
outline: 2px solid Highlight;
|
|
1410
2286
|
}
|
|
1411
2287
|
}
|
|
@@ -1463,6 +2339,197 @@ body {
|
|
|
1463
2339
|
}
|
|
1464
2340
|
}
|
|
1465
2341
|
|
|
2342
|
+
/* Outline numbers (docs/plans/titles-and-containers.md Part 1). A lesson's
|
|
2343
|
+
numbered heading carries `data-sec-number="1.1.2"` (`remark-notation.mjs`,
|
|
2344
|
+
from the manifest), printed here ahead of the title as generated content —
|
|
2345
|
+
so the heading's own text, its anchor and the "On this page" entry stay the
|
|
2346
|
+
title alone. The number shows on a wide screen and in print; on a narrow one
|
|
2347
|
+
only on a collapsed section's bar, which says what is folded away, and in
|
|
2348
|
+
the chain icon's "Link copied · § 1.1.2". The en space is part of the
|
|
2349
|
+
content, not a margin, so a screen reader hears "1.1.2 Title", not
|
|
2350
|
+
"1.1.2Title". */
|
|
2351
|
+
.sl-markdown-content [data-sec-number]::before {
|
|
2352
|
+
content: attr(data-sec-number) '\2002';
|
|
2353
|
+
color: var(--sl-color-text-accent);
|
|
2354
|
+
font-variant-numeric: tabular-nums;
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2357
|
+
@media screen and (width < 50em) {
|
|
2358
|
+
.sl-markdown-content [data-sec-number]::before {
|
|
2359
|
+
content: none;
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
.sl-markdown-content
|
|
2363
|
+
details.sl-section-collapsible:not([data-state='open'])
|
|
2364
|
+
> .sl-section-summary
|
|
2365
|
+
> [data-sec-number]::before {
|
|
2366
|
+
content: attr(data-sec-number) '\2002';
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
|
|
2370
|
+
@media print {
|
|
2371
|
+
.sl-markdown-content [data-sec-number]::before {
|
|
2372
|
+
color: inherit;
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
|
|
2376
|
+
/* Kind badges (Part 6): the `<h2>` a knowledge check and a worked-example set
|
|
2377
|
+
draw (`BlockHeading.astro`). The kind's icon leads the author's title, as
|
|
2378
|
+
it does in "On this page"; the kind's word and the block's number are a
|
|
2379
|
+
small label in the card's top-right corner, inside its top padding. The
|
|
2380
|
+
label is out of the text flow, so the title keeps the whole line at every
|
|
2381
|
+
width and still wraps word by word, and the number reads as the block's
|
|
2382
|
+
label rather than as a section number. `data-labels="icon"` keeps the word
|
|
2383
|
+
for a screen reader only (`sr-only`). The card's padding is set for it
|
|
2384
|
+
below; `--block-label-lift` is how far the label sits above the title's
|
|
2385
|
+
line box, measured from the card's inner top edge. */
|
|
2386
|
+
.sl-markdown-content .ex-section-card:has(> .block-heading-wrapper) {
|
|
2387
|
+
--block-label-lift: 1.25rem;
|
|
2388
|
+
padding-block-start: var(--block-label-lift);
|
|
2389
|
+
}
|
|
2390
|
+
|
|
2391
|
+
.sl-markdown-content .block-heading-wrapper {
|
|
2392
|
+
position: relative;
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
.sl-markdown-content .block-heading {
|
|
2396
|
+
/* A wrapped title's later lines start under its first word, not under
|
|
2397
|
+
the icon. */
|
|
2398
|
+
padding-inline-start: 1.1em;
|
|
2399
|
+
text-indent: -1.1em;
|
|
2400
|
+
}
|
|
2401
|
+
|
|
2402
|
+
.sl-markdown-content .block-heading__icon {
|
|
2403
|
+
display: inline-block;
|
|
2404
|
+
width: 0.8em;
|
|
2405
|
+
height: 0.8em;
|
|
2406
|
+
margin-inline-end: 0.3em;
|
|
2407
|
+
vertical-align: -0.06em;
|
|
2408
|
+
color: var(--sl-color-text-accent);
|
|
2409
|
+
}
|
|
2410
|
+
|
|
2411
|
+
.sl-markdown-content .block-badge {
|
|
2412
|
+
position: absolute;
|
|
2413
|
+
inset-block-start: calc(0.3rem - var(--block-label-lift, 1.25rem));
|
|
2414
|
+
inset-inline-end: 0;
|
|
2415
|
+
color: var(--sl-color-text-accent);
|
|
2416
|
+
font-size: 0.75rem;
|
|
2417
|
+
font-weight: 600;
|
|
2418
|
+
letter-spacing: 0.05em;
|
|
2419
|
+
line-height: 1.2;
|
|
2420
|
+
text-indent: 0;
|
|
2421
|
+
text-transform: uppercase;
|
|
2422
|
+
white-space: nowrap;
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2425
|
+
/* Narrow and touch screens set the heading inline beside the section's
|
|
2426
|
+
chevron, with the summary's own hanging indent (below); the heading's
|
|
2427
|
+
indent above would double it. */
|
|
2428
|
+
@media screen and (width < 50em), screen and (hover: none) {
|
|
2429
|
+
.sl-markdown-content .block-heading {
|
|
2430
|
+
padding-inline-start: 0;
|
|
2431
|
+
text-indent: 0;
|
|
2432
|
+
}
|
|
2433
|
+
}
|
|
2434
|
+
|
|
2435
|
+
/* The number follows the section numbers' rules above (Q11): shown on a wide
|
|
2436
|
+
screen and in print; on a narrow one only on a folded bar, and in the chain
|
|
2437
|
+
icon's "Link copied · Example 1.1.1". Real text, so the heading's name reads
|
|
2438
|
+
"Example 1.1.1 ‹title›" wherever it shows. */
|
|
2439
|
+
.sl-markdown-content .block-heading__number {
|
|
2440
|
+
color: var(--sl-color-text-accent);
|
|
2441
|
+
font-variant-numeric: tabular-nums;
|
|
2442
|
+
}
|
|
2443
|
+
|
|
2444
|
+
@media screen and (width < 50em) {
|
|
2445
|
+
.sl-markdown-content .block-heading__number {
|
|
2446
|
+
display: none;
|
|
2447
|
+
}
|
|
2448
|
+
|
|
2449
|
+
.sl-markdown-content
|
|
2450
|
+
details.sl-section-collapsible:not([data-state='open'])
|
|
2451
|
+
> .sl-section-summary
|
|
2452
|
+
> .block-heading
|
|
2453
|
+
.block-heading__number {
|
|
2454
|
+
display: inline;
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
|
|
2458
|
+
@media print {
|
|
2459
|
+
.sl-markdown-content .block-heading__number {
|
|
2460
|
+
color: inherit;
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
|
|
2464
|
+
/* "On this page" lists a check and an example set by its title alone, as it
|
|
2465
|
+
lists a section; the badge's icon before the title says which kind it is
|
|
2466
|
+
(`LayoutPageSidebar.astro` marks the link `data-block-kind`). A mask, so
|
|
2467
|
+
the icon takes the link's colour, current and hovered alike. */
|
|
2468
|
+
:is(starlight-toc, mobile-starlight-toc) a[data-block-kind]::before {
|
|
2469
|
+
content: '';
|
|
2470
|
+
display: inline-block;
|
|
2471
|
+
width: 0.95em;
|
|
2472
|
+
height: 0.95em;
|
|
2473
|
+
margin-inline-end: 0.35em;
|
|
2474
|
+
vertical-align: -0.12em;
|
|
2475
|
+
background-color: currentColor;
|
|
2476
|
+
mask: var(--block-kind-icon) center / contain no-repeat;
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2479
|
+
:is(starlight-toc, mobile-starlight-toc) a[data-block-kind='check'] {
|
|
2480
|
+
--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");
|
|
2481
|
+
}
|
|
2482
|
+
|
|
2483
|
+
:is(starlight-toc, mobile-starlight-toc) a[data-block-kind='example'] {
|
|
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='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");
|
|
2485
|
+
}
|
|
2486
|
+
|
|
2487
|
+
/* "Link copied · § 1.1.2" — `HeadingAnchorEnhancer.astro` places it under the
|
|
2488
|
+
title in page coordinates, clamped to the text column, and removes it
|
|
2489
|
+
after a moment; the same accent chip as an equation's "Copied!", with an
|
|
2490
|
+
edge and a shadow because the section behind it is flashing the same
|
|
2491
|
+
accent tint. */
|
|
2492
|
+
.sl-anchor-copied {
|
|
2493
|
+
position: absolute;
|
|
2494
|
+
z-index: 30;
|
|
2495
|
+
padding: 0.15rem 0.5rem;
|
|
2496
|
+
border: 1px solid var(--sl-color-accent);
|
|
2497
|
+
border-radius: 0.35rem;
|
|
2498
|
+
box-shadow: 0 0.2rem 0.6rem rgba(0, 0, 0, 0.15);
|
|
2499
|
+
background: var(--sl-color-accent-low);
|
|
2500
|
+
color: var(--sl-color-text-accent);
|
|
2501
|
+
font-size: var(--sl-text-xs);
|
|
2502
|
+
line-height: 1.5;
|
|
2503
|
+
/* One line for a short name; a long title wraps inside the cap, never
|
|
2504
|
+
wider than the column (the script keeps it inside the column). */
|
|
2505
|
+
width: max-content;
|
|
2506
|
+
max-width: min(28rem, calc(100vw - 2rem));
|
|
2507
|
+
pointer-events: none;
|
|
2508
|
+
animation: sl-anchor-copied 1.8s ease both;
|
|
2509
|
+
}
|
|
2510
|
+
|
|
2511
|
+
@keyframes sl-anchor-copied {
|
|
2512
|
+
0%,
|
|
2513
|
+
75% {
|
|
2514
|
+
opacity: 1;
|
|
2515
|
+
}
|
|
2516
|
+
100% {
|
|
2517
|
+
opacity: 0;
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
|
|
2521
|
+
@media (prefers-reduced-motion: reduce) {
|
|
2522
|
+
.sl-anchor-copied {
|
|
2523
|
+
animation: none;
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
|
|
2527
|
+
@media print {
|
|
2528
|
+
.sl-anchor-copied {
|
|
2529
|
+
display: none;
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
|
|
1466
2533
|
/* Collapsible sections (docs/plans/collapsible-disclosure.md Part 3),
|
|
1467
2534
|
wrapped at runtime by `CollapsibleSections.astro` around headings an
|
|
1468
2535
|
author opted in with `{collapsible}`. Starlight's own `markdown.css` gives
|
|
@@ -1535,13 +2602,21 @@ body {
|
|
|
1535
2602
|
never satisfies this selector. Both rules are unlayered, so they win over
|
|
1536
2603
|
`anchor-links.css`'s `@layer starlight.content` version regardless of
|
|
1537
2604
|
specificity — this replaces that default behavior for sections rather
|
|
1538
|
-
than adding to it.
|
|
2605
|
+
than adding to it. Like Starlight's own rule, the icon hides only where a
|
|
2606
|
+
hover can reveal it: on a touch screen it stays visible, since it is a
|
|
2607
|
+
real tap target at the end of the title line either way (an invisible one
|
|
2608
|
+
used to take a tap meant for the title and change the URL instead). */
|
|
1539
2609
|
.sl-markdown-content .sl-heading-wrapper.sl-section-titlebar > .sl-anchor-link {
|
|
1540
2610
|
position: absolute;
|
|
1541
2611
|
top: 0.2em;
|
|
1542
2612
|
inset-inline-end: 0;
|
|
1543
2613
|
margin-inline-start: 0;
|
|
1544
|
-
|
|
2614
|
+
}
|
|
2615
|
+
|
|
2616
|
+
@media (hover: hover) {
|
|
2617
|
+
.sl-markdown-content .sl-heading-wrapper.sl-section-titlebar > .sl-anchor-link {
|
|
2618
|
+
opacity: 0;
|
|
2619
|
+
}
|
|
1545
2620
|
}
|
|
1546
2621
|
|
|
1547
2622
|
.sl-markdown-content .sl-heading-wrapper.sl-section-titlebar:has(> .sl-section-collapsible > summary:hover)
|
|
@@ -1553,24 +2628,72 @@ body {
|
|
|
1553
2628
|
opacity: 1;
|
|
1554
2629
|
}
|
|
1555
2630
|
|
|
2631
|
+
/* A narrow screen shows no section number and, often, has no hover to reveal
|
|
2632
|
+
the chain icon — yet the icon is the way to the section's link and, in its
|
|
2633
|
+
"Link copied · § 1.1.2", its number (docs/plans/titles-and-containers.md
|
|
2634
|
+
Q3). So it is always shown there, smaller and in the muted text colour.
|
|
2635
|
+
The size variable also sets the room `anchor-links.css` reserves for it at
|
|
2636
|
+
the end of the title. After the hover rules above, which it overrides. */
|
|
2637
|
+
@media screen and (width < 50em) {
|
|
2638
|
+
.sl-markdown-content .sl-heading-wrapper {
|
|
2639
|
+
--sl-anchor-icon-size: 0.7em;
|
|
2640
|
+
}
|
|
2641
|
+
|
|
2642
|
+
.sl-markdown-content .sl-heading-wrapper > .sl-anchor-link,
|
|
2643
|
+
.sl-markdown-content .sl-heading-wrapper.sl-section-titlebar > .sl-anchor-link {
|
|
2644
|
+
opacity: 1;
|
|
2645
|
+
color: var(--sl-color-gray-3);
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
|
|
1556
2649
|
/* The chevron sits to the *left* of the title without shifting the title's
|
|
1557
2650
|
own position: `markdown.css`'s default marker is inline, right before the
|
|
1558
2651
|
text, pushed left slightly by a negative margin — meaning the title
|
|
1559
2652
|
itself sits further right than an ordinary (non-collapsible) heading.
|
|
1560
2653
|
Taking the marker fully out of flow with `position: absolute` and a
|
|
1561
2654
|
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.
|
|
2655
|
+
own text always starts at the same position a plain heading's would.
|
|
2656
|
+
That gutter is only `--sl-content-pad-x` wide (16–24px) and ends at the
|
|
2657
|
+
sidebar's border, so the marker is centred in it — a fixed `-1.6em` once
|
|
2658
|
+
put the glyph right on that border line. Inside a `[card]` section the
|
|
2659
|
+
gutter is the card's own padding (`--ex-section-gutter`, `surfaces.css`).
|
|
2660
|
+
Narrow and touch screens have no usable gutter at all; the marker moves
|
|
2661
|
+
into the title line there (below). */
|
|
1563
2662
|
.sl-markdown-content .sl-section-summary {
|
|
1564
2663
|
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`. */
|
|
2664
|
+
/* Room for the absolutely-positioned anchor icon at the end of the line. */
|
|
1567
2665
|
padding-inline-end: 1.5em;
|
|
2666
|
+
/* The title's own font size, so the gutter chevron can centre on the
|
|
2667
|
+
title's first line — not on the whole summary, which also holds the
|
|
2668
|
+
"Hidden here" line while closed. */
|
|
2669
|
+
--sl-section-title-size: var(--sl-text-h2);
|
|
2670
|
+
}
|
|
2671
|
+
|
|
2672
|
+
.sl-markdown-content .sl-section-summary:has(> h3) {
|
|
2673
|
+
--sl-section-title-size: var(--sl-text-h3);
|
|
2674
|
+
}
|
|
2675
|
+
|
|
2676
|
+
.sl-markdown-content .sl-section-summary:has(> h4) {
|
|
2677
|
+
--sl-section-title-size: var(--sl-text-h4);
|
|
2678
|
+
}
|
|
2679
|
+
|
|
2680
|
+
.sl-markdown-content .sl-section-summary:has(> h5) {
|
|
2681
|
+
--sl-section-title-size: var(--sl-text-h5);
|
|
2682
|
+
}
|
|
2683
|
+
|
|
2684
|
+
.sl-markdown-content .sl-section-summary:has(> h6) {
|
|
2685
|
+
--sl-section-title-size: var(--sl-text-h6, var(--sl-text-base));
|
|
1568
2686
|
}
|
|
1569
2687
|
|
|
1570
2688
|
.sl-markdown-content .sl-section-summary::before {
|
|
1571
2689
|
position: absolute;
|
|
1572
|
-
left
|
|
1573
|
-
|
|
2690
|
+
/* `<summary>` starts 0.5rem left of the text (`markdown.css`), so this
|
|
2691
|
+
centres the marker box on the middle of the gutter. */
|
|
2692
|
+
left: calc(
|
|
2693
|
+
0.5rem - var(--ex-section-gutter, var(--sl-content-pad-x, 1rem)) / 2 -
|
|
2694
|
+
var(--sl-details-marker-size, 1.25rem) / 2
|
|
2695
|
+
);
|
|
2696
|
+
top: calc(var(--sl-section-title-size) * var(--sl-line-height-headings) / 2);
|
|
1574
2697
|
margin: 0; /* cancel `markdown.css`'s inline-flow margin trick */
|
|
1575
2698
|
transform: translateY(-50%);
|
|
1576
2699
|
opacity: 0;
|
|
@@ -1602,6 +2725,109 @@ body {
|
|
|
1602
2725
|
transition: opacity 100ms ease;
|
|
1603
2726
|
}
|
|
1604
2727
|
|
|
2728
|
+
/* A closed section's cues beyond the chevron — the two `aria-hidden` spans
|
|
2729
|
+
`CollapsibleSections.astro` appends to `<summary>` after the heading.
|
|
2730
|
+
`.sl-section-hint` ("(click to expand)", "(tap to expand)" on touch) is
|
|
2731
|
+
for narrow/touch screens only (enabled in the block below);
|
|
2732
|
+
`.sl-section-stub` ("Hidden here: 2 paragraphs, 1 equation") shows on
|
|
2733
|
+
every screen. Both vanish once the section is `open` — the stub by
|
|
2734
|
+
collapsing its grid row, so a peek grown into a real expand slides the
|
|
2735
|
+
body up smoothly instead of jumping by a line. */
|
|
2736
|
+
.sl-markdown-content .sl-section-hint {
|
|
2737
|
+
display: none;
|
|
2738
|
+
margin-inline-start: 0.4em;
|
|
2739
|
+
font-size: var(--sl-text-sm);
|
|
2740
|
+
font-weight: 400;
|
|
2741
|
+
color: var(--sl-color-gray-3);
|
|
2742
|
+
white-space: nowrap;
|
|
2743
|
+
}
|
|
2744
|
+
|
|
2745
|
+
.sl-markdown-content .sl-section-hint::before {
|
|
2746
|
+
content: '(click to expand)';
|
|
2747
|
+
}
|
|
2748
|
+
|
|
2749
|
+
@media (hover: none) {
|
|
2750
|
+
.sl-markdown-content .sl-section-hint::before {
|
|
2751
|
+
content: '(tap to expand)';
|
|
2752
|
+
}
|
|
2753
|
+
}
|
|
2754
|
+
|
|
2755
|
+
.sl-markdown-content .sl-section-stub {
|
|
2756
|
+
display: grid;
|
|
2757
|
+
grid-template-rows: 0fr;
|
|
2758
|
+
opacity: 0;
|
|
2759
|
+
margin-block-start: 0;
|
|
2760
|
+
padding-block-end: 0;
|
|
2761
|
+
border-block-end: 0 dashed var(--sl-color-gray-5);
|
|
2762
|
+
text-indent: 0; /* the narrow-screen hanging indent is for the title only */
|
|
2763
|
+
font-size: var(--sl-text-sm);
|
|
2764
|
+
font-weight: 400;
|
|
2765
|
+
line-height: 1.5;
|
|
2766
|
+
color: var(--sl-color-gray-3);
|
|
2767
|
+
transition:
|
|
2768
|
+
grid-template-rows 220ms ease,
|
|
2769
|
+
opacity 150ms ease,
|
|
2770
|
+
margin-block-start 220ms ease,
|
|
2771
|
+
padding-block-end 220ms ease,
|
|
2772
|
+
border-block-end-width 220ms ease;
|
|
2773
|
+
}
|
|
2774
|
+
|
|
2775
|
+
.sl-markdown-content .sl-section-stub > span {
|
|
2776
|
+
overflow: hidden;
|
|
2777
|
+
min-height: 0;
|
|
2778
|
+
}
|
|
2779
|
+
|
|
2780
|
+
.sl-markdown-content details.sl-section-collapsible:not([data-state='open'])
|
|
2781
|
+
> .sl-section-summary
|
|
2782
|
+
> .sl-section-stub {
|
|
2783
|
+
grid-template-rows: 1fr;
|
|
2784
|
+
opacity: 1;
|
|
2785
|
+
margin-block-start: 0.3rem;
|
|
2786
|
+
padding-block-end: 0.45rem;
|
|
2787
|
+
border-block-end-width: 1px;
|
|
2788
|
+
}
|
|
2789
|
+
|
|
2790
|
+
/* Narrow and touch screens: there is no gutter to hold the chevron (on a
|
|
2791
|
+
phone it used to render off-screen), and no hover to reveal it on an open
|
|
2792
|
+
section. It moves into the title line and stays visible in both states —
|
|
2793
|
+
`›` closed, `⌄` open, so it also tells a reader the section can fold —
|
|
2794
|
+
with a hanging indent that keeps a wrapped title's later lines under its
|
|
2795
|
+
text, not under the chevron. The room reserved is the marker's own box
|
|
2796
|
+
minus its negative start margin plus its end gap (`markdown.css`).
|
|
2797
|
+
`screen` only: a printer reports `hover: none` too, and an inline heading
|
|
2798
|
+
would lose the print stylesheet's `break-after: avoid`. */
|
|
2799
|
+
@media screen and (width < 50em), screen and (hover: none) {
|
|
2800
|
+
.sl-markdown-content .sl-section-summary {
|
|
2801
|
+
--sl-section-marker-room: calc(
|
|
2802
|
+
var(--sl-details-marker-size, 1.25rem) * 0.75 + 0.25rem
|
|
2803
|
+
);
|
|
2804
|
+
padding-inline-start: calc(0.5rem + var(--sl-section-marker-room));
|
|
2805
|
+
text-indent: calc(-1 * var(--sl-section-marker-room));
|
|
2806
|
+
}
|
|
2807
|
+
|
|
2808
|
+
.sl-markdown-content .sl-section-summary > :is(h1, h2, h3, h4, h5, h6) {
|
|
2809
|
+
display: inline;
|
|
2810
|
+
}
|
|
2811
|
+
|
|
2812
|
+
.sl-markdown-content .sl-section-summary::before {
|
|
2813
|
+
position: static;
|
|
2814
|
+
vertical-align: -0.15em;
|
|
2815
|
+
transform: none;
|
|
2816
|
+
opacity: 1;
|
|
2817
|
+
transition: transform 150ms ease;
|
|
2818
|
+
}
|
|
2819
|
+
|
|
2820
|
+
.sl-markdown-content details.sl-section-collapsible[open] > .sl-section-summary::before {
|
|
2821
|
+
transform: rotateZ(90deg);
|
|
2822
|
+
}
|
|
2823
|
+
|
|
2824
|
+
.sl-markdown-content details.sl-section-collapsible:not([data-state='open'])
|
|
2825
|
+
> .sl-section-summary
|
|
2826
|
+
> .sl-section-hint {
|
|
2827
|
+
display: inline;
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
|
|
1605
2831
|
/* The section body: normally native `<details>` hiding/showing is all that's
|
|
1606
2832
|
needed (nothing renders while closed), but `peeking` (a collapsed section
|
|
1607
2833
|
hovered/focused — see `CollapsibleSections.astro`) has to force the
|
|
@@ -1650,13 +2876,16 @@ body {
|
|
|
1650
2876
|
|
|
1651
2877
|
@media (prefers-reduced-motion: reduce) {
|
|
1652
2878
|
.sl-markdown-content .sl-section-summary::before,
|
|
1653
|
-
.sl-markdown-content .sl-section-body
|
|
2879
|
+
.sl-markdown-content .sl-section-body,
|
|
2880
|
+
.sl-markdown-content .sl-section-stub {
|
|
1654
2881
|
transition: none;
|
|
1655
2882
|
}
|
|
1656
2883
|
}
|
|
1657
2884
|
|
|
1658
2885
|
@media print {
|
|
1659
|
-
.sl-markdown-content .sl-section-summary::before
|
|
2886
|
+
.sl-markdown-content .sl-section-summary::before,
|
|
2887
|
+
.sl-markdown-content .sl-section-hint,
|
|
2888
|
+
.sl-markdown-content .sl-section-stub {
|
|
1660
2889
|
display: none !important;
|
|
1661
2890
|
}
|
|
1662
2891
|
|
|
@@ -1664,14 +2893,13 @@ body {
|
|
|
1664
2893
|
display: none;
|
|
1665
2894
|
}
|
|
1666
2895
|
|
|
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`. */
|
|
2896
|
+
/* Print follows the screen, and CSS couldn't do otherwise anyway: the
|
|
2897
|
+
HTML spec has the browser skip rendering a closed <details>'s
|
|
2898
|
+
non-summary children outright — a rule no author CSS can override
|
|
2899
|
+
(`display`, `content-visibility`, `!important` included). What JS does
|
|
2900
|
+
at print time (`src/components/disclosure/print-as-shown.ts`) is settle
|
|
2901
|
+
a peeking or mid-animation section to the state it reads as, and add a
|
|
2902
|
+
"(content collapsed …)" note after each closed one. */
|
|
1675
2903
|
}
|
|
1676
2904
|
|
|
1677
2905
|
/* Table column narrowing + expand-on-overflow
|
|
@@ -1702,10 +2930,10 @@ body {
|
|
|
1702
2930
|
`TableOverflowExpander.astro`'s script, and to every table on the site,
|
|
1703
2931
|
not just ones wide enough to overflow. `color-mix` against `--sl-color-bg`
|
|
1704
2932
|
(not a fixed gray token) keeps the stripe theme-correct automatically —
|
|
1705
|
-
the same technique
|
|
1706
|
-
reason: a token like
|
|
1707
|
-
|
|
1708
|
-
|
|
2933
|
+
the same technique `surfaces.css`'s accent tint uses, and for the same
|
|
2934
|
+
reason: a token like `--sl-color-gray-7` is only defined for one theme.
|
|
2935
|
+
The hover rule is unlayered and comes after the stripe rule, so it wins
|
|
2936
|
+
over an even/odd row's own stripe regardless of specificity. */
|
|
1709
2937
|
.sl-markdown-content table:not(:where(.not-content *)) tbody tr:nth-child(even) {
|
|
1710
2938
|
background: color-mix(in srgb, var(--sl-color-bg) 85%, var(--sl-color-gray-5) 15%);
|
|
1711
2939
|
}
|
|
@@ -1731,6 +2959,19 @@ body {
|
|
|
1731
2959
|
flex: 1 1 auto;
|
|
1732
2960
|
min-width: 0;
|
|
1733
2961
|
overflow-x: auto;
|
|
2962
|
+
/* A size container, so a row spanning the whole table (the "… N more
|
|
2963
|
+
rows …" separator, `Table.astro`) can size its label to the part of
|
|
2964
|
+
the table on screen (`100cqi`), not to its whole scrolled width. It
|
|
2965
|
+
takes its width from the flex row, never from its content, so the
|
|
2966
|
+
inline-size containment this implies changes nothing else. */
|
|
2967
|
+
container-type: inline-size;
|
|
2968
|
+
}
|
|
2969
|
+
|
|
2970
|
+
/* A preview card sizes itself to its content, and a size container has no
|
|
2971
|
+
width of its own to give it: in a card the table's width sizes the card,
|
|
2972
|
+
as it always did (`FloatRefLayer.astro`). */
|
|
2973
|
+
.hover-panel .table-overflow-scroll {
|
|
2974
|
+
container-type: normal;
|
|
1734
2975
|
}
|
|
1735
2976
|
|
|
1736
2977
|
/* A scrollable region must be reachable by keyboard (WCAG 2.1.1) — the
|
|
@@ -1898,6 +3139,7 @@ body {
|
|
|
1898
3139
|
.right-sidebar-container,
|
|
1899
3140
|
.pagination-links,
|
|
1900
3141
|
.layout-edge-toggle,
|
|
3142
|
+
.layout-edge-resizer,
|
|
1901
3143
|
[data-explico-export-chrome],
|
|
1902
3144
|
[data-popup-root],
|
|
1903
3145
|
[data-citation-panel],
|
|
@@ -1909,11 +3151,8 @@ body {
|
|
|
1909
3151
|
.table-overflow-expand-btn,
|
|
1910
3152
|
.keyed-table__pagination-links,
|
|
1911
3153
|
.keyed-table__more-row,
|
|
1912
|
-
.diagram-toolbar,
|
|
1913
3154
|
.sl-anchor-link,
|
|
1914
|
-
.
|
|
1915
|
-
.diagram__title-anchor,
|
|
1916
|
-
.memo-block__title-anchor,
|
|
3155
|
+
.float-caption__anchor,
|
|
1917
3156
|
.short-note__collapse,
|
|
1918
3157
|
.assessment-actions,
|
|
1919
3158
|
.assessment-chevron,
|
|
@@ -1956,9 +3195,6 @@ body {
|
|
|
1956
3195
|
}
|
|
1957
3196
|
|
|
1958
3197
|
.sl-markdown-content :is(h1, h2, h3, h4, h5, h6),
|
|
1959
|
-
.keyed-figure__summary,
|
|
1960
|
-
.diagram__summary,
|
|
1961
|
-
.memo-block__summary,
|
|
1962
3198
|
.assessment-item-heading {
|
|
1963
3199
|
break-after: avoid-page;
|
|
1964
3200
|
page-break-after: avoid;
|
|
@@ -1978,7 +3214,7 @@ body {
|
|
|
1978
3214
|
.compact-example,
|
|
1979
3215
|
.assessment-item,
|
|
1980
3216
|
.lab-result,
|
|
1981
|
-
.lab-chart
|
|
3217
|
+
.lab-chart,
|
|
1982
3218
|
.sl-markdown-content pre,
|
|
1983
3219
|
.sl-markdown-content blockquote {
|
|
1984
3220
|
break-inside: avoid-page;
|
|
@@ -2038,15 +3274,15 @@ body {
|
|
|
2038
3274
|
display: table-row !important;
|
|
2039
3275
|
}
|
|
2040
3276
|
|
|
2041
|
-
|
|
2042
|
-
|
|
3277
|
+
/* An open example set's inactive tabs are hidden only to save screen
|
|
3278
|
+
space. A closed question panel or short note is the reader's own
|
|
3279
|
+
disclosure, and print follows the screen for those — it stays closed
|
|
3280
|
+
and gets a `.explico-collapsed-note` (below) instead. */
|
|
2043
3281
|
.compact-example[hidden] {
|
|
2044
3282
|
display: block !important;
|
|
2045
3283
|
}
|
|
2046
3284
|
|
|
2047
3285
|
.diagram,
|
|
2048
|
-
.diagram__titlebar,
|
|
2049
|
-
.diagram__details,
|
|
2050
3286
|
.diagram__body,
|
|
2051
3287
|
.diagram-stage,
|
|
2052
3288
|
.diagram-scroll {
|
|
@@ -2077,6 +3313,32 @@ body {
|
|
|
2077
3313
|
height: 100% !important;
|
|
2078
3314
|
}
|
|
2079
3315
|
|
|
3316
|
+
/* WebKit (Safari, every iOS browser) paints a `foreignObject` descendant
|
|
3317
|
+
with its own render layer — every KaTeX `position: relative` span —
|
|
3318
|
+
without the SVG's internal transforms, the `viewBox` scale above
|
|
3319
|
+
included, so a printed diagram loses its formulas. Where CSS can divide
|
|
3320
|
+
lengths, keep the SVG at its build-time size and scale the HTML canvas
|
|
3321
|
+
instead; the negative block margin gives the layout box the scaled
|
|
3322
|
+
height. Without that support the `viewBox` scaling above stays. */
|
|
3323
|
+
@supports (transform: scale(calc(100cqw / 1px))) {
|
|
3324
|
+
.diagram-scroll {
|
|
3325
|
+
container-type: inline-size;
|
|
3326
|
+
}
|
|
3327
|
+
|
|
3328
|
+
.diagram-canvas {
|
|
3329
|
+
width: calc(var(--diagram-width) * 1px) !important;
|
|
3330
|
+
max-width: none !important;
|
|
3331
|
+
height: calc(var(--diagram-height) * 1px) !important;
|
|
3332
|
+
aspect-ratio: auto;
|
|
3333
|
+
margin-block-end: calc(
|
|
3334
|
+
100cqw * var(--diagram-height) / var(--diagram-width) -
|
|
3335
|
+
var(--diagram-height) * 1px
|
|
3336
|
+
);
|
|
3337
|
+
transform: scale(calc(100cqw / (var(--diagram-width) * 1px)));
|
|
3338
|
+
transform-origin: 0 0;
|
|
3339
|
+
}
|
|
3340
|
+
}
|
|
3341
|
+
|
|
2080
3342
|
.lab-chart,
|
|
2081
3343
|
.lab-math,
|
|
2082
3344
|
.katex-display {
|
|
@@ -2085,10 +3347,14 @@ body {
|
|
|
2085
3347
|
overflow: visible !important;
|
|
2086
3348
|
}
|
|
2087
3349
|
|
|
3350
|
+
/* Not KaTeX's own SVGs: a `\sqrt` radical (and stretchy arrows/accents)
|
|
3351
|
+
is a deliberately oversized SVG clipped by its parent, and its height
|
|
3352
|
+
comes from KaTeX's `height` attribute — `height: auto` resolved it to
|
|
3353
|
+
0, so every printed square root lost its radical sign. */
|
|
2088
3354
|
.lab-chart svg,
|
|
2089
3355
|
.keyed-figure img,
|
|
2090
3356
|
.sl-markdown-content img,
|
|
2091
|
-
.sl-markdown-content svg {
|
|
3357
|
+
.sl-markdown-content svg:not(.katex *) {
|
|
2092
3358
|
max-width: 100% !important;
|
|
2093
3359
|
height: auto;
|
|
2094
3360
|
}
|
|
@@ -2108,14 +3374,18 @@ body {
|
|
|
2108
3374
|
}
|
|
2109
3375
|
|
|
2110
3376
|
:is(
|
|
3377
|
+
.ex-tier-meta,
|
|
3378
|
+
.ex-tier-accent,
|
|
3379
|
+
.ex-tier-aside,
|
|
3380
|
+
.starlight-aside,
|
|
3381
|
+
.sl-markdown-content article.card,
|
|
2111
3382
|
.lab-shell,
|
|
2112
3383
|
.lab-result,
|
|
2113
3384
|
.assessment-shell,
|
|
2114
3385
|
.assessment-item,
|
|
2115
3386
|
.memo-block-frame,
|
|
2116
|
-
.keyed-figure__details,
|
|
2117
3387
|
.compact-examples,
|
|
2118
|
-
.
|
|
3388
|
+
.block-badge
|
|
2119
3389
|
) {
|
|
2120
3390
|
color: #111 !important;
|
|
2121
3391
|
border-color: #777 !important;
|
|
@@ -2130,4 +3400,38 @@ body {
|
|
|
2130
3400
|
-webkit-print-color-adjust: exact;
|
|
2131
3401
|
}
|
|
2132
3402
|
|
|
3403
|
+
/* "(content collapsed — full text: …)" under a disclosure the reader left
|
|
3404
|
+
closed (`src/components/disclosure/print-as-shown.ts`). Sized in `rem`:
|
|
3405
|
+
a section's note sits inside its heading-sized title bar. */
|
|
3406
|
+
.explico-collapsed-note {
|
|
3407
|
+
display: block;
|
|
3408
|
+
margin-block: 0.15rem 0.75rem;
|
|
3409
|
+
font-size: 0.8rem;
|
|
3410
|
+
font-style: italic;
|
|
3411
|
+
font-weight: 400;
|
|
3412
|
+
line-height: 1.4;
|
|
3413
|
+
color: #444;
|
|
3414
|
+
overflow-wrap: anywhere;
|
|
3415
|
+
text-indent: 0;
|
|
3416
|
+
}
|
|
3417
|
+
|
|
3418
|
+
.explico-collapsed-note a[href] {
|
|
3419
|
+
color: #08775b !important;
|
|
3420
|
+
text-decoration: underline;
|
|
3421
|
+
print-color-adjust: exact;
|
|
3422
|
+
-webkit-print-color-adjust: exact;
|
|
3423
|
+
}
|
|
3424
|
+
|
|
3425
|
+
.memo-block-frame .explico-collapsed-note {
|
|
3426
|
+
margin: 0;
|
|
3427
|
+
padding-block-end: 0.25rem;
|
|
3428
|
+
}
|
|
3429
|
+
}
|
|
3430
|
+
|
|
3431
|
+
/* The note exists only while a print is being prepared, and never shows on
|
|
3432
|
+
screen even then (the print button prepares before the dialog opens). */
|
|
3433
|
+
@media not print {
|
|
3434
|
+
.explico-collapsed-note {
|
|
3435
|
+
display: none;
|
|
3436
|
+
}
|
|
2133
3437
|
}
|