codetrail-cli 1.4.1__py3-none-any.whl

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 (171) hide show
  1. codetrail/__init__.py +3 -0
  2. codetrail/__main__.py +5 -0
  3. codetrail/agents/__init__.py +4 -0
  4. codetrail/agents/convert.py +92 -0
  5. codetrail/agents/export.py +284 -0
  6. codetrail/agents/instructions.py +42 -0
  7. codetrail/agents/protocol.py +111 -0
  8. codetrail/agents/tools.py +185 -0
  9. codetrail/assistant/__init__.py +161 -0
  10. codetrail/assistant/claude_code.py +330 -0
  11. codetrail/assistant/codex.py +260 -0
  12. codetrail/assistant/environment.py +66 -0
  13. codetrail/assistant/estimate.py +225 -0
  14. codetrail/assistant/fake.py +74 -0
  15. codetrail/assistant/guard.py +80 -0
  16. codetrail/assistant/guard_hook.py +58 -0
  17. codetrail/assistant/local.py +245 -0
  18. codetrail/assistant/local_tools.py +177 -0
  19. codetrail/assistant/prompts.py +404 -0
  20. codetrail/assistant/routing.py +86 -0
  21. codetrail/assistant/runner.py +120 -0
  22. codetrail/assistant/status.py +186 -0
  23. codetrail/assistant/usage.py +93 -0
  24. codetrail/bridge.py +292 -0
  25. codetrail/cli.py +407 -0
  26. codetrail/config.py +485 -0
  27. codetrail/database/__init__.py +60 -0
  28. codetrail/database/migrations/0001_facts.sql +34 -0
  29. codetrail/database/migrations/0002_settings.sql +5 -0
  30. codetrail/database/migrations/0003_learning.sql +34 -0
  31. codetrail/database/migrations/0004_assistant_usage.sql +24 -0
  32. codetrail/database/migrations/0005_page_failures.sql +7 -0
  33. codetrail/database/migrations/0006_metric_values.sql +9 -0
  34. codetrail/errors.py +5 -0
  35. codetrail/extract/__init__.py +249 -0
  36. codetrail/extract/adr.py +98 -0
  37. codetrail/extract/github_actions.py +140 -0
  38. codetrail/extract/openapi.py +101 -0
  39. codetrail/extract/python.py +221 -0
  40. codetrail/extract/swift.py +204 -0
  41. codetrail/extract/terraform.py +166 -0
  42. codetrail/extract/typescript.py +464 -0
  43. codetrail/facts/__init__.py +112 -0
  44. codetrail/facts/store.py +209 -0
  45. codetrail/generate/__init__.py +1 -0
  46. codetrail/generate/failures.py +31 -0
  47. codetrail/generate/outline.py +159 -0
  48. codetrail/generate/revise.py +72 -0
  49. codetrail/generate/run.py +530 -0
  50. codetrail/generate/scope.py +135 -0
  51. codetrail/generate/validate.py +218 -0
  52. codetrail/guide/__init__.py +147 -0
  53. codetrail/learn/__init__.py +143 -0
  54. codetrail/learn/routes.py +139 -0
  55. codetrail/locales/ar/LC_MESSAGES/codetrail.mo +0 -0
  56. codetrail/locales/ar/LC_MESSAGES/codetrail.po +2236 -0
  57. codetrail/locales/codetrail.pot +1942 -0
  58. codetrail/lock.py +114 -0
  59. codetrail/metrics/__init__.py +6 -0
  60. codetrail/metrics/activity.py +96 -0
  61. codetrail/metrics/churn.py +156 -0
  62. codetrail/metrics/commits.py +45 -0
  63. codetrail/metrics/coverage.py +114 -0
  64. codetrail/metrics/decisions.py +77 -0
  65. codetrail/metrics/history.py +47 -0
  66. codetrail/metrics/inventory.py +63 -0
  67. codetrail/metrics/rationale.py +74 -0
  68. codetrail/metrics/releases.py +26 -0
  69. codetrail/metrics/report.py +111 -0
  70. codetrail/metrics/repository.py +128 -0
  71. codetrail/metrics/size.py +95 -0
  72. codetrail/py.typed +0 -0
  73. codetrail/remove.py +50 -0
  74. codetrail/repo/__init__.py +4 -0
  75. codetrail/repo/git.py +56 -0
  76. codetrail/repo/gitleaks.toml +6 -0
  77. codetrail/repo/history.py +262 -0
  78. codetrail/repo/mirror.py +137 -0
  79. codetrail/repo/refresh.py +41 -0
  80. codetrail/repo/rules.py +83 -0
  81. codetrail/repo/secrets.py +145 -0
  82. codetrail/repo/signal.py +65 -0
  83. codetrail/repo/source.py +166 -0
  84. codetrail/search.py +178 -0
  85. codetrail/server.py +45 -0
  86. codetrail/system.py +484 -0
  87. codetrail/update.py +276 -0
  88. codetrail/web/__init__.py +1 -0
  89. codetrail/web/app.py +897 -0
  90. codetrail/web/diagrams.py +414 -0
  91. codetrail/web/documentation.py +146 -0
  92. codetrail/web/i18n.py +44 -0
  93. codetrail/web/navigation.py +127 -0
  94. codetrail/web/render.py +126 -0
  95. codetrail/web/repository_view.py +230 -0
  96. codetrail/web/security.py +171 -0
  97. codetrail/web/static/brand/favicon.svg +1 -0
  98. codetrail/web/static/brand/mark.svg +1 -0
  99. codetrail/web/static/css/base.css +192 -0
  100. codetrail/web/static/css/components.css +2254 -0
  101. codetrail/web/static/css/content.css +310 -0
  102. codetrail/web/static/css/layout.css +410 -0
  103. codetrail/web/static/css/print.css +42 -0
  104. codetrail/web/static/css/tokens.css +228 -0
  105. codetrail/web/static/js/api.js +49 -0
  106. codetrail/web/static/js/ask.js +182 -0
  107. codetrail/web/static/js/d2-worker.js +34 -0
  108. codetrail/web/static/js/d2.js +28 -0
  109. codetrail/web/static/js/diagram.js +52 -0
  110. codetrail/web/static/js/documentation.js +24 -0
  111. codetrail/web/static/js/learning.js +47 -0
  112. codetrail/web/static/js/main.js +38 -0
  113. codetrail/web/static/js/outline.js +44 -0
  114. codetrail/web/static/js/palette.js +211 -0
  115. codetrail/web/static/js/repository.js +528 -0
  116. codetrail/web/static/js/resize.js +126 -0
  117. codetrail/web/static/js/shortcuts.js +87 -0
  118. codetrail/web/static/js/sidebar.js +194 -0
  119. codetrail/web/static/js/theme-init.js +27 -0
  120. codetrail/web/static/js/theme.js +42 -0
  121. codetrail/web/static/js/update.js +107 -0
  122. codetrail/web/static/vendor/d2/LICENSE +375 -0
  123. codetrail/web/static/vendor/d2/LICENSE-elk +263 -0
  124. codetrail/web/static/vendor/d2/LICENSE-wasm_exec +27 -0
  125. codetrail/web/static/vendor/d2/VERSION +12 -0
  126. codetrail/web/static/vendor/d2/d2.wasm +0 -0
  127. codetrail/web/static/vendor/d2/elk.js +105914 -0
  128. codetrail/web/static/vendor/d2/wasm_exec.js +656 -0
  129. codetrail/web/static/vendor/inter/InterVariable-Italic.woff2 +0 -0
  130. codetrail/web/static/vendor/inter/InterVariable.woff2 +0 -0
  131. codetrail/web/static/vendor/inter/LICENSE.txt +92 -0
  132. codetrail/web/static/vendor/inter/VERSION +6 -0
  133. codetrail/web/static/vendor/noto-sans-arabic/NotoSansArabic-wght.woff2 +0 -0
  134. codetrail/web/static/vendor/noto-sans-arabic/OFL.txt +93 -0
  135. codetrail/web/static/vendor/noto-sans-arabic/VERSION +12 -0
  136. codetrail/web/target_view.py +63 -0
  137. codetrail/web/templates/answers.html +25 -0
  138. codetrail/web/templates/area.html +46 -0
  139. codetrail/web/templates/base.html +37 -0
  140. codetrail/web/templates/decisions.html +30 -0
  141. codetrail/web/templates/diagram.html +10 -0
  142. codetrail/web/templates/digests.html +24 -0
  143. codetrail/web/templates/documentation.html +247 -0
  144. codetrail/web/templates/error.html +9 -0
  145. codetrail/web/templates/estimate.html +48 -0
  146. codetrail/web/templates/fact.html +29 -0
  147. codetrail/web/templates/home.html +196 -0
  148. codetrail/web/templates/layout/ask_panel.html +27 -0
  149. codetrail/web/templates/layout/header.html +32 -0
  150. codetrail/web/templates/layout/icons.html +27 -0
  151. codetrail/web/templates/layout/outline.html +4 -0
  152. codetrail/web/templates/layout/palette.html +27 -0
  153. codetrail/web/templates/layout/shortcuts.html +27 -0
  154. codetrail/web/templates/layout/sidebar.html +79 -0
  155. codetrail/web/templates/layout/update_dialog.html +18 -0
  156. codetrail/web/templates/macros.html +13 -0
  157. codetrail/web/templates/page.html +93 -0
  158. codetrail/web/templates/progress.html +46 -0
  159. codetrail/web/templates/repository.html +369 -0
  160. codetrail/web/templates/search.html +31 -0
  161. codetrail/web/templates/source.html +15 -0
  162. codetrail/web/templates/system.html +43 -0
  163. codetrail/web/templates/system_arrows.html +17 -0
  164. codetrail/web/templates/system_legend.html +9 -0
  165. codetrail/web/templates/update_log.html +30 -0
  166. codetrail/web/trend.py +22 -0
  167. codetrail_cli-1.4.1.dist-info/METADATA +372 -0
  168. codetrail_cli-1.4.1.dist-info/RECORD +171 -0
  169. codetrail_cli-1.4.1.dist-info/WHEEL +4 -0
  170. codetrail_cli-1.4.1.dist-info/entry_points.txt +3 -0
  171. codetrail_cli-1.4.1.dist-info/licenses/LICENSE +202 -0
@@ -0,0 +1,310 @@
1
+ /* Guide content: pages, rationale callouts, diagrams, checks, source and diffs. */
2
+
3
+ .prose {
4
+ font-size: 1rem;
5
+ }
6
+
7
+ .prose > :first-child {
8
+ margin-block-start: 0;
9
+ }
10
+
11
+ .prose ul,
12
+ .prose ol {
13
+ padding-inline-start: 1.4em;
14
+ }
15
+
16
+ .prose li + li {
17
+ margin-block-start: var(--space-1);
18
+ }
19
+
20
+ .prose pre {
21
+ padding: var(--space-4);
22
+ border: 1px solid var(--line);
23
+ border-radius: var(--radius);
24
+ background: var(--card);
25
+ font-size: 0.85rem;
26
+ line-height: 1.55;
27
+ }
28
+
29
+ .prose blockquote {
30
+ margin: var(--space-4) 0;
31
+ padding-inline-start: var(--space-4);
32
+ border-inline-start: 3px solid var(--line-strong);
33
+ color: var(--text-muted);
34
+ }
35
+
36
+ .prose table {
37
+ margin-block: var(--space-4);
38
+ font-size: 0.92rem;
39
+ }
40
+
41
+ .prose h2,
42
+ .prose h3 {
43
+ scroll-margin-block-start: calc(var(--header-height) + var(--space-4));
44
+ }
45
+
46
+ .rationale {
47
+ margin-block: var(--space-5);
48
+ padding: var(--space-3) var(--space-4);
49
+ border: 1px solid var(--line);
50
+ border-inline-start: 3px solid var(--line-strong);
51
+ border-radius: var(--radius);
52
+ border-start-start-radius: 0;
53
+ border-end-start-radius: 0;
54
+ background: var(--card);
55
+ }
56
+
57
+ .rationale.documented {
58
+ border-color: color-mix(in srgb, var(--documented) 25%, var(--line));
59
+ border-inline-start-color: var(--documented);
60
+ background: var(--documented-tint);
61
+ }
62
+
63
+ .rationale.inferred {
64
+ border-color: color-mix(in srgb, var(--inferred) 25%, var(--line));
65
+ border-inline-start-color: var(--inferred);
66
+ background: var(--inferred-tint);
67
+ }
68
+
69
+ .rationale-label {
70
+ display: flex;
71
+ align-items: center;
72
+ gap: var(--space-2);
73
+ margin: 0 0 var(--space-1);
74
+ color: var(--text-muted);
75
+ font-size: 0.8rem;
76
+ font-weight: 600;
77
+ }
78
+
79
+ .rationale.documented .rationale-label {
80
+ color: var(--accent-text);
81
+ }
82
+
83
+ .rationale.inferred .rationale-label {
84
+ color: var(--inferred-text);
85
+ }
86
+
87
+ .rationale p:last-child {
88
+ margin-block-end: 0;
89
+ }
90
+
91
+ .diagram-block {
92
+ margin-block: var(--space-6);
93
+ padding: var(--space-4);
94
+ border: 1px solid var(--line);
95
+ border-radius: var(--radius-card);
96
+ background: var(--card);
97
+ }
98
+
99
+ .diagram-block pre.diagram {
100
+ margin: 0;
101
+ color: var(--text-faint);
102
+ font-size: 0.72rem;
103
+ white-space: pre-wrap;
104
+ }
105
+
106
+ th.align-left,
107
+ td.align-left {
108
+ text-align: start;
109
+ }
110
+
111
+ th.align-center,
112
+ td.align-center {
113
+ text-align: center;
114
+ }
115
+
116
+ th.align-right,
117
+ td.align-right {
118
+ text-align: end;
119
+ }
120
+
121
+ .diagram-svg {
122
+ overflow-x: auto;
123
+ text-align: center;
124
+ }
125
+
126
+ .diagram-svg img {
127
+ max-inline-size: 100%;
128
+ block-size: auto;
129
+ }
130
+
131
+ .diagram-block.enlarged .diagram-svg img {
132
+ max-inline-size: none;
133
+ }
134
+
135
+ .diagram-tools {
136
+ display: flex;
137
+ justify-content: flex-end;
138
+ gap: var(--space-2);
139
+ }
140
+
141
+ .diagram-block figcaption {
142
+ margin-block-start: var(--space-2);
143
+ font-size: 0.85rem;
144
+ }
145
+
146
+ .diagram-block details summary {
147
+ color: var(--text-muted);
148
+ cursor: pointer;
149
+ }
150
+
151
+ /* The system diagram's legend: one small shape or line per kind, in the interface language (design 17.4). */
152
+ .legend {
153
+ display: flex;
154
+ flex-wrap: wrap;
155
+ gap: var(--space-2) var(--space-5);
156
+ margin: var(--space-3) 0 0;
157
+ font-size: 0.85rem;
158
+ color: var(--text-muted);
159
+ }
160
+
161
+ .legend div {
162
+ display: flex;
163
+ align-items: center;
164
+ gap: var(--space-2);
165
+ }
166
+
167
+ .legend dt,
168
+ .legend dd {
169
+ margin: 0;
170
+ }
171
+
172
+ .legend-shape {
173
+ display: inline-block;
174
+ inline-size: 22px;
175
+ block-size: 14px;
176
+ border: 1.5px solid var(--line-strong);
177
+ background: var(--card);
178
+ }
179
+
180
+ .legend-rounded {
181
+ border-radius: 5px;
182
+ }
183
+
184
+ .legend-document {
185
+ border-radius: 0 0 40% 40% / 0 0 5px 5px;
186
+ }
187
+
188
+ .legend-double {
189
+ border-style: double;
190
+ border-width: 4px;
191
+ }
192
+
193
+ .legend-stadium {
194
+ border-radius: 999px;
195
+ }
196
+
197
+ .legend-line {
198
+ display: inline-block;
199
+ inline-size: 26px;
200
+ border-block-start: 2px solid var(--text-muted);
201
+ }
202
+
203
+ .legend-dashed {
204
+ border-block-start-style: dashed;
205
+ }
206
+
207
+ .system-parts td {
208
+ overflow-wrap: anywhere;
209
+ }
210
+
211
+ .checks {
212
+ margin-block-start: var(--space-12);
213
+ }
214
+
215
+ .checks .check {
216
+ display: grid;
217
+ gap: var(--space-3);
218
+ margin-block-end: var(--space-4);
219
+ padding: var(--space-5);
220
+ border: 1px solid var(--line);
221
+ border-radius: var(--radius-card);
222
+ background: var(--raised);
223
+ }
224
+
225
+ .check-question {
226
+ display: flex;
227
+ align-items: flex-start;
228
+ justify-content: space-between;
229
+ gap: var(--space-3);
230
+ margin: 0;
231
+ font-weight: 600;
232
+ }
233
+
234
+ .check-row {
235
+ display: flex;
236
+ flex-wrap: wrap;
237
+ align-items: center;
238
+ gap: var(--space-3);
239
+ }
240
+
241
+ .feedback {
242
+ margin: 0;
243
+ color: var(--text-muted);
244
+ font-size: 0.92rem;
245
+ }
246
+
247
+ .feedback:empty {
248
+ display: none;
249
+ }
250
+
251
+ .changes pre {
252
+ padding: var(--space-3);
253
+ border-radius: var(--radius);
254
+ background: var(--card);
255
+ font-size: 0.82rem;
256
+ }
257
+
258
+ .changes pre span.added {
259
+ color: var(--learned);
260
+ }
261
+
262
+ .changes pre span.removed {
263
+ color: var(--inferred-text);
264
+ }
265
+
266
+ pre.source {
267
+ margin: 0;
268
+ padding: var(--space-3) 0;
269
+ border: 1px solid var(--line);
270
+ border-radius: var(--radius-card);
271
+ background: var(--card);
272
+ font: 0.84rem/1.6 var(--font-mono);
273
+ counter-reset: line;
274
+ }
275
+
276
+ pre.source > span {
277
+ display: block;
278
+ padding-inline-end: var(--space-4);
279
+ }
280
+
281
+ pre.source a.line {
282
+ display: inline-block;
283
+ inline-size: 4.5rem;
284
+ padding-inline-end: var(--space-4);
285
+ color: var(--text-faint);
286
+ text-align: end;
287
+ user-select: none;
288
+ }
289
+
290
+ pre.source span:target {
291
+ background: color-mix(in srgb, var(--accent) 16%, transparent);
292
+ }
293
+
294
+ .files {
295
+ columns: 2 18rem;
296
+ margin: 0;
297
+ padding: 0;
298
+ list-style: none;
299
+ font-family: var(--font-mono);
300
+ font-size: 0.82rem;
301
+ }
302
+
303
+ .files li {
304
+ padding-block: 2px;
305
+ break-inside: avoid;
306
+ }
307
+
308
+ .attributes th {
309
+ inline-size: 30%;
310
+ }
@@ -0,0 +1,410 @@
1
+ /* The shell (design sections 16.1 and 22): a header, then the sidebar, the reading column and the outline. The header
2
+ and the sidebar are one tinted frame; the page is a card inside it. Below 1200px the outline goes; below 900px the
3
+ sidebar moves behind the menu button. */
4
+
5
+ body {
6
+ background: var(--sidebar);
7
+ }
8
+
9
+ .topbar {
10
+ position: sticky;
11
+ inset-block-start: 0;
12
+ z-index: 30;
13
+ display: flex;
14
+ align-items: center;
15
+ gap: var(--space-4);
16
+ block-size: var(--header-height);
17
+ padding-inline: var(--space-5);
18
+ background: var(--sidebar);
19
+ }
20
+
21
+ .brand {
22
+ display: inline-flex;
23
+ align-items: center;
24
+ gap: var(--space-2);
25
+ color: var(--text);
26
+ font-weight: 600;
27
+ letter-spacing: -0.01em;
28
+ white-space: nowrap;
29
+ }
30
+
31
+ .brand:hover {
32
+ text-decoration: none;
33
+ }
34
+
35
+ .brand img {
36
+ inline-size: 24px;
37
+ block-size: 24px;
38
+ }
39
+
40
+ .target {
41
+ display: inline-flex;
42
+ align-items: baseline;
43
+ gap: var(--space-2);
44
+ padding-inline-start: var(--space-4);
45
+ border-inline-start: 1px solid var(--line);
46
+ color: var(--text);
47
+ font-weight: 500;
48
+ white-space: nowrap;
49
+ overflow: hidden;
50
+ text-overflow: ellipsis;
51
+ min-inline-size: 0;
52
+ }
53
+
54
+ .target-meta {
55
+ color: var(--text-faint);
56
+ font-family: var(--font-mono);
57
+ font-size: 0.78rem;
58
+ font-weight: 400;
59
+ }
60
+
61
+ .topbar-search {
62
+ flex: 1;
63
+ display: flex;
64
+ justify-content: center;
65
+ min-inline-size: 0;
66
+ }
67
+
68
+ .topbar-actions {
69
+ display: flex;
70
+ align-items: center;
71
+ gap: var(--space-2);
72
+ }
73
+
74
+ .topbar .menu-button {
75
+ display: none;
76
+ }
77
+
78
+ .shell {
79
+ display: grid;
80
+ grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
81
+ min-block-size: calc(100vh - var(--header-height));
82
+ }
83
+
84
+ /* The article and its outline are one group, centered in the space beside the sidebar, so on a wide screen the text
85
+ doesn't hug the sidebar and the outline stays next to what it outlines. A page with no outline centers one wider
86
+ column instead. */
87
+ .page-area {
88
+ display: grid;
89
+ grid-template-columns: minmax(0, var(--article-width)) var(--outline-width);
90
+ justify-content: center;
91
+ column-gap: var(--space-12);
92
+ margin-inline-end: var(--space-2);
93
+ margin-block-end: var(--space-2);
94
+ padding-inline: var(--space-12);
95
+ border-radius: var(--radius-card);
96
+ background: var(--page);
97
+ box-shadow: var(--shadow-card);
98
+ }
99
+
100
+ .page-area:not(:has(> .outline:not([hidden]))) {
101
+ grid-template-columns: minmax(0, var(--wide-width));
102
+ }
103
+
104
+ .sidebar {
105
+ position: sticky;
106
+ inset-block-start: var(--header-height);
107
+ block-size: calc(100vh - var(--header-height));
108
+ overflow-y: auto;
109
+ padding: var(--space-2) var(--space-2) var(--space-10);
110
+ overscroll-behavior: contain;
111
+ }
112
+
113
+ /* Hidden (design section 22.1): the page takes the whole width, and the sidebar waits off screen as a floating card
114
+ that peeks in from the window's start edge. Only above 900px: below, it's the drawer. */
115
+ .sidebar-edge {
116
+ display: none;
117
+ position: fixed;
118
+ z-index: 27;
119
+ inset-block: var(--header-height) 0;
120
+ inset-inline-start: 0;
121
+ inline-size: 10px;
122
+ padding: 0;
123
+ border: 0;
124
+ background: transparent;
125
+ cursor: pointer;
126
+ }
127
+
128
+ .sidebar-edge::after {
129
+ content: "";
130
+ position: absolute;
131
+ inset-block-start: 45%;
132
+ inset-inline-start: 3px;
133
+ inline-size: 3px;
134
+ block-size: 44px;
135
+ border-radius: 2px;
136
+ background: var(--line-strong);
137
+ }
138
+
139
+ .sidebar-edge:focus-visible {
140
+ box-shadow: var(--focus);
141
+ outline: none;
142
+ }
143
+
144
+ @media (min-width: 901px) {
145
+ :root[data-sidebar="hidden"] .shell {
146
+ grid-template-columns: minmax(0, 1fr);
147
+ }
148
+
149
+ :root[data-sidebar="hidden"] .page-area {
150
+ margin-inline-start: var(--space-2);
151
+ }
152
+
153
+ :root[data-sidebar="hidden"] .sidebar {
154
+ position: fixed;
155
+ z-index: 28;
156
+ inset-block: calc(var(--header-height) + var(--space-2)) var(--space-2);
157
+ inset-inline-start: var(--space-2);
158
+ inline-size: var(--sidebar-width);
159
+ block-size: auto;
160
+ border-radius: var(--radius-card);
161
+ background: var(--sidebar);
162
+ box-shadow: var(--shadow-float);
163
+ transform: translateX(calc(-100% - var(--space-4)));
164
+ visibility: hidden;
165
+ transition: transform var(--duration) var(--ease), visibility 0s linear var(--duration);
166
+ }
167
+
168
+ :root[dir="rtl"][data-sidebar="hidden"] .sidebar {
169
+ transform: translateX(calc(100% + var(--space-4)));
170
+ }
171
+
172
+ :root[data-sidebar="hidden"] body.sidebar-peek .sidebar {
173
+ transform: none;
174
+ visibility: visible;
175
+ transition: transform var(--duration) var(--ease), visibility 0s;
176
+ }
177
+
178
+ :root[data-sidebar="hidden"] .resize-sidebar {
179
+ display: none;
180
+ }
181
+
182
+ :root[data-sidebar="hidden"] .sidebar-edge {
183
+ display: block;
184
+ }
185
+ }
186
+
187
+ .content {
188
+ min-inline-size: 0;
189
+ padding-block: var(--space-10) var(--space-12);
190
+ }
191
+
192
+ .content:focus {
193
+ outline: none;
194
+ }
195
+
196
+ .reading {
197
+ max-inline-size: var(--article-width);
198
+ margin-inline: auto;
199
+ }
200
+
201
+ .wide {
202
+ max-inline-size: var(--wide-width);
203
+ }
204
+
205
+ .outline {
206
+ position: sticky;
207
+ inset-block-start: var(--header-height);
208
+ block-size: calc(100vh - var(--header-height));
209
+ overflow-y: auto;
210
+ padding-block: var(--space-10) var(--space-8);
211
+ }
212
+
213
+ .outline-title {
214
+ margin: 0 0 var(--space-2);
215
+ color: var(--text-faint);
216
+ font-size: 0.72rem;
217
+ font-weight: 600;
218
+ letter-spacing: 0.06em;
219
+ text-transform: uppercase;
220
+ }
221
+
222
+ .outline ol {
223
+ margin: 0;
224
+ padding: 0;
225
+ list-style: none;
226
+ border-inline-start: 1px solid var(--line);
227
+ }
228
+
229
+ .outline a {
230
+ display: block;
231
+ margin-inline-start: -1px;
232
+ padding: 3px var(--space-3);
233
+ border-inline-start: 2px solid transparent;
234
+ color: var(--text-muted);
235
+ font-size: 0.84rem;
236
+ line-height: 1.4;
237
+ }
238
+
239
+ .outline .depth-3 a {
240
+ padding-inline-start: var(--space-6);
241
+ }
242
+
243
+ .outline a:hover {
244
+ color: var(--text);
245
+ text-decoration: none;
246
+ }
247
+
248
+ .outline a[aria-current="location"] {
249
+ border-inline-start-color: var(--accent);
250
+ color: var(--accent-text);
251
+ font-weight: 500;
252
+ }
253
+
254
+ [dir="rtl"] .icon-flip {
255
+ transform: scaleX(-1);
256
+ }
257
+
258
+ .footer {
259
+ margin-block-start: var(--space-12);
260
+ padding-block-start: var(--space-5);
261
+ border-block-start: 1px solid var(--line);
262
+ color: var(--text-faint);
263
+ font-size: 0.8rem;
264
+ }
265
+
266
+ /* With the Ask panel open on a wide screen, the page makes room for it instead of being covered. */
267
+ @media (min-width: 1201px) {
268
+ body.ask-open .shell {
269
+ grid-template-columns: var(--sidebar-width) minmax(0, 1fr) var(--panel-width);
270
+ }
271
+
272
+ :root[data-sidebar="hidden"] body.ask-open .shell {
273
+ grid-template-columns: minmax(0, 1fr) var(--panel-width);
274
+ }
275
+
276
+ body.ask-open .page-area {
277
+ grid-template-columns: minmax(0, var(--article-width));
278
+ }
279
+
280
+ body.ask-open .outline {
281
+ display: none;
282
+ }
283
+ }
284
+
285
+ @media (max-width: 1200px) {
286
+ .page-area,
287
+ .page-area:not(:has(> .outline:not([hidden]))) {
288
+ grid-template-columns: minmax(0, var(--wide-width));
289
+ }
290
+
291
+ .outline {
292
+ display: none;
293
+ }
294
+ }
295
+
296
+ @media (max-width: 900px) {
297
+ .topbar .menu-button {
298
+ display: inline-flex;
299
+ }
300
+
301
+ .target,
302
+ .topbar-actions .language,
303
+ .search-hint,
304
+ .topbar .sidebar-toggle {
305
+ display: none;
306
+ }
307
+
308
+ .shell {
309
+ grid-template-columns: minmax(0, 1fr);
310
+ }
311
+
312
+ .sidebar {
313
+ position: fixed;
314
+ inset-block: var(--header-height) 0;
315
+ inset-inline-start: 0;
316
+ z-index: 25;
317
+ inline-size: min(var(--sidebar-width), 86vw);
318
+ block-size: auto;
319
+ background: var(--sidebar);
320
+ transform: translateX(-100%);
321
+ transition: transform var(--duration) var(--ease);
322
+ box-shadow: var(--shadow-float);
323
+ }
324
+
325
+ [dir="rtl"] .sidebar {
326
+ transform: translateX(100%);
327
+ }
328
+
329
+ body.menu-open .sidebar {
330
+ transform: none;
331
+ }
332
+
333
+ .page-area {
334
+ margin: 0;
335
+ padding-inline: var(--space-4);
336
+ border-radius: 0;
337
+ box-shadow: none;
338
+ }
339
+
340
+ .content {
341
+ padding-block: var(--space-6) var(--space-10);
342
+ }
343
+ }
344
+
345
+ @media (max-width: 560px) {
346
+ .topbar {
347
+ gap: var(--space-2);
348
+ padding-inline: var(--space-3);
349
+ }
350
+
351
+ .brand span,
352
+ .topbar-actions .button span,
353
+ .topbar-actions [data-shortcuts-open] {
354
+ display: none;
355
+ }
356
+ }
357
+
358
+ /* Resize handles on the sidebar's and the Ask panel's inner edges (design section 16.1). */
359
+ .resize-handle {
360
+ position: fixed;
361
+ z-index: 26;
362
+ inline-size: 9px;
363
+ cursor: col-resize;
364
+ touch-action: none;
365
+ }
366
+
367
+ .resize-handle::after {
368
+ content: "";
369
+ position: absolute;
370
+ inset-block: 0;
371
+ inset-inline-start: 4px;
372
+ inline-size: 1px;
373
+ background: transparent;
374
+ transition: background var(--duration) var(--ease);
375
+ }
376
+
377
+ .resize-handle:hover::after,
378
+ .resize-handle:focus-visible::after,
379
+ .resize-handle.dragging::after {
380
+ inset-inline-start: 3px;
381
+ inline-size: 3px;
382
+ background: var(--accent);
383
+ }
384
+
385
+ .resize-handle:focus-visible {
386
+ box-shadow: none;
387
+ }
388
+
389
+ .resize-sidebar {
390
+ inset-block: var(--header-height) 0;
391
+ inset-inline-start: calc(var(--sidebar-width) - 5px);
392
+ }
393
+
394
+ .ask-panel .resize-panel {
395
+ position: absolute;
396
+ inset-block: 0;
397
+ inset-inline-start: -5px;
398
+ }
399
+
400
+ body.resizing {
401
+ cursor: col-resize;
402
+ user-select: none;
403
+ }
404
+
405
+ @media (max-width: 900px) {
406
+ .resize-handle,
407
+ .ask-panel .resize-panel {
408
+ display: none;
409
+ }
410
+ }