@lernapps/app-templates 0.0.1 → 0.1.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.
Files changed (232) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +195 -2
  3. package/dist/appname-Bh23cUuz.mjs +12 -0
  4. package/dist/assessment-Dy359O1O.mjs +1696 -0
  5. package/dist/block-BK_ohsH1.mjs +82 -0
  6. package/dist/blocks-CxtCPAa5.mjs +149 -0
  7. package/dist/blocks.mjs +4 -0
  8. package/dist/check-CteIFN96.mjs +254 -0
  9. package/dist/content-DO6oEJxj.mjs +140 -0
  10. package/dist/contract-PONpxJtd.mjs +52 -0
  11. package/dist/e2e-CU0n_unV.mjs +89 -0
  12. package/dist/engine-CArxqizW.mjs +136 -0
  13. package/dist/explainer-e2e.mjs +1311 -0
  14. package/dist/explainer-islands.mjs +197 -0
  15. package/dist/explainer-plugin.mjs +2132 -0
  16. package/dist/explainer.mjs +1246 -0
  17. package/dist/html-mffkHGHh.mjs +89 -0
  18. package/dist/image-CspJVfyQ.mjs +21 -0
  19. package/dist/interactive-e2e.mjs +140 -0
  20. package/dist/interactive-plugin.mjs +242 -0
  21. package/dist/interactive.mjs +75 -0
  22. package/dist/load-RosvaPZf.mjs +16976 -0
  23. package/dist/needs-BzEahJ6X.mjs +97 -0
  24. package/dist/pages-9RaaomoO.mjs +81 -0
  25. package/dist/questions-e2e.mjs +1 -0
  26. package/dist/questions-engine.mjs +3 -0
  27. package/dist/questions.mjs +6 -0
  28. package/dist/quiz-DnW-xtCh.mjs +70 -0
  29. package/dist/quiz-e2e.mjs +174 -0
  30. package/dist/quiz-plugin.mjs +266 -0
  31. package/dist/quiz.mjs +246 -0
  32. package/dist/render-D5kwkNt1.mjs +507 -0
  33. package/dist/render-DqHOJyHK.mjs +146 -0
  34. package/dist/render-GS1Htlu8.mjs +545 -0
  35. package/dist/result-D_mmCVwN.mjs +180 -0
  36. package/dist/tasks-DADUYy52.mjs +74 -0
  37. package/dist/validate-BDwL7Su3.mjs +1076 -0
  38. package/dist/validate-Bxy9NfB8.mjs +146 -0
  39. package/dist/vue-DO1m6q1R.mjs +40 -0
  40. package/dist/vue-code-BkJjW_I_.mjs +320 -0
  41. package/docs/arc42/01-introduction-and-goals.arc42.md +82 -0
  42. package/docs/arc42/02-constraints.arc42.md +228 -0
  43. package/docs/arc42/03-system-context.arc42.md +118 -0
  44. package/docs/arc42/04-solution-strategy.arc42.md +47 -0
  45. package/docs/arc42/05-building-blocks.arc42.md +307 -0
  46. package/docs/arc42/06-runtime-view.arc42.md +98 -0
  47. package/docs/arc42/07-deployment-view.arc42.md +160 -0
  48. package/docs/arc42/08-concepts.arc42.md +123 -0
  49. package/docs/arc42/09-decisions.arc42.md +246 -0
  50. package/docs/arc42/10-quality-requirements.arc42.md +155 -0
  51. package/docs/arc42/11-risks.arc42.md +113 -0
  52. package/docs/arc42/12-glossary.arc42.md +162 -0
  53. package/docs/arc42/architecture-evidence.md +395 -0
  54. package/explainer/.arc42ignore +3 -0
  55. package/explainer/README.md +54 -0
  56. package/explainer/_gitignore +5 -0
  57. package/explainer/docs/arc42/03-explainer-system-context.arc42.md +35 -0
  58. package/explainer/docs/arc42/05-explainer-building-blocks.arc42.md +659 -0
  59. package/explainer/docs/arc42/06-explainer-runtime-view.arc42.md +105 -0
  60. package/explainer/docs/arc42/07-explainer-deployment-view.arc42.md +34 -0
  61. package/explainer/docs/arc42/08-explainer-concepts.arc42.md +17 -0
  62. package/explainer/docs/arc42/09-explainer-decisions.arc42.md +443 -0
  63. package/explainer/docs/arc42/10-explainer-quality-requirements.arc42.md +54 -0
  64. package/explainer/docs/arc42/11-explainer-risks.arc42.md +17 -0
  65. package/explainer/docs/arc42/12-explainer-glossary.arc42.md +185 -0
  66. package/explainer/e2e/explainer.e2e.ts +3 -0
  67. package/explainer/index.html +11 -0
  68. package/explainer/package.json +18 -0
  69. package/explainer/playwright.config.ts +1 -0
  70. package/explainer/src/app.yaml +20 -0
  71. package/explainer/src/components/ProzentFeld.test.ts +30 -0
  72. package/explainer/src/components/ProzentFeld.ts +121 -0
  73. package/explainer/src/components/ProzentFeld.vue +84 -0
  74. package/explainer/src/images/hunderterfeld-klammern.svg +105 -0
  75. package/explainer/src/main.ts +4 -0
  76. package/explainer/src/prozent/chapter.yaml +18 -0
  77. package/explainer/src/prozent/grundwert.yaml +115 -0
  78. package/explainer/src/prozent/prozentsatz.yaml +99 -0
  79. package/explainer/src/prozent/prozentwert.yaml +119 -0
  80. package/explainer/tsconfig.json +1 -0
  81. package/explainer/vite.config.ts +4 -0
  82. package/interactive/.arc42ignore +5 -0
  83. package/interactive/README.md +28 -0
  84. package/interactive/_gitignore +4 -0
  85. package/interactive/docs/arc42/05-interactive-building-blocks.arc42.md +518 -0
  86. package/interactive/docs/arc42/06-interactive-runtime-view.arc42.md +58 -0
  87. package/interactive/docs/arc42/07-interactive-deployment-view.arc42.md +35 -0
  88. package/interactive/docs/arc42/08-interactive-concepts.arc42.md +52 -0
  89. package/interactive/docs/arc42/09-interactive-decisions.arc42.md +130 -0
  90. package/interactive/docs/arc42/10-interactive-quality-requirements.arc42.md +45 -0
  91. package/interactive/docs/arc42/11-interactive-risks.arc42.md +20 -0
  92. package/interactive/docs/arc42/12-interactive-glossary.arc42.md +80 -0
  93. package/interactive/e2e/interactive.e2e.ts +3 -0
  94. package/interactive/index.html +11 -0
  95. package/interactive/package.json +18 -0
  96. package/interactive/playwright.config.ts +1 -0
  97. package/interactive/src/app.yaml +28 -0
  98. package/interactive/src/core/index.ts +101 -0
  99. package/interactive/src/data/lessons.json +4 -0
  100. package/interactive/src/env.d.ts +6 -0
  101. package/interactive/src/main.ts +6 -0
  102. package/interactive/src/messages/de.json +12 -0
  103. package/interactive/src/playthroughs/grundreihe.yaml +33 -0
  104. package/interactive/src/playthroughs/obere-reihe.yaml +14 -0
  105. package/interactive/src/ui/App.vue +85 -0
  106. package/interactive/tsconfig.json +1 -0
  107. package/interactive/vite.config.ts +4 -0
  108. package/package.json +143 -4
  109. package/quiz/README.md +31 -0
  110. package/quiz/_gitignore +5 -0
  111. package/quiz/docs/arc42/05-quiz-building-blocks.arc42.md +283 -0
  112. package/quiz/docs/arc42/06-quiz-runtime-view.arc42.md +21 -0
  113. package/quiz/docs/arc42/07-quiz-deployment-view.arc42.md +33 -0
  114. package/quiz/docs/arc42/09-quiz-decisions.arc42.md +36 -0
  115. package/quiz/docs/arc42/10-quiz-quality-requirements.arc42.md +53 -0
  116. package/quiz/docs/arc42/11-quiz-risks.arc42.md +19 -0
  117. package/quiz/docs/arc42/12-quiz-glossary.arc42.md +27 -0
  118. package/quiz/e2e/quiz.e2e.ts +3 -0
  119. package/quiz/index.html +11 -0
  120. package/quiz/package.json +18 -0
  121. package/quiz/playwright.config.ts +1 -0
  122. package/quiz/src/images/berge-ordnen.jpg +0 -0
  123. package/quiz/src/images/everest-hoehe.jpg +0 -0
  124. package/quiz/src/images/galapagos.jpg +0 -0
  125. package/quiz/src/images/grand-canyon.jpg +0 -0
  126. package/quiz/src/images/totes-meer.jpg +0 -0
  127. package/quiz/src/images/uluru.jpg +0 -0
  128. package/quiz/src/images/wasserfaelle-laender.jpg +0 -0
  129. package/quiz/src/main.ts +4 -0
  130. package/quiz/src/quiz.json +312 -0
  131. package/quiz/tsconfig.json +1 -0
  132. package/quiz/vite.config.ts +4 -0
  133. package/runtime/explainer/assessment-client.ts +478 -0
  134. package/runtime/explainer/assessment-page.ts +448 -0
  135. package/runtime/explainer/assessment.ts +393 -0
  136. package/runtime/explainer/check-page.ts +520 -0
  137. package/runtime/explainer/components/exercise.ts +409 -0
  138. package/runtime/explainer/components/props.ts +230 -0
  139. package/runtime/explainer/components/read.ts +428 -0
  140. package/runtime/explainer/content.ts +277 -0
  141. package/runtime/explainer/e2e.ts +1488 -0
  142. package/runtime/explainer/exercises.ts +326 -0
  143. package/runtime/explainer/explainer.css +1283 -0
  144. package/runtime/explainer/explainer.ts +838 -0
  145. package/runtime/explainer/explainer.v1.schema.json +1165 -0
  146. package/runtime/explainer/expression.ts +407 -0
  147. package/runtime/explainer/fraction.ts +107 -0
  148. package/runtime/explainer/generated/comparator.ts +31 -0
  149. package/runtime/explainer/generated/question.ts +165 -0
  150. package/runtime/explainer/generated/soundness.ts +280 -0
  151. package/runtime/explainer/generated/texts.ts +257 -0
  152. package/runtime/explainer/generated/types.ts +103 -0
  153. package/runtime/explainer/generated/values.ts +136 -0
  154. package/runtime/explainer/islands.ts +281 -0
  155. package/runtime/explainer/load.ts +457 -0
  156. package/runtime/explainer/messages/de.json +200 -0
  157. package/runtime/explainer/messages/en.json +200 -0
  158. package/runtime/explainer/messages.ts +13 -0
  159. package/runtime/explainer/needs.ts +122 -0
  160. package/runtime/explainer/open-task.ts +235 -0
  161. package/runtime/explainer/outline.ts +306 -0
  162. package/runtime/explainer/plugin.ts +488 -0
  163. package/runtime/explainer/position.ts +62 -0
  164. package/runtime/explainer/prompt.ts +75 -0
  165. package/runtime/explainer/render.ts +686 -0
  166. package/runtime/explainer/result.ts +238 -0
  167. package/runtime/explainer/routes.ts +119 -0
  168. package/runtime/explainer/schema.ts +140 -0
  169. package/runtime/explainer/scope.ts +87 -0
  170. package/runtime/explainer/stuck.ts +57 -0
  171. package/runtime/explainer/tasks.ts +109 -0
  172. package/runtime/explainer/tutor.ts +469 -0
  173. package/runtime/explainer/tutorpage.ts +669 -0
  174. package/runtime/explainer/video.ts +123 -0
  175. package/runtime/interactive/contract.ts +121 -0
  176. package/runtime/interactive/e2e.ts +190 -0
  177. package/runtime/interactive/interactive.css +82 -0
  178. package/runtime/interactive/interactive.ts +115 -0
  179. package/runtime/interactive/interactive.v1.schema.json +146 -0
  180. package/runtime/interactive/load.ts +188 -0
  181. package/runtime/interactive/messages/de.json +14 -0
  182. package/runtime/interactive/messages/en.json +14 -0
  183. package/runtime/interactive/messages.ts +11 -0
  184. package/runtime/interactive/playthrough.v1.schema.json +143 -0
  185. package/runtime/interactive/plugin.ts +266 -0
  186. package/runtime/interactive/render.ts +126 -0
  187. package/runtime/quiz/e2e.ts +233 -0
  188. package/runtime/quiz/engine.ts +242 -0
  189. package/runtime/quiz/messages/de.json +23 -0
  190. package/runtime/quiz/messages/en.json +23 -0
  191. package/runtime/quiz/plugin.ts +150 -0
  192. package/runtime/quiz/quiz.css +154 -0
  193. package/runtime/quiz/quiz.ts +56 -0
  194. package/runtime/quiz/quiz.v1.schema.json +72 -0
  195. package/runtime/quiz/render.ts +173 -0
  196. package/runtime/quiz/validate.ts +108 -0
  197. package/runtime/shared/appname.ts +16 -0
  198. package/runtime/shared/blocks/block.ts +162 -0
  199. package/runtime/shared/blocks/blocks.css +190 -0
  200. package/runtime/shared/blocks/blocks.v1.schema.json +432 -0
  201. package/runtime/shared/blocks/code.ts +26 -0
  202. package/runtime/shared/blocks/figures.ts +49 -0
  203. package/runtime/shared/blocks/image.ts +25 -0
  204. package/runtime/shared/blocks/index.ts +13 -0
  205. package/runtime/shared/blocks/messages/de.json +4 -0
  206. package/runtime/shared/blocks/messages/en.json +4 -0
  207. package/runtime/shared/blocks/render.ts +134 -0
  208. package/runtime/shared/blocks/validate.ts +165 -0
  209. package/runtime/shared/content.ts +197 -0
  210. package/runtime/shared/examples.ts +20 -0
  211. package/runtime/shared/html.ts +10 -0
  212. package/runtime/shared/languages.ts +94 -0
  213. package/runtime/shared/page.css +101 -0
  214. package/runtime/shared/pages.ts +114 -0
  215. package/runtime/shared/questions/e2e.ts +115 -0
  216. package/runtime/shared/questions/engine.ts +209 -0
  217. package/runtime/shared/questions/index.ts +39 -0
  218. package/runtime/shared/questions/messages/de.json +26 -0
  219. package/runtime/shared/questions/messages/en.json +26 -0
  220. package/runtime/shared/questions/question.ts +433 -0
  221. package/runtime/shared/questions/question.v1.schema.json +346 -0
  222. package/runtime/shared/questions/questions.css +192 -0
  223. package/runtime/shared/questions/render.ts +255 -0
  224. package/runtime/shared/questions/validate.ts +518 -0
  225. package/runtime/shared/schema.ts +44 -0
  226. package/runtime/shared/text/check.ts +68 -0
  227. package/runtime/shared/text/formula.ts +69 -0
  228. package/runtime/shared/text/markdown.ts +185 -0
  229. package/runtime/shared/text/speech.ts +39 -0
  230. package/runtime/shared/text/text.v1.schema.json +34 -0
  231. package/runtime/shared/vue-code.ts +395 -0
  232. package/runtime/shared/vue.ts +38 -0
@@ -0,0 +1,1283 @@
1
+ /* The look of an explainer (@lernapps/app-templates/explainer/style.css): the frame and the questions are shared
2
+ (page.css, questions.css); this is the explainer's page: chapters and pages with sections, formulas, figures, tables,
3
+ timelines, definitions, quotes, code, videos and exercises, complete without JavaScript. */
4
+ @import "../shared/page.css";
5
+ @import "../shared/blocks/blocks.css";
6
+ @import "../shared/questions/questions.css";
7
+
8
+ /* the explainer's own colours: the boxes */
9
+ :root {
10
+ --explainer-example: #ecfdf3;
11
+ --explainer-note: #fff7e0;
12
+ --explainer-done: #15803d;
13
+ }
14
+
15
+ @media (prefers-color-scheme: dark) {
16
+ :root {
17
+ --explainer-example: #12261b;
18
+ --explainer-note: #2b2512;
19
+ --explainer-done: #4ade80;
20
+ --explainer-hl-keyword: #e0a3ff;
21
+ --explainer-hl-string: #8fe0ac;
22
+ --explainer-hl-number: #ffb77a;
23
+ --explainer-hl-comment: #a3a9b3;
24
+ }
25
+ }
26
+
27
+ .explainer-breadcrumbs,
28
+ .explainer,
29
+ .explainer-pager {
30
+ max-width: var(--page-max-width, 44rem);
31
+ margin: 0 auto;
32
+ padding: 0 1rem;
33
+ overflow-wrap: break-word;
34
+ }
35
+
36
+ .explainer-breadcrumbs ol {
37
+ display: flex;
38
+ flex-wrap: wrap;
39
+ gap: 0.25rem 0.75rem;
40
+ margin: 0;
41
+ padding: 0;
42
+ list-style: none;
43
+ }
44
+
45
+ .explainer-breadcrumbs {
46
+ margin-top: 0.5rem;
47
+ font-size: 0.9375rem;
48
+ }
49
+
50
+ .explainer-breadcrumbs li + li::before {
51
+ content: "›";
52
+ margin-right: 0.75rem;
53
+ color: var(--page-muted);
54
+ }
55
+
56
+ .explainer h1 {
57
+ font-size: 1.875rem;
58
+ line-height: 1.2;
59
+ }
60
+
61
+ /* A long compound word in a heading ("Instrumentenfamilien") breaks rather than widening the page at 360 px: hyphenated
62
+ where the browser can, anywhere else; break-word alone does not shrink a flex item below its longest word */
63
+ .explainer h1,
64
+ .explainer h2,
65
+ .explainer h3 {
66
+ hyphens: auto;
67
+ overflow-wrap: anywhere;
68
+ }
69
+
70
+ .explainer h2,
71
+ .explainer h3,
72
+ .explainer h4 {
73
+ line-height: 1.25;
74
+ scroll-margin-top: 1rem;
75
+ }
76
+
77
+ .explainer-toc {
78
+ margin: 1rem 0;
79
+ padding: 0.5rem 1rem;
80
+ border-left: 4px solid var(--page-accent);
81
+ background: var(--page-surface);
82
+ }
83
+
84
+ .explainer-toc-title {
85
+ margin: 0.25rem 0;
86
+ font-weight: 600;
87
+ }
88
+
89
+ .explainer-timeline {
90
+ margin: 1rem 0;
91
+ padding-left: 1.25rem;
92
+ border-left: 3px solid var(--page-border);
93
+ list-style: none;
94
+ }
95
+
96
+ .explainer-timeline li {
97
+ margin-bottom: 0.75rem;
98
+ }
99
+
100
+ .explainer-event {
101
+ margin: 0;
102
+ }
103
+
104
+ .explainer-date {
105
+ display: block;
106
+ color: var(--page-muted);
107
+ font-size: 0.9375rem;
108
+ }
109
+
110
+ .explainer-event-text p {
111
+ margin: 0.25rem 0 0;
112
+ }
113
+
114
+ .explainer-definition {
115
+ margin: 1rem 0;
116
+ }
117
+
118
+ .explainer-definition dt {
119
+ font-weight: 600;
120
+ }
121
+
122
+ .explainer-definition dd {
123
+ margin-left: 1rem;
124
+ }
125
+
126
+ .explainer-definition dd p:first-child {
127
+ margin-top: 0.25rem;
128
+ }
129
+
130
+ .explainer-box {
131
+ margin: 1.25rem 0;
132
+ padding: 0.25rem 1rem;
133
+ border: 1px solid var(--page-border);
134
+ border-radius: 0.5rem;
135
+ }
136
+
137
+ .explainer-example {
138
+ background: var(--explainer-example);
139
+ }
140
+
141
+ .explainer-note {
142
+ background: var(--explainer-note);
143
+ }
144
+
145
+ .explainer-box-title {
146
+ margin: 0.75rem 0 0.5rem;
147
+ font-size: 1.0625rem;
148
+ }
149
+
150
+ .explainer-pages li,
151
+ .explainer-chapters > li {
152
+ margin-bottom: 0.5rem;
153
+ }
154
+
155
+ .explainer-chapter-link {
156
+ font-weight: 600;
157
+ }
158
+
159
+ .explainer-description {
160
+ display: block;
161
+ color: var(--page-muted);
162
+ font-size: 0.9375rem;
163
+ }
164
+
165
+ .explainer-glossary dt {
166
+ margin-top: 1rem;
167
+ font-weight: 600;
168
+ }
169
+
170
+ .explainer-glossary dd {
171
+ margin-left: 1rem;
172
+ }
173
+
174
+ .explainer-pager {
175
+ display: flex;
176
+ flex-wrap: wrap;
177
+ gap: 0.75rem;
178
+ justify-content: space-between;
179
+ margin-top: 2rem;
180
+ margin-bottom: 1rem;
181
+ }
182
+
183
+ .explainer-pager a[rel="next"] {
184
+ margin-left: auto;
185
+ }
186
+
187
+ /* Exercises: the question types and generated exercises, whose controls and feedback come from the questions'
188
+ stylesheet in the explainer's colours (--question-*). Without JavaScript the worked tasks and every "Lösung" show;
189
+ with JavaScript the live part shows, and the solutions and worked tasks once the exercise is solved or its solution
190
+ asked for. */
191
+ .explainer-exercise,
192
+ .explainer-component {
193
+ margin: 1rem 0 1.5rem;
194
+ }
195
+
196
+ .explainer-exercise details {
197
+ margin: 0.5rem 0;
198
+ padding: 0.25rem 0.75rem;
199
+ border: 1px solid var(--page-border);
200
+ border-radius: 0.375rem;
201
+ }
202
+
203
+ .explainer-exercise summary {
204
+ cursor: pointer;
205
+ font-weight: 600;
206
+ }
207
+
208
+ .explainer-exercise summary:focus-visible {
209
+ outline: 3px solid var(--page-text);
210
+ outline-offset: 2px;
211
+ }
212
+
213
+ .explainer-exercise .question {
214
+ margin: 0;
215
+ }
216
+
217
+ /* "Neue Aufgabe": a circular arrow beside the task number, its name the button's label */
218
+ .explainer-new-task {
219
+ display: inline-flex;
220
+ align-items: center;
221
+ justify-content: center;
222
+ width: 2.75rem;
223
+ height: 2.75rem;
224
+ margin: -0.5rem 0;
225
+ padding: 0;
226
+ border: 0;
227
+ border-radius: 0.375rem;
228
+ background: transparent;
229
+ color: var(--page-accent);
230
+ vertical-align: middle;
231
+ cursor: pointer;
232
+ }
233
+
234
+ .explainer-new-task:focus-visible {
235
+ outline: 3px solid var(--page-text);
236
+ outline-offset: 2px;
237
+ }
238
+
239
+ .explainer-worked {
240
+ padding-left: 1.5rem;
241
+ }
242
+
243
+ .explainer-worked-task {
244
+ margin: 0 0 1rem;
245
+ }
246
+
247
+ .explainer-live:not([hidden]) + .explainer-worked-intro {
248
+ margin-top: 1rem;
249
+ padding-top: 0.5rem;
250
+ border-top: 1px solid var(--page-border);
251
+ }
252
+
253
+ /* A component: its island, hidden until it hydrates, and its nojs text, which it replaces or keeps folded as a text
254
+ description under it; the reason of a wrong answer under its feedback */
255
+ .explainer-nojs.explainer-caption {
256
+ margin-top: 0.5rem;
257
+ color: var(--page-muted);
258
+ font-size: 0.9375rem;
259
+ }
260
+
261
+ .explainer-nojs.explainer-caption summary {
262
+ cursor: pointer;
263
+ font-weight: 600;
264
+ }
265
+
266
+ .explainer-component .question-diagnosis {
267
+ display: block;
268
+ margin: 0.25rem 0 0;
269
+ }
270
+
271
+ /* "Prüfen" of an exercise component, which the explainer draws under it in the row .question-actions: the button of the
272
+ questions, which style only buttons inside .question */
273
+ .explainer-component-form > .question-actions {
274
+ margin: 0.75rem 0 0;
275
+ }
276
+
277
+ .explainer-component-form > .question-actions .question-check {
278
+ font: inherit;
279
+ padding: 0.5rem 1rem;
280
+ border: 2px solid var(--page-accent);
281
+ border-radius: 0.375rem;
282
+ background: var(--page-accent);
283
+ color: var(--page-on-accent);
284
+ cursor: pointer;
285
+ }
286
+
287
+ .explainer-component-form > .question-actions .question-check:disabled {
288
+ cursor: default;
289
+ opacity: 0.6;
290
+ }
291
+
292
+ .explainer-component-form > .question-actions .question-check:focus-visible {
293
+ outline: 3px solid var(--page-text);
294
+ outline-offset: 2px;
295
+ }
296
+
297
+ /* The task number of a seeded exercise ("Aufgabe Nr. 7"), which a learner can name to a tutor, and the controls of an
298
+ exercise component: its number and "Neue Aufgabe", shown once it hydrates */
299
+ .explainer-task-number {
300
+ margin: 0 0 0.25rem;
301
+ color: var(--page-muted);
302
+ font-size: 0.9375rem;
303
+ font-weight: 600;
304
+ }
305
+
306
+ .explainer-task-controls {
307
+ display: flex;
308
+ flex-wrap: wrap;
309
+ align-items: center;
310
+ gap: 0.5rem 1rem;
311
+ margin: 0 0 0.5rem;
312
+ }
313
+
314
+ .explainer-task-controls[hidden] {
315
+ display: none;
316
+ }
317
+
318
+ .explainer-task-controls .explainer-task-number {
319
+ margin: 0;
320
+ }
321
+
322
+ .explainer-task-controls {
323
+ gap: 0.25rem;
324
+ }
325
+
326
+ /* "Zurück zum Tutor", on a page a tutor opened (via=tutor) */
327
+ /* what a copy for the running chat says: always on a line of its own, below its button */
328
+ .explainer-back > [role="status"],
329
+ .explainer-help-note > [role="status"] {
330
+ display: block;
331
+ }
332
+
333
+ .explainer-back > [role="status"]:not(:empty),
334
+ .explainer-help-note > [role="status"]:not(:empty) {
335
+ margin-top: 0.5rem;
336
+ }
337
+
338
+ .explainer-back button {
339
+ font: inherit;
340
+ min-height: 2.75rem;
341
+ padding: 0.5rem 1rem;
342
+ border: 2px solid var(--page-accent);
343
+ border-radius: 0.375rem;
344
+ background: var(--page-background);
345
+ color: var(--page-accent);
346
+ cursor: pointer;
347
+ }
348
+
349
+ .explainer-back button:focus-visible {
350
+ outline: 3px solid var(--page-text);
351
+ outline-offset: 2px;
352
+ }
353
+
354
+ /* the result line, selected for copying by hand when the clipboard refused it */
355
+ .explainer-back-line {
356
+ display: block;
357
+ box-sizing: border-box;
358
+ width: 100%;
359
+ margin-top: 0.5rem;
360
+ font: inherit;
361
+ color: var(--page-text);
362
+ background: var(--page-background);
363
+ border: 2px solid var(--page-border);
364
+ }
365
+
366
+ .explainer-back-line[hidden] {
367
+ display: none;
368
+ }
369
+
370
+ /* "Mit einem KI-Tutor lernen": a select with "Einschalten" beside it, a plain link per assistant without JavaScript */
371
+ .explainer-tutor-actions {
372
+ display: flex;
373
+ flex-wrap: wrap;
374
+ align-items: center;
375
+ gap: 0.5rem 1rem;
376
+ }
377
+
378
+ .explainer-tutor-way {
379
+ display: inline-flex;
380
+ flex-wrap: wrap;
381
+ align-items: center;
382
+ gap: 0.5rem;
383
+ }
384
+
385
+ .explainer-tutor-way[hidden],
386
+ .explainer-tutor-plain[hidden] {
387
+ display: none;
388
+ }
389
+
390
+ /* A content page's title with way A beside it, right-aligned on a wide screen; on a narrow one way A goes below the
391
+ title at full width, and so does the unfolded box */
392
+ .explainer-title-row {
393
+ display: flex;
394
+ flex-wrap: wrap;
395
+ align-items: center;
396
+ gap: 0.5rem 1rem;
397
+ margin: 0 0 1.5rem;
398
+ }
399
+
400
+ .explainer-title-row > h1 {
401
+ flex: 1 1 auto;
402
+ min-width: 0;
403
+ margin: 0;
404
+ }
405
+
406
+ .explainer-title-row > .explainer-tutor-page {
407
+ display: flex;
408
+ flex-direction: column;
409
+ align-items: flex-end;
410
+ margin: 0 0 0 auto;
411
+ }
412
+
413
+ .explainer-title-row > .explainer-tutor-page:has(> details[open]:not([hidden])) {
414
+ flex-basis: 100%;
415
+ align-items: stretch;
416
+ }
417
+
418
+ /* the status line under the button, a box of its own: green after a copy, the note colour when copying failed */
419
+ .explainer-tutor-page > .explainer-tutor-status {
420
+ align-self: stretch;
421
+ margin: 0.5rem 0 0;
422
+ padding: 0.75rem 1rem;
423
+ background: var(--explainer-note);
424
+ border-left: 4px solid var(--page-accent);
425
+ }
426
+
427
+ .explainer-tutor-page > .explainer-tutor-status[data-state="ok"] {
428
+ background: var(--explainer-example);
429
+ border-left-color: var(--explainer-done);
430
+ }
431
+
432
+ /* a failed copy is shown full width, also beside the title */
433
+ .explainer-title-row > .explainer-tutor-page:has(> .explainer-tutor-status[data-state="failed"]) {
434
+ flex-basis: 100%;
435
+ }
436
+
437
+ /* the button says "kopiert" itself after a copy; the line goes to screen readers only, until the screen is narrow */
438
+ .explainer-tutor-bar[data-done] .explainer-tutor-go-text {
439
+ display: none;
440
+ }
441
+
442
+ @media (min-width: 40.0625rem) {
443
+ .explainer-tutor-page > .explainer-tutor-status[data-state="ok"] {
444
+ position: absolute;
445
+ width: 1px;
446
+ height: 1px;
447
+ margin: -1px;
448
+ padding: 0;
449
+ border: 0;
450
+ overflow: hidden;
451
+ clip-path: inset(50%);
452
+ white-space: nowrap;
453
+ }
454
+ }
455
+
456
+ @media (max-width: 40rem) {
457
+ .explainer-title-row > .explainer-tutor-page {
458
+ flex-basis: 100%;
459
+ align-items: stretch;
460
+ margin: 0;
461
+ }
462
+
463
+ .explainer-tutor-bar[data-done] .explainer-tutor-go-done {
464
+ display: none;
465
+ }
466
+
467
+ .explainer-tutor-bar[data-done] .explainer-tutor-go-text {
468
+ display: inline;
469
+ }
470
+
471
+ .explainer-tutor-bar .explainer-tutor-go {
472
+ width: 100%;
473
+ justify-content: center;
474
+ }
475
+ }
476
+
477
+ /* Way A while no assistant is on: one folded line; unfolded, a box */
478
+
479
+ .explainer-tutor-off > summary {
480
+ cursor: pointer;
481
+ color: var(--page-accent);
482
+ padding: 0.625rem 0;
483
+ }
484
+
485
+ .explainer-tutor-off[open] {
486
+ padding: 0 1rem 0.25rem;
487
+ border: 2px solid var(--page-border);
488
+ border-radius: 0.375rem;
489
+ }
490
+
491
+ .explainer-tutor-off > p {
492
+ margin: 0.5rem 0;
493
+ }
494
+
495
+ .explainer-tutor-status:empty {
496
+ display: none;
497
+ }
498
+
499
+ /* The symbol of the learner's assistant: the first letter of its name in a circle */
500
+ .explainer-ki-icon {
501
+ display: inline-flex;
502
+ align-items: center;
503
+ justify-content: center;
504
+ flex: none;
505
+ width: 1.5rem;
506
+ height: 1.5rem;
507
+ border-radius: 50%;
508
+ background: var(--page-surface);
509
+ color: var(--page-text);
510
+ font-size: 0.75rem;
511
+ font-weight: 700;
512
+ line-height: 1;
513
+ }
514
+
515
+ /* Way A, switched on: one quiet button, the assistant's symbol and "Mit <name> lernen", outlined (the secondary kind) */
516
+ .explainer-tutor-bar {
517
+ display: flex;
518
+ margin: 0;
519
+ }
520
+
521
+ .explainer-tutor-bar[hidden],
522
+ .explainer-tutor-off[hidden] {
523
+ display: none;
524
+ }
525
+
526
+ .explainer-tutor-bar button,
527
+ .explainer-tutor-on {
528
+ font: inherit;
529
+ min-height: 2.75rem;
530
+ padding: 0.375rem 0.875rem;
531
+ border: 2px solid var(--page-accent);
532
+ border-radius: 0.375rem;
533
+ background: var(--page-background);
534
+ color: var(--page-accent);
535
+ cursor: pointer;
536
+ }
537
+
538
+ .explainer-tutor-bar .explainer-tutor-go {
539
+ display: inline-flex;
540
+ align-items: center;
541
+ gap: 0.5rem;
542
+ }
543
+
544
+ .explainer-tutor-on {
545
+ background: var(--page-accent);
546
+ color: var(--page-on-accent);
547
+ }
548
+
549
+ .explainer-tutor-go .explainer-ki-icon {
550
+ background: var(--page-accent);
551
+ color: var(--page-on-accent);
552
+ }
553
+
554
+ .explainer-tutor-select {
555
+ font: inherit;
556
+ min-height: 2.75rem;
557
+ padding: 0.375rem 0.5rem;
558
+ border: 2px solid var(--page-border);
559
+ border-radius: 0.375rem;
560
+ background: var(--page-background);
561
+ color: var(--page-text);
562
+ }
563
+
564
+ .explainer-tutor-note {
565
+ color: var(--page-muted);
566
+ font-size: 0.9375rem;
567
+ }
568
+
569
+ .explainer-tutor-bar button:focus-visible,
570
+ .explainer-tutor-on:focus-visible,
571
+ .explainer-tutor-select:focus-visible {
572
+ outline: 3px solid var(--page-text);
573
+ outline-offset: 2px;
574
+ }
575
+
576
+ /* Way B in every exercise, while a way to the tutor is on: one button in the row of "Prüfen" and "Lösung", plain
577
+ ("Hilfe"), standing out after a wrong answer ("Warum?"), filled on a page a tutor opened once the task is done
578
+ ("Zurück") */
579
+ .explainer-help-row {
580
+ margin: 0.75rem 0 0;
581
+ }
582
+
583
+ .explainer-help-row[hidden],
584
+ button.explainer-help[hidden],
585
+ .explainer-help-note[hidden] {
586
+ display: none;
587
+ }
588
+
589
+ button.explainer-help,
590
+ .question button.explainer-help {
591
+ display: inline-flex;
592
+ align-items: center;
593
+ gap: 0.375rem;
594
+ font: inherit;
595
+ min-height: 2.75rem;
596
+ padding: 0.375rem 0.75rem 0.375rem 0.375rem;
597
+ border: 2px solid var(--page-border);
598
+ border-radius: 0.375rem;
599
+ background: var(--page-background);
600
+ color: var(--page-text);
601
+ cursor: pointer;
602
+ }
603
+
604
+ button.explainer-help.explainer-help-why,
605
+ .question button.explainer-help.explainer-help-why {
606
+ border-color: var(--page-accent);
607
+ background: var(--page-surface);
608
+ color: var(--page-accent);
609
+ font-weight: 600;
610
+ }
611
+
612
+ button.explainer-help.explainer-help-back,
613
+ .question button.explainer-help.explainer-help-back {
614
+ border-color: var(--page-accent);
615
+ background: var(--page-accent);
616
+ color: var(--page-on-accent);
617
+ }
618
+
619
+ .explainer-help-why .explainer-ki-icon,
620
+ .explainer-help-back .explainer-ki-icon {
621
+ background: var(--page-accent);
622
+ color: var(--page-on-accent);
623
+ }
624
+
625
+ .explainer-help-back .explainer-ki-icon {
626
+ background: var(--page-on-accent);
627
+ color: var(--page-accent);
628
+ }
629
+
630
+ button.explainer-help:focus-visible {
631
+ outline: 3px solid var(--page-text);
632
+ outline-offset: 2px;
633
+ }
634
+
635
+ .explainer-help-note {
636
+ margin: 0.5rem 0 0;
637
+ color: var(--page-muted);
638
+ }
639
+
640
+ /* Usability: sections and exercises must be told apart at a glance. */
641
+
642
+ /* A section starts with a rule and room; a subsection is lighter */
643
+ .explainer > section.explainer-section,
644
+ .explainer-main > section.explainer-section {
645
+ margin-top: 2.5rem;
646
+ padding-top: 0.5rem;
647
+ border-top: 2px solid var(--page-border);
648
+ }
649
+
650
+ .explainer section.explainer-section > h2 {
651
+ margin: 0.75rem 0 0.75rem;
652
+ font-size: 1.5rem;
653
+ }
654
+
655
+ .explainer section.explainer-section section.explainer-section {
656
+ margin-top: 1.75rem;
657
+ padding-top: 0;
658
+ border-top: 0;
659
+ }
660
+
661
+ .explainer section.explainer-section section.explainer-section > h3 {
662
+ padding-left: 0.6rem;
663
+ border-left: 4px solid var(--page-accent);
664
+ font-size: 1.2rem;
665
+ }
666
+
667
+ /* An exercise is a card of its own with a label on top, apart from the explanation around it */
668
+ .explainer-exercise {
669
+ padding: 0 1rem 1rem;
670
+ border: 2px solid var(--page-accent);
671
+ border-radius: 0.75rem;
672
+ background: var(--page-background);
673
+ }
674
+
675
+ .explainer-exercise-label {
676
+ margin: 0 -1rem 1rem;
677
+ padding: 0.4rem 1rem;
678
+ border-radius: 0.5rem 0.5rem 0 0;
679
+ background: var(--page-accent);
680
+ color: var(--page-on-accent);
681
+ font-size: 0.9375rem;
682
+ font-weight: 700;
683
+ letter-spacing: 0.04em;
684
+ text-transform: uppercase;
685
+ }
686
+
687
+ .explainer-exercise-label::before {
688
+ content: "✎ ";
689
+ }
690
+
691
+ /* a long task text wraps inside its frame instead of over its border */
692
+ .explainer-exercise legend {
693
+ float: left;
694
+ width: 100%;
695
+ margin: 0 0 0.5rem;
696
+ padding: 0;
697
+ }
698
+
699
+ .explainer-exercise legend + * {
700
+ clear: both;
701
+ }
702
+
703
+ /* The solution is the part of an exercise one looks for: its own colour, a label that says what is behind it */
704
+ .explainer-exercise details.explainer-solution {
705
+ margin: 0.75rem 0;
706
+ padding: 0.25rem 0.75rem;
707
+ border: 1px solid var(--page-right);
708
+ border-left-width: 5px;
709
+ background: var(--page-right-background);
710
+ color: var(--page-right);
711
+ }
712
+
713
+ .explainer-exercise details.explainer-solution > summary::before {
714
+ content: "✔ ";
715
+ }
716
+
717
+ .explainer-exercise details.explainer-solution[open] > summary {
718
+ margin-bottom: 0.5rem;
719
+ }
720
+
721
+ .explainer-exercise details.explainer-solution p,
722
+ .explainer-exercise details.explainer-solution li {
723
+ color: var(--page-text);
724
+ }
725
+
726
+ /* the hint is lighter than the solution */
727
+ .explainer-exercise details.explainer-hint {
728
+ border-style: dashed;
729
+ }
730
+
731
+ .explainer-worked-task {
732
+ margin-bottom: 1.5rem;
733
+ padding-bottom: 1rem;
734
+ border-bottom: 1px dashed var(--page-border);
735
+ }
736
+
737
+ .explainer-worked-task:last-child {
738
+ border-bottom: 0;
739
+ }
740
+
741
+ .explainer-drawing .fig-on {
742
+ fill: var(--page-accent);
743
+ }
744
+
745
+ .explainer-drawing .fig-off {
746
+ fill: var(--page-background);
747
+ }
748
+
749
+ .explainer-drawing .fig-line {
750
+ stroke: var(--page-muted);
751
+ }
752
+
753
+ .explainer-drawing .fig-text {
754
+ fill: var(--page-text);
755
+ }
756
+
757
+ /* The choice of the learner's assistant on the start page, shown once the client module runs */
758
+ .explainer-tutor-choice[hidden] {
759
+ display: none;
760
+ }
761
+
762
+ .explainer-tutor-choice label {
763
+ display: flex;
764
+ flex-direction: column;
765
+ gap: 0.25rem;
766
+ font-weight: 600;
767
+ }
768
+
769
+ .explainer-tutor-choose {
770
+ font: inherit;
771
+ font-weight: 400;
772
+ min-height: 2.75rem;
773
+ max-width: 20rem;
774
+ padding: 0.375rem 0.5rem;
775
+ border: 2px solid var(--page-border);
776
+ border-radius: 0.375rem;
777
+ background: var(--page-background);
778
+ color: var(--page-text);
779
+ }
780
+
781
+ .explainer-tutor-choose:focus-visible {
782
+ outline: 3px solid var(--page-text);
783
+ outline-offset: 2px;
784
+ }
785
+
786
+ /* The choice of the assistant and, beside it, "Einstellungen", which opens the dialog of the learner's needs: a box per
787
+ need with its name, its sentences below in the muted colour, then where the choice holds and "Fertig" */
788
+ .explainer-tutor-choice {
789
+ display: flex;
790
+ align-items: flex-end;
791
+ gap: 0.5rem;
792
+ }
793
+
794
+ /* the select takes the room the gear leaves, up to its own width, so that both fit on a phone */
795
+ .explainer-tutor-choice > label {
796
+ flex: 0 1 20rem;
797
+ min-width: 0;
798
+ }
799
+
800
+ .explainer-tutor-choice .explainer-tutor-choose {
801
+ width: 100%;
802
+ }
803
+
804
+ .explainer-tutor-needs-open,
805
+ .explainer-tutor-needs-done {
806
+ font: inherit;
807
+ min-height: 2.75rem;
808
+ padding: 0.375rem 0.875rem;
809
+ border: 2px solid var(--page-accent);
810
+ border-radius: 0.375rem;
811
+ background: var(--page-background);
812
+ color: var(--page-accent);
813
+ cursor: pointer;
814
+ }
815
+
816
+ .explainer-tutor-needs-open {
817
+ display: inline-flex;
818
+ align-items: center;
819
+ justify-content: center;
820
+ width: 2.75rem;
821
+ padding: 0;
822
+ }
823
+
824
+ .explainer-tutor-needs-done {
825
+ background: var(--page-accent);
826
+ color: var(--page-on-accent);
827
+ }
828
+
829
+ .explainer-tutor-needs {
830
+ width: min(40rem, calc(100vw - 2rem));
831
+ max-height: calc(100dvh - 2rem);
832
+ padding: 1rem 1.25rem;
833
+ border: 1px solid var(--page-border);
834
+ border-radius: 0.5rem;
835
+ background: var(--page-background);
836
+ color: var(--page-text);
837
+ }
838
+
839
+ .explainer-tutor-needs::backdrop {
840
+ background: rgb(0 0 0 / 0.5);
841
+ }
842
+
843
+ .explainer-tutor-needs h2 {
844
+ margin-top: 0;
845
+ }
846
+
847
+ .explainer-tutor-need-choice {
848
+ display: grid;
849
+ grid-template-columns: auto 1fr;
850
+ gap: 0 0.5rem;
851
+ margin: 0.75rem 0;
852
+ }
853
+
854
+ .explainer-tutor-need-choice > input {
855
+ width: 1.25rem;
856
+ height: 1.25rem;
857
+ margin: 0.125rem 0 0;
858
+ }
859
+
860
+ .explainer-tutor-need-choice > label {
861
+ font-weight: 600;
862
+ }
863
+
864
+ .explainer-tutor-need-text {
865
+ grid-column: 2;
866
+ margin: 0;
867
+ color: var(--page-muted);
868
+ font-size: 0.9375rem;
869
+ }
870
+
871
+ .explainer-tutor-language-choice {
872
+ margin: 0 0 0.75rem 1.75rem;
873
+ }
874
+
875
+ .explainer-tutor-language-choice[hidden] {
876
+ display: none;
877
+ }
878
+
879
+ .explainer-tutor-language-choice label {
880
+ display: flex;
881
+ flex-direction: column;
882
+ gap: 0.25rem;
883
+ }
884
+
885
+ .explainer-tutor-language {
886
+ font: inherit;
887
+ min-height: 2.75rem;
888
+ max-width: 20rem;
889
+ padding: 0.375rem 0.5rem;
890
+ border: 2px solid var(--page-border);
891
+ border-radius: 0.375rem;
892
+ background: var(--page-background);
893
+ color: var(--page-text);
894
+ }
895
+
896
+ .explainer-tutor-needs-where {
897
+ display: flex;
898
+ flex-direction: column;
899
+ gap: 0.5rem;
900
+ margin: 1rem 0;
901
+ border: 1px solid var(--page-border);
902
+ border-radius: 0.375rem;
903
+ }
904
+
905
+ .explainer-tutor-needs-open:focus-visible,
906
+ .explainer-tutor-needs-done:focus-visible,
907
+ .explainer-tutor-language:focus-visible,
908
+ .explainer-tutor-need-choice > input:focus-visible,
909
+ .explainer-tutor-needs-where input:focus-visible {
910
+ outline: 3px solid var(--page-text);
911
+ outline-offset: 2px;
912
+ }
913
+
914
+ /* A video: a card with its title as a link, its channel and the note on privacy; with JavaScript the button that loads
915
+ the player and the choice to load every player directly; the player in the width of the page, 16:9 */
916
+ .explainer-video {
917
+ margin: 1.25rem 0;
918
+ padding: 0.75rem 1rem;
919
+ border: 1px solid var(--page-border);
920
+ border-radius: 0.375rem;
921
+ background: var(--page-surface);
922
+ }
923
+
924
+ .explainer-video figcaption {
925
+ font-weight: 600;
926
+ }
927
+
928
+ .explainer-video-channel {
929
+ display: block;
930
+ color: var(--page-muted);
931
+ font-weight: 400;
932
+ font-size: 0.9375rem;
933
+ }
934
+
935
+ .explainer-video-note {
936
+ margin: 0.5rem 0;
937
+ color: var(--page-muted);
938
+ font-size: 0.9375rem;
939
+ }
940
+
941
+ .explainer-video-controls {
942
+ display: flex;
943
+ flex-wrap: wrap;
944
+ align-items: center;
945
+ gap: 0.5rem 1rem;
946
+ margin: 0.5rem 0 0;
947
+ }
948
+
949
+ .explainer-video-controls[hidden] {
950
+ display: none;
951
+ }
952
+
953
+ .explainer-video-play {
954
+ font: inherit;
955
+ min-height: 2.75rem;
956
+ padding: 0.5rem 1rem;
957
+ border: 2px solid var(--page-accent);
958
+ border-radius: 0.375rem;
959
+ background: var(--page-accent);
960
+ color: var(--page-on-accent);
961
+ cursor: pointer;
962
+ }
963
+
964
+ .explainer-video-play:focus-visible,
965
+ .explainer-video-always input:focus-visible {
966
+ outline: 3px solid var(--page-text);
967
+ outline-offset: 2px;
968
+ }
969
+
970
+ .explainer-video-always {
971
+ display: inline-flex;
972
+ align-items: center;
973
+ gap: 0.5rem;
974
+ min-height: 2.75rem;
975
+ cursor: pointer;
976
+ }
977
+
978
+ .explainer-video-always input {
979
+ width: 1.25rem;
980
+ height: 1.25rem;
981
+ margin: 0;
982
+ }
983
+
984
+ .explainer-video-frame {
985
+ margin: 0 0 0.75rem;
986
+ aspect-ratio: 16 / 9;
987
+ }
988
+
989
+ .explainer-video-frame iframe {
990
+ display: block;
991
+ width: 100%;
992
+ height: 100%;
993
+ border: 0;
994
+ }
995
+
996
+ /* The self-assessment (assessment-client.ts): the offer on the start page or a chapter's page, its pages of exercises
997
+ without "Prüfen", and its result, a line per content page coloured by how it went */
998
+ .explainer-assessment-offer {
999
+ margin: 1.5rem 0;
1000
+ padding: 0 1rem 0.5rem;
1001
+ border: 2px solid var(--page-accent);
1002
+ border-radius: 0.75rem;
1003
+ }
1004
+
1005
+ .explainer-assessment-offer[hidden],
1006
+ .explainer-assessment[hidden],
1007
+ .explainer-assessment-intro[hidden],
1008
+ .explainer-assessment-step[hidden],
1009
+ .explainer-assessment-result[hidden],
1010
+ .explainer-assessment-nojs[hidden] {
1011
+ display: none;
1012
+ }
1013
+
1014
+ .explainer-assessment-link,
1015
+ .explainer-assessment button,
1016
+ .explainer-assessment-way {
1017
+ display: inline-flex;
1018
+ align-items: center;
1019
+ min-height: 2.75rem;
1020
+ padding: 0.375rem 0.875rem;
1021
+ border: 2px solid var(--page-accent);
1022
+ border-radius: 0.375rem;
1023
+ background: var(--page-background);
1024
+ color: var(--page-accent);
1025
+ font: inherit;
1026
+ text-decoration: none;
1027
+ cursor: pointer;
1028
+ }
1029
+
1030
+ .explainer-assessment-link,
1031
+ .explainer-assessment-begin,
1032
+ .explainer-assessment button.explainer-assessment-next,
1033
+ .explainer-assessment button.explainer-assessment-finish,
1034
+ .explainer-assessment button.explainer-assessment-go {
1035
+ background: var(--page-accent);
1036
+ color: var(--page-on-accent);
1037
+ }
1038
+
1039
+ .explainer-assessment-way {
1040
+ border-color: var(--page-border);
1041
+ color: var(--page-text);
1042
+ }
1043
+
1044
+ .explainer-assessment-link:focus-visible,
1045
+ .explainer-assessment button:focus-visible,
1046
+ .explainer-assessment-way:focus-visible {
1047
+ outline: 3px solid var(--page-accent);
1048
+ outline-offset: 2px;
1049
+ }
1050
+
1051
+ .explainer-assessment-items {
1052
+ margin: 0;
1053
+ padding: 0;
1054
+ list-style: none;
1055
+ }
1056
+
1057
+ .explainer-assessment-item {
1058
+ margin: 0 0 1.25rem;
1059
+ padding: 0 1rem 1rem;
1060
+ border: 2px solid var(--page-accent);
1061
+ border-radius: 0.75rem;
1062
+ }
1063
+
1064
+ .explainer-assessment-label {
1065
+ margin: 0 -1rem 1rem;
1066
+ padding: 0.4rem 1rem;
1067
+ border-radius: 0.5rem 0.5rem 0 0;
1068
+ background: var(--page-accent);
1069
+ color: var(--page-on-accent);
1070
+ font-size: 0.9375rem;
1071
+ font-weight: 700;
1072
+ }
1073
+
1074
+ /* a long task text wraps inside its frame instead of over its border */
1075
+ .explainer-assessment-item legend {
1076
+ float: left;
1077
+ width: 100%;
1078
+ margin: 0 0 0.5rem;
1079
+ padding: 0;
1080
+ }
1081
+
1082
+ .explainer-assessment-item legend + * {
1083
+ clear: both;
1084
+ }
1085
+
1086
+ .explainer-assessment-nav,
1087
+ .explainer-assessment-again,
1088
+ .explainer-assessment-tutor-actions {
1089
+ display: flex;
1090
+ flex-wrap: wrap;
1091
+ gap: 0.5rem;
1092
+ }
1093
+
1094
+ .explainer-assessment-pages {
1095
+ padding: 0;
1096
+ list-style: none;
1097
+ }
1098
+
1099
+ .explainer-assessment-page {
1100
+ margin: 0 0 0.5rem;
1101
+ padding: 0.5rem 0.75rem;
1102
+ border-left: 0.375rem solid var(--page-border);
1103
+ border-radius: 0.25rem;
1104
+ background: var(--page-surface);
1105
+ }
1106
+
1107
+ .explainer-assessment-page strong {
1108
+ display: block;
1109
+ }
1110
+
1111
+ .explainer-assessment-page[data-band="known"] {
1112
+ border-left-color: var(--page-right);
1113
+ background: var(--page-right-background);
1114
+ }
1115
+
1116
+ .explainer-assessment-page[data-band="partly"] {
1117
+ border-left-color: var(--page-muted);
1118
+ background: var(--explainer-note);
1119
+ }
1120
+
1121
+ .explainer-assessment-page[data-band="read"] {
1122
+ border-left-color: var(--page-wrong);
1123
+ background: var(--page-wrong-background);
1124
+ }
1125
+
1126
+ .explainer-assessment-page[data-band="unasked"] {
1127
+ color: var(--page-muted);
1128
+ }
1129
+
1130
+ .explainer-assessment-count {
1131
+ color: var(--page-muted);
1132
+ font-size: 0.9375rem;
1133
+ }
1134
+
1135
+ .explainer-assessment-tutor {
1136
+ margin: 1.5rem 0;
1137
+ padding: 0 1rem 0.5rem;
1138
+ border: 2px solid var(--page-border);
1139
+ border-radius: 0.75rem;
1140
+ }
1141
+
1142
+ .explainer-assessment-tutor-status:empty,
1143
+ .explainer-assessment-status:empty {
1144
+ display: none;
1145
+ }
1146
+
1147
+ /* An open task (open-task.ts): "Deine Lösung" as two equal choices, the text field or the photo, the tick boxes,
1148
+ the result. Its buttons are those of the questions, which style only buttons inside .question */
1149
+ .explainer-open-live {
1150
+ margin: 0 0 0.75rem;
1151
+ }
1152
+
1153
+ .explainer-open-choice {
1154
+ display: grid;
1155
+ grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
1156
+ gap: 0.5rem;
1157
+ margin: 0 0 0.75rem;
1158
+ padding: 0;
1159
+ border: 0;
1160
+ }
1161
+
1162
+ .explainer-open-choice legend {
1163
+ margin-bottom: 0.5rem;
1164
+ padding: 0;
1165
+ font-weight: 600;
1166
+ }
1167
+
1168
+ .explainer-open-choice label,
1169
+ .explainer-open-check label {
1170
+ display: flex;
1171
+ gap: 0.5rem;
1172
+ align-items: flex-start;
1173
+ min-height: 2.75rem;
1174
+ padding: 0.5rem 0.75rem;
1175
+ border: 1px solid var(--page-border);
1176
+ border-radius: 0.375rem;
1177
+ cursor: pointer;
1178
+ }
1179
+
1180
+ .explainer-open-choice label:has(input:checked) {
1181
+ border: 2px solid var(--page-accent);
1182
+ }
1183
+
1184
+ .explainer-open-choice input,
1185
+ .explainer-open-check input {
1186
+ width: 1.25rem;
1187
+ height: 1.25rem;
1188
+ margin: 0.15rem 0 0;
1189
+ flex-shrink: 0;
1190
+ accent-color: var(--page-accent);
1191
+ }
1192
+
1193
+ .explainer-open-text label {
1194
+ display: block;
1195
+ margin-bottom: 0.25rem;
1196
+ font-weight: 600;
1197
+ }
1198
+
1199
+ .explainer-open-text textarea {
1200
+ box-sizing: border-box;
1201
+ width: 100%;
1202
+ padding: 0.5rem 0.75rem;
1203
+ border: 1px solid var(--page-border);
1204
+ border-radius: 0.375rem;
1205
+ font: inherit;
1206
+ resize: vertical;
1207
+ }
1208
+
1209
+ /* the file input is the photo button: it opens the camera on a phone */
1210
+ .explainer-open-shoot {
1211
+ display: inline-flex;
1212
+ align-items: center;
1213
+ min-height: 2.75rem;
1214
+ padding: 0 1rem;
1215
+ border: 2px solid var(--page-accent);
1216
+ border-radius: 0.375rem;
1217
+ color: var(--page-accent);
1218
+ cursor: pointer;
1219
+ }
1220
+
1221
+ .explainer-open-shoot input {
1222
+ position: absolute;
1223
+ width: 1px;
1224
+ height: 1px;
1225
+ opacity: 0;
1226
+ }
1227
+
1228
+ .explainer-open-shoot:focus-within,
1229
+ .explainer-open-text textarea:focus-visible,
1230
+ .explainer-open-choice label:focus-within,
1231
+ .explainer-open-check label:focus-within,
1232
+ .explainer-open-live button:focus-visible {
1233
+ outline: 3px solid var(--page-text);
1234
+ outline-offset: 2px;
1235
+ }
1236
+
1237
+ .explainer-open-preview {
1238
+ display: block;
1239
+ max-width: 12rem;
1240
+ max-height: 16rem;
1241
+ margin: 0.75rem 0 0;
1242
+ border: 1px solid var(--page-border);
1243
+ border-radius: 0.375rem;
1244
+ }
1245
+
1246
+ .explainer-open-check {
1247
+ display: grid;
1248
+ gap: 0.5rem;
1249
+ margin: 0 0 0.75rem;
1250
+ padding: 0.75rem 1rem;
1251
+ border: 1px solid var(--page-border);
1252
+ border-radius: 0.375rem;
1253
+ }
1254
+
1255
+ .explainer-open-check legend {
1256
+ padding: 0 0.25rem;
1257
+ font-weight: 700;
1258
+ }
1259
+
1260
+ .explainer-open-check p,
1261
+ .explainer-open-need:empty,
1262
+ .explainer-open-locked {
1263
+ margin: 0;
1264
+ }
1265
+
1266
+ .explainer-open-locked {
1267
+ color: var(--page-muted);
1268
+ }
1269
+
1270
+ .explainer-open-live .question-actions button {
1271
+ font: inherit;
1272
+ padding: 0.5rem 1rem;
1273
+ border: 2px solid var(--page-accent);
1274
+ border-radius: 0.375rem;
1275
+ background: var(--page-accent);
1276
+ color: var(--page-on-accent);
1277
+ cursor: pointer;
1278
+ }
1279
+
1280
+ .explainer-open-live .question-actions button.explainer-open-change {
1281
+ background: var(--page-background);
1282
+ color: var(--page-accent);
1283
+ }