483 lines · 15 KB
Raw Download
1
/* Minimal stylesheet — system fonts only, single-column responsive layout. */
2
3
:root {
4
    --bg: #ffffff;
5
    --fg: #1f2328;
6
    --muted: #656d76;
7
    --border: #d0d7de;
8
    --link: #0969da;
9
    --accent: #0969da;
10
    --card: #f6f8fa;
11
    --code-bg: #f6f8fa;
12
    --ln: #8c959f;
13
    /* syntax tokens — GitHub Primer (light) */
14
    --tok-com:  #6e7781;
15
    --tok-str:  #0a3069;
16
    --tok-num:  #0550ae;
17
    --tok-kw:   #cf222e;
18
    --tok-var:  #953800;
19
    --tok-fn:   #8250df;
20
    --tok-tag:  #116329;
21
    --tok-attr: #0550ae;
22
    --tok-sel:  #8250df;
23
}
24
25
@media (prefers-color-scheme: dark) {
26
    :root {
27
        --bg: #0d1117;
28
        --fg: #e6edf3;
29
        --muted: #8b949e;
30
        --border: #30363d;
31
        --link: #58a6ff;
32
        --accent: #58a6ff;
33
        --card: #161b22;
34
        --code-bg: #161b22;
35
        --ln: #6e7681;
36
        /* syntax tokens — GitHub Primer (dark) */
37
        --tok-com:  #8b949e;
38
        --tok-str:  #a5d6ff;
39
        --tok-num:  #79c0ff;
40
        --tok-kw:   #ff7b72;
41
        --tok-var:  #ffa657;
42
        --tok-fn:   #d2a8ff;
43
        --tok-tag:  #7ee787;
44
        --tok-attr: #79c0ff;
45
        --tok-sel:  #d2a8ff;
46
    }
47
}
48
49
* { box-sizing: border-box; }
50
51
body {
52
    margin: 0;
53
    background: var(--bg);
54
    color: var(--fg);
55
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
56
    line-height: 1.5;
57
    font-size: 16px;
58
    /* Stop mobile browsers auto-inflating large text blocks (e.g. code),
59
       which desktop never does — keeps code sized as authored and aligned
60
       with its line numbers. */
61
    -webkit-text-size-adjust: 100%;
62
    text-size-adjust: 100%;
63
}
64
65
.wrap {
66
    width: 100%;
67
    max-width: 960px;
68
    margin: 0 auto;
69
    padding: 0 16px;
70
}
71
72
a { color: var(--link); text-decoration: none; }
73
a:hover { text-decoration: underline; }
74
75
/* Header / footer */
76
.site-header {
77
    border-bottom: 1px solid var(--border);
78
    background: var(--card);
79
}
80
.site-header .wrap {
81
    display: flex;
82
    align-items: center;
83
    justify-content: space-between;
84
    height: 56px;
85
}
86
.brand { font-weight: 700; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; color: var(--fg); }
87
.site-header nav a { color: var(--muted); }
88
main.wrap { padding-top: 24px; padding-bottom: 48px; min-height: 60vh; }
89
.site-footer { border-top: 1px solid var(--border); color: var(--muted); font-size: 14px; }
90
.site-footer .wrap { padding-top: 16px; padding-bottom: 16px; }
91
92
/* Typography */
93
h1 { font-size: 1.6rem; margin: 0 0 12px; }
94
h2 { font-size: 1.2rem; margin: 24px 0 12px; }
95
.muted { color: var(--muted); font-size: 0.9rem; }
96
.empty { color: var(--muted); font-style: italic; }
97
98
.crumbs { color: var(--muted); font-size: 0.9rem; margin-bottom: 8px; }
99
.file-meta { margin-bottom: 8px; }
100
101
/* Badges */
102
.badge {
103
    display: inline-block;
104
    font-size: 0.75rem;
105
    padding: 2px 8px;
106
    border: 1px solid var(--border);
107
    border-radius: 999px;
108
    color: var(--muted);
109
    vertical-align: middle;
110
    margin-left: 6px;
111
}
112
113
/* Repo list */
114
.repo-list-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
115
.repo-list-head h1 { margin: 0; }
116
.repo-sort { display: flex; align-items: center; gap: 8px; }
117
.repo-sort label { color: var(--muted); font-size: 0.9rem; }
118
.repo-sort select {
119
    padding: 6px 10px;
120
    font-size: 0.9rem;
121
    border-radius: 6px;
122
    border: 1px solid var(--border);
123
    background: var(--card);
124
    color: var(--fg);
125
}
126
/* Repo header (title + Download ZIP) */
127
.repo-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 12px; }
128
.repo-head h1 { margin: 0; }
129
.btn-download-zip { white-space: nowrap; flex-shrink: 0; }
130
.btn-download-zip .dl-icon { font-weight: 700; margin-right: 2px; }
131
132
.repo-list { list-style: none; padding: 0; margin: 0; }
133
.repo-item { padding: 16px 0; border-bottom: 1px solid var(--border); }
134
.repo-name { font-size: 1.15rem; font-weight: 600; }
135
.repo-desc { margin: 6px 0; }
136
137
/* Tables */
138
.file-table { width: 100%; border-collapse: collapse; margin-top: 8px; }
139
.file-table th, .file-table td { text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--border); }
140
.file-table th { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--muted); }
141
.actions a, .actions form { margin-right: 10px; display: inline-block; }
142
143
/* Cards & forms */
144
.card {
145
    background: var(--card);
146
    border: 1px solid var(--border);
147
    border-radius: 8px;
148
    padding: 16px;
149
    margin-bottom: 24px;
150
}
151
.form label { display: block; margin-bottom: 12px; font-size: 0.9rem; color: var(--muted); }
152
.form input[type=text], .form input[type=password], .form select, .form textarea {
153
    display: block;
154
    width: 100%;
155
    margin-top: 4px;
156
    padding: 8px 10px;
157
    font-size: 1rem;
158
    color: var(--fg);
159
    background: var(--bg);
160
    border: 1px solid var(--border);
161
    border-radius: 6px;
162
    font-family: inherit;
163
}
164
.form textarea { resize: vertical; }
165
166
button, .btn-secondary {
167
    display: inline-block;
168
    padding: 8px 16px;
169
    font-size: 0.95rem;
170
    border-radius: 6px;
171
    border: 1px solid var(--border);
172
    background: var(--accent);
173
    color: #fff;
174
    cursor: pointer;
175
    font-family: inherit;
176
}
177
.btn-secondary { background: transparent; color: var(--fg); }
178
button:hover { opacity: 0.9; }
179
.row { display: flex; gap: 10px; align-items: center; }
180
181
.inline { display: inline; margin: 0; }
182
.link-btn {
183
    background: none;
184
    border: none;
185
    color: var(--link);
186
    padding: 0;
187
    cursor: pointer;
188
    font-size: inherit;
189
}
190
.link-btn.danger, .danger { color: #cf222e; }
191
192
.admin-bar { display: flex; align-items: center; justify-content: space-between; }
193
194
/* Notices */
195
.notice { background: #dafbe1; color: #116329; padding: 8px 12px; border-radius: 6px; }
196
.error  { background: #ffebe9; color: #cf222e; padding: 8px 12px; border-radius: 6px; }
197
@media (prefers-color-scheme: dark) {
198
    .notice { background: #12261e; color: #7ee787; }
199
    .error  { background: #2d1214; color: #ff7b72; }
200
}
201
202
/* Security warning banner (e.g. installer still present) */
203
.warn-banner {
204
    background: #fff8c5; color: #7d4e00; border: 1px solid #eac54f;
205
    padding: 12px 16px; border-radius: 8px; margin-bottom: 16px;
206
}
207
.warn-banner h3 { margin: 0 0 4px; font-size: 1rem; }
208
.warn-banner p { margin: 0 0 10px; }
209
.warn-banner .confirm { display: flex; gap: 8px; align-items: flex-start; margin-bottom: 10px; }
210
.warn-banner button { background: #cf222e; color: #fff; border: 0; border-radius: 6px; padding: 6px 14px; cursor: pointer; font: inherit; }
211
.warn-banner button:hover { background: #a40e26; }
212
@media (prefers-color-scheme: dark) {
213
    .warn-banner { background: #2b2410; color: #e3b341; border-color: #574a1a; }
214
}
215
216
/* Drag & drop */
217
.dropzone {
218
    border: 2px dashed var(--border);
219
    border-radius: 8px;
220
    padding: 24px;
221
    text-align: center;
222
    margin-bottom: 16px;
223
    transition: border-color 0.15s, background 0.15s;
224
}
225
.dropzone.over { border-color: var(--accent); background: rgba(9,105,218,0.06); }
226
.dropzone-buttons { justify-content: center; gap: 12px; flex-wrap: wrap; margin-top: 12px; }
227
.file-pick { cursor: pointer; }
228
.dir { margin-right: 2px; }
229
.file-names { list-style: none; padding: 0; margin: 12px 0 0; font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 0.85rem; }
230
231
/* Code view */
232
.code-view {
233
    border: 1px solid var(--border);
234
    border-radius: 8px;
235
    overflow-x: auto;
236
    background: var(--code-bg);
237
}
238
table.code {
239
    border-collapse: collapse;
240
    width: 100%;
241
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
242
    font-size: 0.85rem;
243
}
244
table.code td { padding: 0; vertical-align: top; }
245
table.code td.ln {
246
    width: 1%;
247
    min-width: 42px;
248
    text-align: right;
249
    padding: 0 12px;
250
    color: var(--ln);
251
    user-select: none;
252
    white-space: nowrap;
253
    border-right: 1px solid var(--border);
254
    /* Match the code cell's <pre> so numbers line up with their lines. */
255
    line-height: 1.35;
256
}
257
table.code td.cl { padding-left: 14px; width: 100%; }
258
table.code pre {
259
    margin: 0;
260
    padding: 0;
261
    min-height: 1.35em;
262
    line-height: 1.35;
263
    white-space: pre;
264
    font-family: inherit;
265
    color: var(--fg);
266
}
267
268
/* Syntax tokens */
269
.tok-com  { color: var(--tok-com); font-style: italic; }
270
.tok-str  { color: var(--tok-str); }
271
.tok-num  { color: var(--tok-num); }
272
.tok-kw   { color: var(--tok-kw); }
273
.tok-var  { color: var(--tok-var); }
274
.tok-fn   { color: var(--tok-fn); }
275
.tok-tag  { color: var(--tok-tag); }
276
.tok-attr { color: var(--tok-attr); }
277
.tok-sel  { color: var(--tok-sel); }
278
279
/* File tree (shared by folder listing and file-view sidebar) */
280
.hidden { display: none !important; }
281
.tree-icon { margin-right: 4px; }
282
ul.tree { list-style: none; margin: 0; padding: 0; }
283
ul.tree ul.tree { margin-left: 18px; border-left: 1px solid var(--border); padding-left: 6px; }
284
.tree li { padding: 3px 0; font-size: 0.95rem; }
285
.tree-dir > details > summary {
286
    list-style: none;
287
    cursor: pointer;
288
    display: flex;
289
    align-items: center;
290
    gap: 2px;
291
}
292
.tree-dir > details > summary::-webkit-details-marker { display: none; }
293
.tree-caret {
294
    display: inline-block;
295
    width: 14px;
296
    color: var(--muted);
297
    transition: transform 0.12s ease;
298
}
299
.tree-caret::before { content: "\25B8"; } /* ▸ */
300
.tree-dir > details[open] > summary .tree-caret { transform: rotate(90deg); }
301
.tree-file.active > a { font-weight: 600; color: var(--fg); }
302
.tree-up { padding: 3px 0 6px; margin-left: 16px; }
303
.tree-listing { margin-top: 8px; }
304
305
/* File view: sidebar + content two-column layout */
306
.file-layout { display: flex; gap: 16px; align-items: flex-start; }
307
.file-sidebar {
308
    flex: 0 0 240px;
309
    max-width: 240px;
310
    border: 1px solid var(--border);
311
    border-radius: 8px;
312
    background: var(--card);
313
    padding: 10px;
314
    position: sticky;
315
    top: 12px;
316
    max-height: 80vh;
317
    overflow: auto;
318
}
319
.tree-search {
320
    width: 100%;
321
    margin-bottom: 8px;
322
    padding: 6px 8px;
323
    font-size: 0.85rem;
324
    color: var(--fg);
325
    background: var(--bg);
326
    border: 1px solid var(--border);
327
    border-radius: 6px;
328
    font-family: inherit;
329
}
330
.file-main { flex: 1 1 auto; min-width: 0; }
331
.file-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 8px; flex-wrap: wrap; }
332
.file-actions { display: flex; flex-wrap: wrap; gap: 8px; }
333
.file-actions .btn-secondary { padding: 4px 12px; font-size: 0.85rem; white-space: nowrap; }
334
335
/* Image viewer */
336
.image-view {
337
    border: 1px solid var(--border);
338
    border-radius: 8px;
339
    padding: 24px;
340
    text-align: center;
341
    background-color: #fff;
342
    background-image:
343
        linear-gradient(45deg, #eee 25%, transparent 25%),
344
        linear-gradient(-45deg, #eee 25%, transparent 25%),
345
        linear-gradient(45deg, transparent 75%, #eee 75%),
346
        linear-gradient(-45deg, transparent 75%, #eee 75%);
347
    background-size: 16px 16px;
348
    background-position: 0 0, 0 8px, 8px -8px, -8px 0;
349
}
350
.image-view.image-view-dark {
351
    background-color: #1c1c1c;
352
    background-image:
353
        linear-gradient(45deg, #333 25%, transparent 25%),
354
        linear-gradient(-45deg, #333 25%, transparent 25%),
355
        linear-gradient(45deg, transparent 75%, #333 75%),
356
        linear-gradient(-45deg, transparent 75%, #333 75%);
357
}
358
.image-view img { max-width: 100%; height: auto; }
359
360
/* 3D model viewer */
361
.model-view {
362
    position: relative;
363
    border: 1px solid var(--border);
364
    border-radius: 8px;
365
    min-height: 60vh;
366
    overflow: hidden;
367
    background: var(--card);
368
    background-image: radial-gradient(circle at 50% 40%,
369
        rgba(127, 127, 127, 0.10), transparent 70%);
370
    display: flex;
371
    align-items: center;
372
    justify-content: center;
373
    touch-action: none;
374
}
375
.model-view.model-error { flex-direction: column; gap: 12px; }
376
.model-canvas {
377
    display: block;
378
    width: 100%;
379
    height: 100%;
380
    position: absolute;
381
    inset: 0;
382
    cursor: grab;
383
}
384
.model-canvas:active { cursor: grabbing; }
385
.model-status { color: var(--muted); font-size: 0.9rem; padding: 24px; text-align: center; }
386
.model-hint {
387
    position: absolute;
388
    left: 50%;
389
    bottom: 10px;
390
    transform: translateX(-50%);
391
    color: var(--muted);
392
    background: var(--card);
393
    border: 1px solid var(--border);
394
    border-radius: 999px;
395
    padding: 3px 12px;
396
    font-size: 0.75rem;
397
    opacity: 0.75;
398
    pointer-events: none;
399
    white-space: nowrap;
400
}
401
402
/* README */
403
.readme {
404
    border: 1px solid var(--border);
405
    border-radius: 8px;
406
    margin-top: 24px;
407
    overflow: hidden;
408
}
409
.readme-head {
410
    background: var(--card);
411
    border-bottom: 1px solid var(--border);
412
    padding: 10px 16px;
413
    font-size: 0.9rem;
414
    font-weight: 600;
415
}
416
.readme-body { padding: 8px 24px 24px; }
417
418
/* Rendered markdown */
419
.markdown h1, .markdown h2, .markdown h3, .markdown h4, .markdown h5, .markdown h6 { scroll-margin-top: 16px; }
420
.markdown h1, .markdown h2, .markdown h3 { margin: 20px 0 12px; padding-bottom: 6px; border-bottom: 1px solid var(--border); }
421
.markdown h1 { font-size: 1.5rem; }
422
.markdown h2 { font-size: 1.25rem; }
423
.markdown h3 { font-size: 1.05rem; border-bottom: none; }
424
.markdown p { margin: 12px 0; }
425
.markdown ul, .markdown ol { padding-left: 24px; }
426
.markdown blockquote { margin: 12px 0; padding: 0 14px; color: var(--muted); border-left: 3px solid var(--border); }
427
.markdown code {
428
    background: var(--code-bg);
429
    border-radius: 6px;
430
    padding: 2px 6px;
431
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
432
    font-size: 0.85em;
433
}
434
.markdown pre.md-code {
435
    background: var(--code-bg);
436
    border: 1px solid var(--border);
437
    border-radius: 8px;
438
    padding: 14px;
439
    overflow-x: auto;
440
}
441
.markdown pre.md-code code { background: none; padding: 0; font-size: 0.85rem; }
442
.markdown img { max-width: 100%; }
443
.markdown hr { border: none; border-top: 1px solid var(--border); margin: 20px 0; }
444
.markdown del { opacity: 0.7; }
445
.markdown table.md-table {
446
    display: block;
447
    width: max-content;
448
    max-width: 100%;
449
    overflow-x: auto;
450
    border-collapse: collapse;
451
    margin: 14px 0;
452
    font-size: 0.9rem;
453
}
454
.markdown table.md-table th,
455
.markdown table.md-table td {
456
    border: 1px solid var(--border);
457
    padding: 6px 13px;
458
}
459
.markdown table.md-table th { font-weight: 600; background: var(--code-bg); }
460
.markdown table.md-table tr:nth-child(2n) td { background: var(--code-bg); }
461
.markdown li input[type="checkbox"] { margin: 0 6px 0 0; vertical-align: middle; }
462
.markdown ul:has(> li > input[type="checkbox"]) { list-style: none; padding-left: 4px; }
463
464
@media (max-width: 600px) {
465
    body { font-size: 15px; }
466
    .site-header .wrap { height: 48px; }
467
    table.code { font-size: 0.75rem; }
468
    .file-layout { flex-direction: column; }
469
    .file-sidebar {
470
        flex-basis: auto;
471
        max-width: none;
472
        width: 100%;
473
        position: static;
474
        max-height: 40vh;
475
    }
476
    /* Column flex uses align-items: flex-start, which would otherwise shrink
477
       .file-main to its content width — collapsing the model viewer and
478
       letting a wide code table push the page past the viewport. Force it to
479
       fill the column; the code view still scrolls horizontally on its own. */
480
    .file-main { width: 100%; }
481
    .readme-body { padding: 8px 14px 16px; }
482
}
483