app.css (54686B)
1 /*! 2 * amit/cdn UI — one stylesheet for every page. 3 * 4 * Structure: 1 tokens · 2 base · 3 layout (header, breadcrumb, footer) · 4 controls · 5 feedback 5 * 6 lists · 7 file page · 8 upload · 9 history/search · 10 docs/prose · 11 stats · 12 shortener 6 * 13 responsive · 14 motion/print 7 * 8 * Theming: colours live in tokens. `html[data-theme]` is set before first paint (see base.html); the 9 * prefers-color-scheme block is only the no-JS fallback. Add a colour once, here, for both themes. 10 */ 11 12 /* ============================== 1. Tokens ============================== */ 13 :root { 14 color-scheme: light; 15 16 /* surfaces */ 17 --bg: #fafaf9; 18 --surface: #ffffff; 19 --surface-2: #f4f4f2; 20 --surface-3: #eaeae6; 21 --border: #e4e4df; 22 --border-strong: #cdcdc5; 23 24 /* text */ 25 --text: #1c1c1a; 26 --muted: #62625b; 27 28 /* brand: the logo's blue for actions, its orange as a rare highlight */ 29 --accent: #2a62d8; 30 --accent-hover: #2152bd; 31 --accent-solid: #2a62d8; 32 --accent-soft: #eaf0fd; 33 --accent-contrast: #ffffff; 34 --highlight: #ff6a42; 35 36 /* status */ 37 --success: #166534; 38 --success-soft: #e8f6ec; 39 --warning: #a14a08; 40 --warning-soft: #fdf3e1; 41 --warning-border: #f0cf9a; 42 --danger: #c0262d; 43 --danger-soft: #fdecec; 44 --danger-border: #f2b8bb; 45 46 /* file-type hues (icons, badges) */ 47 --ft-image: #16a34a; 48 --ft-video: #db2777; 49 --ft-audio: #c026d3; 50 --ft-archive: #d97706; 51 --ft-code: #2563eb; 52 --ft-doc: #dc2626; 53 --ft-data: #0d9488; 54 --ft-font: #7c3aed; 55 56 /* shape, depth, motion */ 57 --r-sm: 6px; 58 --r: 10px; 59 --r-lg: 14px; 60 --r-pill: 999px; 61 --shadow-sm: 0 1px 2px rgb(24 24 20 / 0.06); 62 --shadow-md: 0 6px 20px rgb(24 24 20 / 0.10); 63 --shadow-lg: 0 18px 48px rgb(24 24 20 / 0.22); 64 --ring: 0 0 0 3px color-mix(in srgb, var(--accent) 28%, transparent); 65 --ease: cubic-bezier(0.2, 0.8, 0.2, 1); 66 67 /* type */ 68 --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; 69 --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; 70 --fs-xs: 0.75rem; 71 --fs-sm: 0.8125rem; 72 --fs-md: 0.9375rem; 73 --fs-base: 1rem; 74 --fs-lg: 1.125rem; 75 76 /* layout */ 77 --page-w: 960px; 78 --gutter: 1.25rem; 79 --header-h: 3.5rem; 80 } 81 82 :root[data-theme="dark"] { 83 color-scheme: dark; 84 --bg: #0f1012; 85 --surface: #17181b; 86 --surface-2: #1e2024; 87 --surface-3: #292c31; 88 --border: #2a2d33; 89 --border-strong: #3b3f47; 90 --text: #ececea; 91 --muted: #a1a19a; 92 93 --accent: #7aa5ff; 94 --accent-hover: #9dbcff; 95 --accent-solid: #2f6bea; 96 --accent-soft: #15233f; 97 --accent-contrast: #ffffff; 98 99 --success: #4ade80; 100 --success-soft: #11251a; 101 --warning: #fbbf24; 102 --warning-soft: #2a2110; 103 --warning-border: #5c4516; 104 --danger: #ff7b72; 105 --danger-soft: #2c1517; 106 --danger-border: #6b2b2f; 107 108 --ft-image: #4ade80; 109 --ft-video: #f472b6; 110 --ft-audio: #e879f9; 111 --ft-archive: #fbbf24; 112 --ft-code: #60a5fa; 113 --ft-doc: #f87171; 114 --ft-data: #2dd4bf; 115 --ft-font: #a78bfa; 116 117 --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.4); 118 --shadow-md: 0 8px 24px rgb(0 0 0 / 0.45); 119 --shadow-lg: 0 20px 56px rgb(0 0 0 / 0.65); 120 } 121 122 /* no-JS fallback: follow the system when data-theme was never set */ 123 @media (prefers-color-scheme: dark) { 124 :root:not([data-theme]) { 125 color-scheme: dark; 126 --bg: #0f1012; --surface: #17181b; --surface-2: #1e2024; --surface-3: #292c31; 127 --border: #2a2d33; --border-strong: #3b3f47; --text: #ececea; --muted: #a1a19a; 128 --accent: #7aa5ff; --accent-hover: #9dbcff; --accent-solid: #2f6bea; --accent-soft: #15233f; 129 --success: #4ade80; --warning: #fbbf24; --danger: #ff7b72; 130 } 131 } 132 133 /* ============================== 2. Base ============================== */ 134 *, *::before, *::after { box-sizing: border-box; } 135 * { -webkit-tap-highlight-color: transparent; } 136 137 html { 138 -webkit-text-size-adjust: 100%; 139 text-size-adjust: 100%; 140 scroll-padding-top: calc(var(--header-h) + 1rem); 141 scrollbar-color: var(--border-strong) transparent; 142 } 143 144 body { 145 margin: 0; 146 min-height: 100vh; 147 min-height: 100dvh; 148 display: flex; 149 flex-direction: column; 150 background: var(--bg); 151 color: var(--text); 152 font: 400 var(--fs-base) / 1.6 var(--font); 153 -webkit-font-smoothing: antialiased; 154 -moz-osx-font-smoothing: grayscale; 155 text-rendering: optimizeLegibility; 156 } 157 158 [hidden] { display: none !important; } 159 160 ::selection { background: color-mix(in srgb, var(--accent) 30%, transparent); color: inherit; } 161 162 h1, h2, h3, h4 { margin: 0; line-height: 1.2; letter-spacing: -0.015em; text-wrap: balance; } 163 h1 { font-size: clamp(1.75rem, 1.2rem + 2.2vw, 2.5rem); font-weight: 700; letter-spacing: -0.025em; } 164 h2 { font-size: 1.375rem; font-weight: 650; } 165 h3 { font-size: var(--fs-lg); font-weight: 650; } 166 p { margin: 0 0 1em; } 167 168 a { color: var(--accent); text-decoration: none; } 169 a:hover { color: var(--accent-hover); text-decoration: underline; text-underline-offset: 3px; } 170 /* links inside running text must not rely on colour alone */ 171 p a, li a, .lede a, .callout a, .hero h1 a, .footnote a { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; } 172 .hero h1 a { text-decoration-thickness: 0.07em; text-underline-offset: 0.14em; } 173 .site-footer p a { text-decoration: underline; text-decoration-color: var(--border-strong); } 174 175 code, kbd, samp, pre { font-family: var(--mono); } 176 code { 177 font-size: 0.88em; 178 background: var(--surface-2); 179 border: 1px solid var(--border); 180 border-radius: var(--r-sm); 181 padding: 0.1em 0.4em; 182 overflow-wrap: anywhere; 183 } 184 pre { 185 margin: 0.75rem 0; 186 padding: 1rem 1.1rem; 187 background: var(--surface); 188 border: 1px solid var(--border); 189 border-radius: var(--r); 190 overflow-x: auto; 191 font-size: var(--fs-sm); 192 line-height: 1.6; 193 tab-size: 4; 194 } 195 pre code { background: none; border: 0; padding: 0; font-size: inherit; } 196 197 :focus { outline: none; } 198 :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; } 199 /* controls that draw their own focus indicator (ring or underline) must not also get the generic outline */ 200 .text-input:focus-visible, .select:focus-visible, .url-input:focus-visible, .filter-input:focus-visible, .search-input:focus-visible, .link-row__value:focus-visible { outline: none; } 201 main:focus { outline: none; } 202 203 img, svg, video { max-width: 100%; } 204 button { font: inherit; color: inherit; } 205 206 .sr-only { 207 position: absolute !important; 208 width: 1px; height: 1px; 209 padding: 0; margin: -1px; 210 overflow: hidden; 211 clip: rect(0, 0, 0, 0); 212 white-space: nowrap; 213 border: 0; 214 } 215 216 .skip-link { 217 position: fixed; 218 top: 0.5rem; left: 0.5rem; 219 z-index: 300; 220 padding: 0.6rem 1rem; 221 background: var(--accent-solid); 222 color: var(--accent-contrast); 223 border-radius: var(--r-sm); 224 font-weight: 600; 225 transform: translateY(-200%); 226 } 227 .skip-link:focus { transform: none; color: var(--accent-contrast); text-decoration: none; } 228 229 /* ============================== 3. Layout ============================== */ 230 .page { 231 width: 100%; 232 max-width: calc(var(--page-w) + var(--gutter) * 2); 233 margin: 0 auto; 234 padding: 1.5rem var(--gutter) 0; 235 flex: 1 0 auto; 236 animation: page-in 0.22s var(--ease) both; 237 } 238 body.turbo-loading .page { opacity: 0.55; pointer-events: none; transition: opacity 0.15s; } 239 .turbo-progress-bar { height: 3px; background: var(--highlight); } 240 241 .page-head { margin-bottom: 1.5rem; } 242 .page-head h1 { margin-bottom: 0.4rem; } 243 .lede { color: var(--muted); font-size: var(--fs-lg); max-width: 62ch; margin: 0; text-wrap: pretty; } 244 .section-title { font-size: var(--fs-lg); font-weight: 650; } 245 .hero { margin: 0 0 1rem; } 246 .hero h1 { margin-bottom: 0.75rem; font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2rem); } 247 248 /* ---- Header ---- */ 249 .site-header { 250 position: sticky; 251 top: 0; 252 z-index: 100; 253 background: color-mix(in srgb, var(--bg) 86%, transparent); 254 -webkit-backdrop-filter: saturate(1.6) blur(12px); 255 backdrop-filter: saturate(1.6) blur(12px); 256 border-bottom: 1px solid var(--border); 257 padding-top: env(safe-area-inset-top); 258 } 259 .site-header__inner { 260 display: flex; 261 align-items: center; 262 flex-wrap: wrap; 263 gap: 0 0.5rem; 264 max-width: calc(var(--page-w) + var(--gutter) * 2); 265 margin: 0 auto; 266 padding: 0 var(--gutter); 267 } 268 269 .wordmark { 270 display: inline-flex; 271 align-items: center; 272 min-height: var(--header-h); 273 gap: 0.6rem; 274 order: 0; 275 color: var(--text); 276 font-weight: 700; 277 font-size: var(--fs-lg); 278 letter-spacing: -0.02em; 279 white-space: nowrap; 280 } 281 .wordmark:hover { color: var(--text); text-decoration: none; } 282 .wordmark img { border-radius: 8px; display: block; } 283 .wordmark b { color: var(--highlight); font-weight: 800; margin: 0 0.04em; } 284 285 .site-header__tools { display: flex; align-items: center; gap: 0.4rem; order: 2; margin-left: 0.25rem; min-height: var(--header-h); } 286 .site-nav { display: flex; align-items: center; gap: 0.15rem; order: 1; flex: 1; justify-content: flex-end; } 287 288 .nav-link { 289 display: inline-flex; 290 align-items: center; 291 gap: 0.45rem; 292 padding: 0.45rem 0.7rem; 293 border: 0; 294 border-radius: var(--r-sm); 295 background: none; 296 color: var(--muted); 297 font-size: var(--fs-md); 298 font-weight: 500; 299 line-height: 1.3; 300 white-space: nowrap; 301 cursor: pointer; 302 transition: background 0.12s, color 0.12s; 303 } 304 @media (hover: hover) { .nav-link:hover { color: var(--text); background: var(--surface-2); text-decoration: none; } } 305 .nav-link.is-active { color: var(--accent); background: var(--accent-soft); } 306 .nav-link svg { flex: none; } 307 .nav-cta { margin-left: 0.4rem; background: var(--accent-solid); color: var(--accent-contrast); font-weight: 600; } 308 @media (hover: hover) { .nav-cta:hover { background: var(--accent-hover); color: var(--accent-contrast); } } 309 @media (hover: hover) { :root[data-theme="dark"] .nav-cta:hover { background: #4a7ff0; } } 310 .nav-cta.is-active { background: var(--accent-solid); color: var(--accent-contrast); box-shadow: inset 0 0 0 2px color-mix(in srgb, #fff 35%, transparent); } 311 312 .more { position: relative; } 313 .more__menu { 314 display: none; 315 position: absolute; 316 right: 0; 317 top: calc(100% + 8px); 318 min-width: 11rem; 319 padding: 0.3rem; 320 background: var(--surface); 321 border: 1px solid var(--border); 322 border-radius: var(--r); 323 box-shadow: var(--shadow-md); 324 z-index: 110; 325 } 326 .more.is-open .more__menu { display: flex; flex-direction: column; gap: 2px; } 327 .more.is-open .more__toggle { background: var(--surface-2); color: var(--text); } 328 329 .theme-toggle .i-sun { display: none; } 330 :root[data-theme="dark"] .theme-toggle .i-sun { display: inline-flex; } 331 :root[data-theme="dark"] .theme-toggle .i-moon { display: none; } 332 .nav-toggle { display: none; } 333 .site-header__tools .quick-action { display: none; } 334 .quick-action.is-active { color: var(--accent); background: var(--accent-soft); } 335 .quick-action--primary { color: var(--accent); } 336 html[data-notice="off"] .site-notice { display: none; } 337 .nav-toggle .i-close { display: none; } 338 .nav-toggle[aria-expanded="true"] .i-open { display: none; } 339 .nav-toggle[aria-expanded="true"] .i-close { display: inline-flex; } 340 341 /* ---- Breadcrumb ---- */ 342 .breadcrumb-container { 343 max-width: calc(var(--page-w) + var(--gutter) * 2); 344 margin: 0 auto; 345 padding: 0.85rem var(--gutter) 0; 346 width: 100%; 347 } 348 .breadcrumb { 349 display: flex; 350 align-items: center; 351 flex-wrap: wrap; 352 gap: 0.35rem; 353 color: var(--muted); 354 font-family: var(--mono); 355 font-size: var(--fs-sm); 356 min-width: 0; 357 } 358 .breadcrumb a { 359 color: var(--text); 360 padding: 0.15rem 0.35rem; 361 margin: 0 -0.1rem; 362 border-radius: var(--r-sm); 363 } 364 .breadcrumb > a:first-child { margin-left: -0.35rem; } 365 .breadcrumb a:hover { color: var(--accent); background: var(--surface-2); text-decoration: none; } 366 .breadcrumb-collapsed { position: relative; display: inline-flex; } 367 .breadcrumb-ellipsis, .copy-path-btn { 368 display: inline-flex; 369 align-items: center; 370 justify-content: center; 371 background: var(--surface); 372 border: 1px solid var(--border); 373 border-radius: var(--r-sm); 374 color: var(--muted); 375 cursor: pointer; 376 line-height: 1.4; 377 transition: color 0.12s, border-color 0.12s, background 0.12s; 378 } 379 .breadcrumb-ellipsis { padding: 0.05rem 0.55rem; font-family: var(--mono); } 380 .copy-path-btn { padding: 0.3rem; margin-left: 0.3rem; } 381 .breadcrumb-ellipsis:hover, .copy-path-btn:hover { color: var(--text); border-color: var(--border-strong); background: var(--surface-2); } 382 .breadcrumb-menu { 383 display: none; 384 position: absolute; 385 top: calc(100% + 6px); 386 left: 0; 387 min-width: 12rem; 388 max-width: 75vw; 389 max-height: 16rem; 390 overflow-y: auto; 391 flex-direction: column; 392 gap: 2px; 393 padding: 0.3rem; 394 background: var(--surface); 395 border: 1px solid var(--border); 396 border-radius: var(--r); 397 box-shadow: var(--shadow-md); 398 z-index: 60; 399 } 400 .breadcrumb-menu.open { display: flex; } 401 .breadcrumb-menu a { padding: 0.5rem 0.7rem; margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } 402 403 /* ---- Footer ---- */ 404 .site-footer { margin-top: 4rem; border-top: 1px solid var(--border); padding-bottom: env(safe-area-inset-bottom); } 405 .site-footer__inner { 406 display: flex; 407 justify-content: space-between; 408 align-items: flex-end; 409 flex-wrap: wrap; 410 gap: 0.75rem 2rem; 411 max-width: calc(var(--page-w) + var(--gutter) * 2); 412 margin: 0 auto; 413 padding: 1.5rem var(--gutter) 2rem; 414 color: var(--muted); 415 font-size: var(--fs-sm); 416 } 417 .site-footer p { margin: 0; } 418 .site-footer a { color: var(--text); font-weight: 500; } 419 .site-footer a:hover { color: var(--accent); } 420 .footer-stats { font-family: var(--mono); font-size: var(--fs-xs); } 421 .footer-stats strong { color: var(--text); } 422 423 /* ============================== 4. Controls ============================== */ 424 .btn { 425 display: inline-flex; 426 align-items: center; 427 justify-content: center; 428 gap: 0.5rem; 429 min-height: 2.5rem; 430 padding: 0.5rem 1rem; 431 background: var(--surface); 432 color: var(--text); 433 border: 1px solid var(--border-strong); 434 border-radius: var(--r); 435 font-size: var(--fs-md); 436 font-weight: 500; 437 line-height: 1.2; 438 cursor: pointer; 439 text-decoration: none; 440 box-shadow: var(--shadow-sm); 441 transition: background 0.12s, border-color 0.12s, transform 0.08s, box-shadow 0.12s; 442 } 443 @media (hover: hover) { .btn:hover:not(:disabled) { background: var(--surface-2); color: var(--text); text-decoration: none; } } 444 .btn:active:not(:disabled) { transform: translateY(1px); box-shadow: none; } 445 .btn:disabled { opacity: 0.55; cursor: not-allowed; } 446 .btn svg { flex: none; } 447 .btn-sm { min-height: 2rem; padding: 0.3rem 0.7rem; font-size: var(--fs-sm); border-radius: var(--r-sm); } 448 .btn-primary { background: var(--accent-solid); border-color: var(--accent-solid); color: var(--accent-contrast); } 449 @media (hover: hover) { .btn-primary:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); color: var(--accent-contrast); } } 450 @media (hover: hover) { :root[data-theme="dark"] .btn-primary:hover:not(:disabled) { background: #4a7ff0; border-color: #4a7ff0; } } 451 .btn-ghost-danger { box-shadow: none; color: var(--muted); } 452 @media (hover: hover) { .btn-ghost-danger:hover:not(:disabled) { color: var(--danger); border-color: var(--danger-border); background: var(--danger-soft); } } 453 .btn.is-done { color: var(--success); border-color: var(--success); } 454 455 .icon-btn { 456 display: inline-flex; 457 align-items: center; 458 justify-content: center; 459 width: 2.25rem; 460 height: 2.25rem; 461 padding: 0; 462 background: none; 463 border: 1px solid transparent; 464 border-radius: var(--r-sm); 465 color: var(--muted); 466 cursor: pointer; 467 transition: background 0.12s, color 0.12s; 468 } 469 @media (hover: hover) { .icon-btn:hover { background: var(--surface-2); color: var(--text); } } 470 .icon-btn > span { display: inline-flex; align-items: center; justify-content: center; } 471 .site-header__tools .nav-toggle { display: none; } 472 473 .text-input, .select, .filter-input, .search-input, .url-input { 474 width: 100%; 475 min-height: 2.75rem; 476 padding: 0.6rem 0.9rem; 477 background: var(--surface); 478 color: var(--text); 479 border: 1px solid var(--border-strong); 480 border-radius: var(--r); 481 font: inherit; 482 font-size: var(--fs-md); 483 transition: border-color 0.12s, box-shadow 0.12s, background 0.12s; 484 } 485 .text-input::placeholder, .filter-input::placeholder, .search-input::placeholder, .url-input::placeholder { color: var(--muted); opacity: 0.8; } 486 .text-input:focus, .select:focus, .url-input:focus { border-color: var(--accent); box-shadow: var(--ring); outline: none; } 487 .select { width: auto; min-height: 2.5rem; padding-right: 2rem; cursor: pointer; appearance: none; -webkit-appearance: none; 488 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E"); 489 background-repeat: no-repeat; background-position: right 0.75rem center; } 490 .select-wrap { position: relative; display: inline-flex; align-items: center; } 491 .select-wrap > svg { position: absolute; left: 0.7rem; color: var(--muted); pointer-events: none; } 492 .listing-toolbar .select { padding-left: 2rem; padding-right: 1.8rem; background-position: right 0.6rem center; } 493 494 .input-group { position: relative; display: flex; align-items: center; width: 100%; } 495 .input-group__icon { position: absolute; left: 1rem; display: inline-flex; color: var(--muted); pointer-events: none; } 496 .input-group .filter-input, .input-group .search-input { padding-left: 2.7rem; padding-right: 2.6rem; } 497 .input-clear-btn { 498 position: absolute; right: 0.55rem; top: 50%; transform: translateY(-50%); 499 display: none; align-items: center; justify-content: center; 500 width: 1.9rem; height: 1.9rem; padding: 0; 501 background: none; border: 0; border-radius: 50%; 502 color: var(--muted); cursor: pointer; 503 } 504 .input-group[data-has-text="true"] .input-clear-btn { display: inline-flex; } 505 .input-clear-btn:hover { background: var(--surface-3); color: var(--text); } 506 .input-row { display: flex; gap: 0.6rem; } 507 .input-row .text-input { flex: 1; min-width: 0; } 508 509 .field { margin-bottom: 1.25rem; } 510 .field-label { display: block; margin-bottom: 0.45rem; color: var(--muted); font-size: var(--fs-sm); font-weight: 600; } 511 512 .segmented { display: inline-flex; padding: 3px; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r); gap: 2px; } 513 .segmented__btn { 514 padding: 0.4rem 1rem; border: 0; border-radius: calc(var(--r) - 3px); 515 background: none; color: var(--muted); cursor: pointer; 516 font-family: var(--mono); font-size: var(--fs-sm); font-weight: 600; 517 transition: background 0.12s, color 0.12s; 518 } 519 .segmented__btn:hover { color: var(--text); } 520 .segmented__btn.is-active { background: var(--surface); color: var(--text); box-shadow: var(--shadow-sm); } 521 522 .tabs { display: flex; gap: 0.25rem; border-bottom: 1px solid var(--border); margin-bottom: 1.5rem; overflow-x: auto; } 523 .tab { 524 padding: 0.7rem 1rem; margin-bottom: -1px; background: none; border: 0; 525 border-bottom: 2px solid transparent; color: var(--muted); 526 font-weight: 550; cursor: pointer; white-space: nowrap; 527 } 528 .tab:hover { color: var(--text); } 529 .tab.is-active { color: var(--text); border-bottom-color: var(--highlight); } 530 .tabpanel__head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: 1rem; } 531 532 /* ============================== 5. Feedback ============================== */ 533 .callout, .alert { 534 display: flex; gap: 0.7rem; align-items: flex-start; 535 margin: 0 0 1.25rem; padding: 0.85rem 1rem; 536 background: var(--surface); border: 1px solid var(--border); 537 border-radius: var(--r); font-size: var(--fs-md); line-height: 1.55; 538 } 539 .callout > svg { flex: none; margin-top: 0.2rem; color: var(--accent); } 540 .callout-warning { background: var(--warning-soft); border-color: var(--warning-border); } 541 .callout-warning > svg { color: var(--warning); } 542 .callout a { font-weight: 550; } 543 .alert-danger { background: var(--danger-soft); border-color: var(--danger-border); color: var(--danger); } 544 .site-notice { 545 display: flex; align-items: flex-start; gap: 0.6rem; 546 margin: 0 0 1rem; padding: 0.55rem 0.4rem 0.55rem 0.85rem; 547 background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); 548 color: var(--muted); font-size: var(--fs-sm); line-height: 1.5; 549 } 550 .site-notice > svg { flex: none; margin-top: 0.2rem; color: var(--accent); } 551 .site-notice > span { flex: 1; min-width: 0; } 552 .site-notice a { font-weight: 550; } 553 .notice-close { flex: none; display: grid; place-items: center; width: 2rem; height: 2rem; margin: -0.2rem 0 -0.2rem 0; padding: 0; background: none; border: 0; border-radius: var(--r-sm); color: var(--muted); cursor: pointer; } 554 .notice-close:hover { background: var(--surface-3); color: var(--text); } 555 556 .toasts { 557 position: fixed; z-index: 400; 558 left: 50%; bottom: calc(1.25rem + env(safe-area-inset-bottom)); 559 transform: translateX(-50%); 560 display: flex; flex-direction: column; align-items: center; gap: 0.5rem; 561 width: min(92vw, 26rem); pointer-events: none; 562 } 563 .toast { 564 display: flex; align-items: center; gap: 0.6rem; 565 width: 100%; padding: 0.7rem 1rem; 566 background: var(--text); color: var(--bg); 567 border-radius: var(--r); box-shadow: var(--shadow-lg); 568 font-size: var(--fs-md); font-weight: 500; 569 animation: toast-in 0.22s var(--ease) both; 570 } 571 .toast.is-leaving { animation: toast-out 0.18s ease-in both; } 572 .toast--error { background: var(--danger); color: #fff; } 573 .toast--success svg { color: #4ade80; } 574 :root[data-theme="dark"] .toast--success svg { color: #15803d; } 575 576 .dialog { 577 width: min(92vw, 28rem); padding: 0; 578 background: var(--surface); color: var(--text); 579 border: 1px solid var(--border-strong); border-radius: var(--r-lg); 580 box-shadow: var(--shadow-lg); 581 } 582 .dialog::backdrop { background: rgb(8 8 10 / 0.55); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); } 583 .dialog[open] { animation: page-in 0.18s var(--ease) both; } 584 .dialog__body { padding: 1.5rem; } 585 .dialog h2 { font-size: 1.25rem; margin-bottom: 0.75rem; } 586 .dialog p { color: var(--muted); margin-bottom: 1.5rem; } 587 .dialog p strong { color: var(--text); } 588 .dialog__actions { display: flex; justify-content: flex-end; gap: 0.6rem; } 589 590 .spin-anim { animation: spin 0.8s linear infinite; } 591 .spinner { 592 display: inline-block; width: 14px; height: 14px; vertical-align: -2px; 593 border: 2px solid var(--accent); border-top-color: transparent; border-radius: 50%; 594 animation: spin 0.8s linear infinite; 595 } 596 597 /* ============================== 6. Lists ============================== */ 598 .listing-toolbar { 599 display: flex; align-items: center; justify-content: space-between; 600 flex-wrap: wrap; gap: 0.5rem 0.75rem; margin-bottom: 0.75rem; 601 } 602 .listing-toolbar .select { min-height: 2.25rem; padding-top: 0.3rem; padding-bottom: 0.3rem; font-size: var(--fs-sm); border-color: var(--border); box-shadow: none; } 603 .listing-toolbar .btn { min-height: 2.25rem; padding-top: 0.3rem; padding-bottom: 0.3rem; font-size: var(--fs-sm); } 604 .zip-short { display: none; } 605 .input-group--standalone { margin-bottom: 0.75rem; } 606 .input-group--standalone .filter-input { box-shadow: var(--shadow-sm); } 607 .input-group--standalone .filter-input:focus { border-color: var(--accent); box-shadow: var(--ring); } 608 .listing-toolbar__counts { margin: 0; color: var(--muted); font-family: var(--mono); font-size: var(--fs-sm); } 609 .listing-toolbar__counts strong { color: var(--text); } 610 .listing-toolbar__actions { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } 611 612 .list-container { margin-bottom: 1.5rem; } 613 .list-group { 614 display: flex; flex-direction: column; overflow: hidden; 615 background: var(--surface); border: 1px solid var(--border); 616 border-radius: var(--r-lg); box-shadow: var(--shadow-sm); 617 } 618 .list-group .input-group { border-bottom: 1px solid var(--border); background: var(--surface-2); } 619 .list-group .filter-input, .list-group .search-input { 620 border: 0; border-radius: 0; background: transparent; box-shadow: none; min-height: 3.1rem; 621 } 622 .list-group .filter-input:focus, .list-group .search-input:focus { box-shadow: inset 0 -2px 0 var(--accent); } 623 .list-group .input-group:focus-within { background: var(--surface); } 624 625 .list-item { 626 display: flex; align-items: center; justify-content: space-between; gap: 1rem; 627 min-height: 3.25rem; padding: 0.55rem 1.1rem; 628 border-bottom: 1px solid var(--border); 629 transition: background 0.1s; 630 } 631 .list-item:last-child { border-bottom: 0; } 632 .list-item:hover { background: var(--surface-2); } 633 634 .item-name { display: flex; align-items: center; gap: 0.8rem; flex: 1; min-width: 0; } 635 .item-name svg { 636 flex: none; box-sizing: content-box; 637 width: 18px; height: 18px; padding: 7px; border-radius: 9px; 638 } 639 .item-name svg.folder-icon { color: var(--accent); background: var(--accent-soft); } 640 .item-name svg.file-icon-list { 641 color: var(--ft, var(--muted)); 642 background: color-mix(in srgb, var(--ft, var(--muted)) 13%, transparent); 643 } 644 .item-name a { 645 min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; 646 font-size: var(--fs-md); padding: 0.45rem 0; 647 } 648 .item-name a.folder-link { color: var(--text); font-weight: 650; } 649 .item-name a.file-link { color: var(--text); font-weight: 500; } 650 .item-name a:hover { color: var(--accent); text-decoration: none; } 651 652 .item-meta { display: flex; align-items: center; gap: 0.5rem; flex: none; color: var(--muted); font-family: var(--mono); font-size: var(--fs-xs); white-space: nowrap; } 653 .download-icon { 654 display: inline-flex; align-items: center; justify-content: center; 655 width: 2.25rem; height: 2.25rem; margin: -0.4rem -0.4rem -0.4rem 0; 656 border-radius: var(--r-sm); color: var(--muted); 657 transition: background 0.12s, color 0.12s; 658 } 659 .download-icon:hover { color: var(--accent); background: var(--accent-soft); text-decoration: none; } 660 661 .empty-state { display: flex; flex-direction: column; align-items: center; gap: 0.75rem; padding: 3.5rem 1.5rem; color: var(--muted); text-align: center; } 662 .empty-state svg { opacity: 0.55; } 663 .empty-state p { margin: 0; } 664 665 /* ============================== 7. File page ============================== */ 666 .file-view { display: block; } 667 .file-view__content { display: grid; gap: 1.5rem; } 668 .file-view.is-revealed .file-view__content { animation: page-in 0.22s var(--ease) both; } 669 .file-head { 670 display: grid; grid-template-columns: minmax(0, 1fr) auto; 671 align-items: center; gap: 0.9rem 1.25rem; 672 } 673 .file-name { font-size: clamp(1.35rem, 1rem + 1.6vw, 1.9rem); overflow-wrap: anywhere; letter-spacing: -0.02em; } 674 .file-meta-row { display: flex; align-items: center; flex-wrap: wrap; gap: 0.4rem 0.5rem; margin: 0.55rem 0 0; } 675 .file-pill { 676 padding: 0.1rem 0.6rem; background: var(--surface-2); border: 1px solid var(--border); 677 border-radius: var(--r-pill); color: var(--text); 678 font-family: var(--mono); font-size: var(--fs-xs); font-weight: 650; 679 } 680 .file-path { color: var(--muted); font-family: var(--mono); font-size: var(--fs-xs); overflow-wrap: anywhere; } 681 .file-head__actions { display: flex; gap: 0.5rem; flex-wrap: wrap; justify-content: flex-end; } 682 683 .preview { 684 position: relative; overflow: hidden; 685 background: var(--surface); border: 1px solid var(--border); 686 border-radius: var(--r-lg); box-shadow: var(--shadow-sm); 687 } 688 .preview--image { 689 display: grid; place-items: center; padding: 1rem; 690 background-color: var(--surface-2); 691 background-image: 692 linear-gradient(45deg, var(--surface-3) 25%, transparent 25%, transparent 75%, var(--surface-3) 75%), 693 linear-gradient(45deg, var(--surface-3) 25%, transparent 25%, transparent 75%, var(--surface-3) 75%); 694 background-size: 20px 20px; background-position: 0 0, 10px 10px; 695 } 696 .preview--image img { display: block; max-width: 100%; max-height: 70vh; width: auto; height: auto; border-radius: var(--r-sm); background: transparent; } 697 .preview--video { background: #000; } 698 .preview--video video { display: block; width: 100%; max-height: 70vh; } 699 .preview__audio { display: flex; align-items: center; gap: 1rem; padding: 1.25rem; color: var(--ft-audio); } 700 .preview__audio audio { flex: 1; min-width: 0; } 701 .preview--pdf iframe { display: block; width: 100%; height: 70vh; min-height: 24rem; border: 0; background: var(--surface-2); } 702 .preview__hint { margin: 0; padding: 0.6rem 1rem; border-top: 1px solid var(--border); color: var(--muted); font-size: var(--fs-sm); } 703 .preview__none { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; padding: 3rem 1rem; color: var(--muted); } 704 .preview__none p { margin: 0; } 705 .preview__icon { display: grid; place-items: center; width: 4.5rem; height: 4.5rem; border-radius: 18px; background: var(--surface-2); border: 1px solid var(--border); } 706 .preview__status { margin: 0; padding: 2rem 1rem; text-align: center; color: var(--muted); } 707 .preview__text pre { margin: 0; border: 0; border-radius: 0; max-height: 34rem; overflow: auto; padding: 0.9rem 0; background: transparent; } 708 .preview__text code { display: block; min-width: max-content; counter-reset: ln; } 709 .preview__text .ln { display: block; padding: 0 1rem 0 0; white-space: pre; } 710 .preview__text .ln::before { 711 counter-increment: ln; content: counter(ln); 712 display: inline-block; width: 3.4rem; margin-right: 0.9rem; padding-right: 0.8rem; 713 text-align: right; color: var(--muted); opacity: 0.65; border-right: 1px solid var(--border); 714 user-select: none; -webkit-user-select: none; 715 } 716 .preview__bar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; min-height: 2.9rem; padding: 0.4rem 0.75rem 0.4rem 1rem; border-bottom: 1px solid var(--border); background: var(--surface-2); color: var(--muted); font-size: var(--fs-sm); } 717 .preview__text.is-ready { animation: page-in 0.2s var(--ease) both; } 718 719 /* skeletons: shown while a preview loads, then swapped out in one go */ 720 .sk { display: block; height: 0.8rem; border-radius: 4px; background: linear-gradient(90deg, var(--surface-3) 25%, var(--surface-2) 50%, var(--surface-3) 75%); background-size: 200% 100%; animation: shimmer 1.4s linear infinite; } 721 .sk-label { width: 5.5rem; } 722 .sk-btn { width: 7rem; height: 2rem; border-radius: var(--r-sm); } 723 .sk-lines { display: grid; gap: 0.85rem; padding: 1.1rem 1rem 1.3rem; min-height: 16rem; align-content: start; } 724 html[data-js] .preview--image.is-loading, html[data-js] .preview--pdf.is-loading { min-height: 16rem; } 725 html[data-js] .preview--image.is-loading img { opacity: 0; } 726 html[data-js] .preview--pdf.is-loading iframe { opacity: 0; } 727 html[data-js] .preview--image.is-loading::after, html[data-js] .preview--pdf.is-loading::after { 728 content: ""; position: absolute; inset: 0; z-index: 1; 729 background: linear-gradient(90deg, var(--surface-3) 25%, var(--surface-2) 50%, var(--surface-3) 75%); background-size: 200% 100%; animation: shimmer 1.4s linear infinite; 730 } 731 .preview--image img, .preview--pdf iframe { transition: opacity 0.2s var(--ease); } 732 733 .link-list { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); padding: 1.1rem 1.25rem 0.4rem; box-shadow: var(--shadow-sm); } 734 .link-list .section-title { margin-bottom: 0.5rem; } 735 .link-row { display: grid; grid-template-columns: 9rem minmax(0, 1fr) auto; align-items: center; gap: 0.75rem; padding: 0.7rem 0; border-top: 1px solid var(--border); } 736 .link-row:first-of-type { border-top: 0; } 737 .link-row__label { font-weight: 600; font-size: var(--fs-md); } 738 .link-row__label small { display: block; color: var(--muted); font-weight: 400; font-size: var(--fs-xs); } 739 .link-row__value { 740 display: block; min-width: 0; padding: 0.5rem 0.7rem; 741 background: var(--surface-2); color: var(--text); 742 border: 1px solid var(--border); border-radius: var(--r-sm); 743 font-family: var(--mono); font-size: var(--fs-xs); line-height: 1.5; 744 white-space: normal; overflow-wrap: anywhere; word-break: break-all; 745 -webkit-user-select: all; user-select: all; 746 } 747 748 .notfound { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 1rem; padding: 4rem 0 2rem; } 749 .notfound__icon { display: grid; place-items: center; width: 4.5rem; height: 4.5rem; border-radius: 20px; background: var(--warning-soft); color: var(--warning); border: 1px solid var(--warning-border); } 750 .notfound__actions { display: flex; gap: 0.6rem; flex-wrap: wrap; justify-content: center; margin-top: 0.5rem; } 751 752 /* whole-page skeleton for file pages: shown (JS only) until the preview is ready, then everything appears at once */ 753 .file-skel { display: none; gap: 1.5rem; } 754 html[data-js] .file-view.is-pending .file-skel, .file-skel.is-standalone { display: grid; } 755 html[data-js] .file-view.is-pending .file-view__content { display: none; } 756 .file-skel__head { display: grid; gap: 0.8rem; } 757 .sk-title { width: 55%; height: 1.9rem; border-radius: 6px; } 758 .sk-pills { width: 38%; height: 1.2rem; } 759 .file-skel__actions { display: flex; gap: 0.5rem; flex-wrap: wrap; } 760 .sk-action { height: 2.5rem; flex: 1 1 6rem; max-width: 9rem; border-radius: var(--r); } 761 .file-skel__card, .file-skel__preview { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--shadow-sm); } 762 .file-skel__card { display: grid; gap: 1.1rem; padding: 1.2rem 1.25rem; } 763 .file-skel__row { display: grid; gap: 0.55rem; } 764 .sk-rowlabel { width: 30%; } 765 .sk-rowbar { width: 100%; height: 2.1rem; border-radius: var(--r-sm); } 766 .file-skel__preview { display: grid; gap: 0.85rem; align-content: start; min-height: 16rem; padding: 1.1rem 1rem 1.3rem; } 767 .sk-previewbar { width: 100%; height: 2rem; border-radius: var(--r-sm); margin-bottom: 0.4rem; } 768 769 .icon-btn:active { background: var(--surface-3); color: var(--text); } 770 771 /* ============================== 8. Upload ============================== */ 772 .upload { max-width: 44rem; } 773 .dropzone { 774 display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.35rem; 775 margin-bottom: 1.5rem; padding: 3rem 1.5rem; text-align: center; cursor: pointer; 776 background: var(--surface); color: var(--muted); 777 border: 2px dashed var(--border-strong); border-radius: var(--r-lg); 778 transition: border-color 0.15s, background 0.15s, transform 0.15s; 779 } 780 .dropzone:hover, .dropzone:focus-within, .dropzone.dragover { border-color: var(--accent); background: var(--accent-soft); } 781 .dropzone:focus-within { box-shadow: var(--ring); } 782 .dropzone.dragover { transform: scale(1.01); } 783 .dropzone__icon { display: grid; place-items: center; width: 3.5rem; height: 3.5rem; margin-bottom: 0.4rem; border-radius: 50%; background: var(--surface-2); color: var(--accent); transition: transform 0.15s; } 784 .dropzone.dragover .dropzone__icon { transform: translateY(-3px); } 785 .dropzone__title { color: var(--text); font-size: var(--fs-lg); font-weight: 600; } 786 .dropzone__sub { font-size: var(--fs-md); } 787 .dropzone u { text-decoration-color: var(--accent); text-underline-offset: 3px; color: var(--accent); } 788 789 .upload-queue { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.6rem; } 790 .upload-queue:empty { display: none; } 791 .queue-item { 792 display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0.25rem 1rem; align-items: center; 793 padding: 0.8rem 1rem; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); 794 box-shadow: var(--shadow-sm); animation: page-in 0.2s var(--ease) both; 795 } 796 .queue-item__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 550; } 797 .queue-item__status { color: var(--muted); font-family: var(--mono); font-size: var(--fs-xs); white-space: nowrap; display: inline-flex; align-items: center; gap: 0.4rem; } 798 .queue-item__actions { display: flex; gap: 0.6rem; font-size: var(--fs-sm); font-weight: 550; } 799 .queue-item.is-done { border-color: color-mix(in srgb, var(--success) 40%, var(--border)); } 800 .queue-item.is-done .queue-item__name { color: var(--success); } 801 .queue-item.is-error { border-color: var(--danger-border); background: var(--danger-soft); } 802 .queue-item.is-error .queue-item__status { color: var(--danger); } 803 .queue-item__bar { grid-column: 1 / -1; height: 4px; margin-top: 0.35rem; background: var(--surface-3); border-radius: 2px; overflow: hidden; } 804 .queue-item__bar i { display: block; width: 0; height: 100%; background: var(--accent-solid); border-radius: 2px; transition: width 0.15s linear; } 805 .queue-item.is-saving .queue-item__bar i { width: 100% !important; background: linear-gradient(90deg, var(--accent-solid), var(--highlight), var(--accent-solid)); background-size: 200% 100%; animation: shimmer 1.2s linear infinite; } 806 .queue-item--group { grid-template-columns: 1fr; } 807 .queue-item--group a { word-break: break-all; font-family: var(--mono); font-size: var(--fs-sm); } 808 809 /* ============================== 9. History / search ============================== */ 810 .search-box { margin-bottom: 1.5rem; } 811 .input-group--lg .search-input { min-height: 3.6rem; font-size: var(--fs-lg); } 812 .search-status { padding: 0.7rem 1.1rem; border-bottom: 1px solid var(--border); background: var(--surface-2); color: var(--muted); font-size: var(--fs-md); } 813 .search-status strong { color: var(--text); } 814 .result-path { padding: 0 0 0.15rem 3.1rem; margin-top: -0.35rem; color: var(--muted); font-family: var(--mono); font-size: var(--fs-xs); overflow-wrap: anywhere; } 815 .list-item--stack { flex-direction: column; align-items: stretch; gap: 0; padding-top: 0.7rem; padding-bottom: 0.7rem; } 816 .list-item--stack .row-top { display: flex; align-items: center; justify-content: space-between; gap: 1rem; } 817 .when { color: var(--muted); font-size: var(--fs-xs); } 818 819 /* ============================== 10. Docs / prose ============================== */ 820 .prose h1 { margin-bottom: 0.4rem; } 821 .prose h2 { margin: 2.5rem 0 0.75rem; font-size: 1.4rem; } 822 .prose > h2 { padding-top: 1.2rem; border-top: 1px solid var(--border); } 823 .toc-title, .prose h3 { margin: 1.2rem 0 0.4rem; color: var(--muted); font-size: var(--fs-xs); font-weight: 650; text-transform: uppercase; letter-spacing: 0.06em; } 824 .prose p, .prose li { color: var(--muted); } 825 .prose p { margin: 0.4em 0 0.8em; } 826 .prose section { margin-top: 2.75rem; scroll-margin-top: calc(var(--header-h) + 1rem); } 827 .prose section > h2 { margin-top: 0; } 828 .prose .badge { display: inline-block; margin-left: 0.5rem; padding: 0.1rem 0.55rem; background: var(--accent-soft); color: var(--accent); border-radius: var(--r-pill); font-size: var(--fs-xs); font-weight: 600; vertical-align: middle; } 829 .prose ul, .prose ol { padding-left: 1.3em; } 830 .prose .lede { margin-bottom: 1.5rem; } 831 .footnote { margin-top: 3rem; padding-top: 1.2rem; border-top: 1px solid var(--border); color: var(--muted); font-size: var(--fs-sm); } 832 833 .toc { margin: 1.5rem 0 2.5rem; padding: 1.1rem 1.3rem; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); } 834 .toc .toc-title { margin-top: 0; } 835 .toc ol { margin: 0; padding-left: 1.2em; columns: 2; column-gap: 2rem; font-size: var(--fs-md); } 836 .toc a { color: var(--text); } 837 .toc a:hover { color: var(--accent); } 838 839 .endpoint { margin-bottom: 1.4rem; padding: 1.3rem 1.4rem; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--shadow-sm); scroll-margin-top: calc(var(--header-h) + 1rem); } 840 .endpoint > p:first-of-type { margin-top: 0; } 841 .route-row { display: flex; align-items: center; flex-wrap: wrap; gap: 0.6rem; margin-bottom: 0.6rem; } 842 .method { padding: 0.15rem 0.5rem; border-radius: var(--r-sm); font-family: var(--mono); font-size: var(--fs-xs); font-weight: 750; letter-spacing: 0.04em; } 843 .method.get { background: var(--success-soft); color: var(--success); } 844 .method.post { background: var(--accent-soft); color: var(--accent); } 845 .route-path { font-family: var(--mono); font-size: 1rem; color: var(--text); overflow-wrap: anywhere; } 846 .domain-tag { padding: 0.1rem 0.45rem; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-sm); color: var(--muted); font-family: var(--mono); font-size: var(--fs-xs); } 847 .prose table { width: 100%; margin: 0.5rem 0; border-collapse: collapse; font-size: var(--fs-md); display: block; overflow-x: auto; } 848 .prose th, .prose td { padding: 0.45rem 0.7rem; border-bottom: 1px solid var(--border); text-align: left; vertical-align: top; } 849 .prose th { color: var(--muted); font-size: var(--fs-xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; } 850 .prose td { color: var(--text); } 851 .prose td.desc { color: var(--muted); } 852 .err-list { list-style: none; margin: 0.4rem 0; padding: 0 !important; } 853 .err-list li { padding: 0.3rem 0; font-size: var(--fs-md); overflow: hidden; } 854 .err-code { float: left; width: 3.2em; margin-right: 0.6em; color: var(--danger); font-family: var(--mono); font-weight: 650; } 855 .code-block { position: relative; } 856 .code-block .copy-code { position: absolute; top: 0.5rem; right: 0.5rem; } 857 858 /* ============================== 11. Stats ============================== */ 859 .page-stats .muted { color: var(--muted); font-size: var(--fs-md); } 860 .page-stats h1 { margin: 0 0 0.25rem; } 861 .page-stats h2 { font-size: var(--fs-base); margin: 0; font-weight: 650; } 862 .page-stats { --c0: #4c8dff; --c1: #3fb950; --c2: #d29922; --c3: #f85149; --c4: #a371f7; --c5: #39c5cf; --c6: #db61a2; --c7: #8b949e; --c8: #e3702d; } 863 .page-stats .tiles { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.75rem; margin: 1.25rem 0 1rem; } 864 .page-stats .tile, .page-stats .card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--shadow-sm); } 865 .page-stats .tile { padding: 0.9rem 1.1rem; } 866 .page-stats .tile b { display: block; font-size: 1.6rem; line-height: 1.2; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; } 867 .page-stats .tile span { color: var(--muted); font-size: var(--fs-sm); } 868 .page-stats .grid { display: grid; grid-template-columns: 1fr; gap: 1rem; } 869 .page-stats .card { padding: 1rem 1.15rem 1.15rem; min-width: 0; } 870 .page-stats .card > header { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 0.6rem; margin-bottom: 0.9rem; } 871 .page-stats .seg { display: inline-flex; padding: 2px; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-sm); } 872 .page-stats .seg button { min-height: 1.9rem; padding: 0.25rem 0.8rem; border: 0; border-radius: 4px; background: none; color: var(--muted); font-size: var(--fs-sm); font-weight: 600; cursor: pointer; } 873 .page-stats .seg button[aria-pressed="true"] { background: var(--surface); color: var(--text); box-shadow: var(--shadow-sm); } 874 .page-stats .donut-wrap { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 1.5rem; } 875 .page-stats .donut { position: relative; flex: none; width: 150px; height: 150px; margin: 0 auto; } 876 .page-stats .donut svg { width: 100%; height: 100%; transform: rotate(-90deg); } 877 .page-stats .donut circle { fill: none; stroke-width: 7; } 878 .page-stats .donut .hole { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; line-height: 1.2; } 879 .page-stats .donut .hole b { font-size: 1.15rem; font-variant-numeric: tabular-nums; } 880 .page-stats .legend { flex: 1 1 200px; display: grid; gap: 0.45rem; margin: 0; padding: 0; list-style: none; font-size: var(--fs-md); } 881 .page-stats .legend li { display: flex; align-items: center; gap: 0.5rem; color: var(--text); } 882 .page-stats .legend i { flex: none; width: 11px; height: 11px; border-radius: 3px; } 883 .page-stats .legend .n { margin-left: auto; color: var(--muted); white-space: nowrap; font-variant-numeric: tabular-nums; } 884 .page-stats .bars { display: grid; gap: 0.7rem; } 885 .page-stats .bar .top { display: flex; justify-content: space-between; gap: 0.6rem; font-size: var(--fs-md); } 886 .page-stats .bar .top span:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } 887 .page-stats .bar .top span:last-child { color: var(--muted); white-space: nowrap; font-variant-numeric: tabular-nums; } 888 .page-stats .track { height: 8px; margin-top: 0.3rem; border-radius: 4px; background: var(--surface-3); overflow: hidden; } 889 .page-stats .track i { display: block; min-width: 2px; height: 100%; border-radius: 4px; background: var(--accent); } 890 .page-stats .cols { display: flex; align-items: flex-end; gap: 6px; height: 170px; padding-top: 18px; } 891 .page-stats .col { flex: 1; min-width: 0; height: 100%; display: flex; flex-direction: column; justify-content: flex-end; align-items: center; } 892 .page-stats .col .v { color: var(--muted); font-size: 0.7rem; font-variant-numeric: tabular-nums; } 893 .page-stats .col i { width: 100%; max-width: 44px; min-height: 2px; border-radius: 4px 4px 0 0; background: var(--accent); } 894 .page-stats .labels { display: flex; gap: 6px; margin-top: 6px; } 895 .page-stats .labels span { flex: 1; min-width: 0; text-align: center; color: var(--muted); font-size: 0.68rem; line-height: 1.25; overflow-wrap: anywhere; } 896 .page-stats .files { margin: 0; padding: 0; list-style: none; } 897 .page-stats .files li { display: flex; justify-content: space-between; gap: 0.75rem; padding: 0.55rem 0; border-top: 1px solid var(--border); font-size: var(--fs-md); } 898 .page-stats .files li:first-child { border-top: 0; padding-top: 0; } 899 .page-stats .files a { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } 900 .page-stats .files span { color: var(--muted); white-space: nowrap; font-variant-numeric: tabular-nums; } 901 .page-stats .note { padding: 2.5rem 0; text-align: center; color: var(--muted); } 902 .page-stats .note button { margin-top: 0.75rem; padding: 0.5rem 1rem; background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--r-sm); cursor: pointer; } 903 904 /* ============================== 12. Shortener ============================== */ 905 .shorten > * { max-width: 44rem; } 906 .shorten .btn-icon { display: inline-flex; } 907 .shorten .btn-icon-spinner { display: none; } 908 .shorten .btn.is-loading .btn-icon-default { display: none; } 909 .shorten .btn.is-loading .btn-icon-spinner { display: inline-flex; } 910 .shorten .url-input { padding-right: 2.6rem; } 911 .shorten .actions { display: flex; gap: 0.75rem; align-items: center; margin-top: 1rem; } 912 .error-box { display: none; margin-top: 1rem; padding: 0.8rem 1rem; background: var(--danger-soft); border: 1px solid var(--danger-border); border-radius: var(--r); color: var(--danger); } 913 .result-box { margin-top: 1.5rem; padding: 1.25rem; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--shadow-sm); animation: page-in 0.2s var(--ease) both; } 914 .result-box h3 { margin-bottom: 0.75rem; } 915 .result-url { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; padding: 0.6rem 0.75rem; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r); } 916 .result-url a { min-width: 0; overflow-wrap: anywhere; font-family: var(--mono); font-size: var(--fs-md); } 917 .info-text { margin: 0.75rem 0 0; color: var(--muted); font-size: var(--fs-sm); } 918 919 /* ============================== 13. Responsive ============================== */ 920 @media (max-width: 820px) { 921 .site-header__tools .nav-toggle { display: inline-flex; } 922 .site-nav { 923 display: none; order: 3; flex: 1 0 100%; 924 flex-direction: column; align-items: stretch; justify-content: flex-start; 925 gap: 2px; padding: 0.4rem 0 0.9rem; 926 } 927 .site-nav.is-open { display: flex; max-height: calc(100vh - var(--header-h) - env(safe-area-inset-top)); max-height: calc(100dvh - var(--header-h) - env(safe-area-inset-top)); overflow-y: auto; overscroll-behavior: contain; } 928 .site-nav .nav-link { padding: 0.7rem 0.75rem; font-size: var(--fs-base); } 929 .nav-cta { margin: 0.4rem 0 0; justify-content: center; } 930 .more__toggle { display: none; } 931 .more__menu { display: flex; position: static; min-width: 0; padding: 0; flex-direction: column; gap: 2px; background: none; border: 0; box-shadow: none; } 932 .site-header__tools { margin-left: auto; gap: 0.15rem; } 933 .site-header__tools .quick-action { display: inline-flex; } 934 .site-header__tools .icon-btn { width: 2.6rem; height: 2.6rem; } 935 .site-nav .nav-dup { display: none; } 936 .wordmark { order: 0; } 937 } 938 939 @media (max-width: 640px) { 940 :root { --gutter: 1rem; } 941 .page { padding-top: 1.1rem; } 942 .file-head { grid-template-columns: minmax(0, 1fr); } 943 .file-head__actions { justify-content: stretch; } 944 .file-head__actions .btn { flex: 1 1 0; } 945 .link-row { grid-template-columns: minmax(0, 1fr) auto; } 946 .link-row__label { grid-column: 1 / -1; } 947 .link-row { align-items: start; } 948 .link-row__label small { display: inline; margin-left: 0.4rem; } 949 .toc ol { columns: 1; } 950 /* small copy buttons become icon-only: the copy glyph is universal, and the link box gets the room back */ 951 .link-row .btn > span, [data-copy-preview] > span { display: none; } 952 .link-row .btn-sm, .preview__bar .btn-sm { width: 2.6rem; min-width: 2.6rem; height: 2.6rem; padding: 0; } 953 .preview__bar { padding-right: 0.5rem; } 954 .sk-btn { width: 2.6rem; height: 2.6rem; } 955 .list-item { padding-left: 0.85rem; padding-right: 0.85rem; } 956 .item-name { gap: 0.65rem; } 957 .listing-toolbar { flex-wrap: nowrap; } 958 .listing-toolbar__counts { flex: 1 1 auto; min-width: 0; line-height: 1.35; } 959 .listing-toolbar__actions { flex: 0 0 auto; flex-wrap: nowrap; gap: 0.4rem; } 960 .listing-toolbar__actions .btn { white-space: nowrap; padding-left: 0.7rem; padding-right: 0.7rem; } 961 .zip-long { display: none; } 962 .zip-short { display: inline; } 963 .listing-toolbar__actions .select { max-width: 7.6rem; } 964 .file-head__actions .btn-primary { flex: 1 1 100%; } 965 .dropzone { padding: 2.25rem 1rem; } 966 .input-row { flex-direction: column; } 967 .page-stats .tiles { grid-template-columns: repeat(2, 1fr); } 968 .result-url { flex-direction: column; align-items: stretch; } 969 .site-footer__inner { align-items: flex-start; flex-direction: column; } 970 } 971 972 @media (min-width: 760px) { 973 .page-stats .tiles { grid-template-columns: repeat(4, 1fr); } 974 .page-stats .grid { grid-template-columns: 1fr 1fr; } 975 .page-stats .span2 { grid-column: 1 / -1; } 976 } 977 978 /* ============================== 14. Motion / print ============================== */ 979 @keyframes spin { to { transform: rotate(360deg); } } 980 @keyframes page-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } } 981 @keyframes toast-in { from { opacity: 0; transform: translateY(10px) scale(0.98); } to { opacity: 1; transform: none; } } 982 @keyframes toast-out { to { opacity: 0; transform: translateY(6px); } } 983 @keyframes shimmer { to { background-position: -200% 0; } } 984 985 @media (prefers-reduced-motion: reduce) { 986 *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; } 987 } 988 989 @media print { 990 .site-header, .breadcrumb-container, .site-footer, .toasts, .listing-toolbar__actions, .skip-link { display: none !important; } 991 body { background: #fff; color: #000; } 992 .page { padding: 0; max-width: none; animation: none; } 993 } 994 995 /* ---- File-type colours: --ft is set from the file name alone, so server-built and browser-built rows match ---- */ 996 [data-name$=".png" i], 997 [data-name$=".jpg" i], 998 [data-name$=".jpeg" i], 999 [data-name$=".gif" i], 1000 [data-name$=".webp" i], 1001 [data-name$=".avif" i], 1002 [data-name$=".bmp" i], 1003 [data-name$=".ico" i], 1004 [data-name$=".svg" i], 1005 [data-name$=".heic" i], 1006 [data-name$=".tif" i], 1007 [data-name$=".tiff" i] { --ft: var(--ft-image); } 1008 [data-name$=".mp4" i], 1009 [data-name$=".webm" i], 1010 [data-name$=".mov" i], 1011 [data-name$=".mkv" i], 1012 [data-name$=".avi" i], 1013 [data-name$=".m4v" i], 1014 [data-name$=".ogv" i] { --ft: var(--ft-video); } 1015 [data-name$=".mp3" i], 1016 [data-name$=".wav" i], 1017 [data-name$=".ogg" i], 1018 [data-name$=".oga" i], 1019 [data-name$=".flac" i], 1020 [data-name$=".m4a" i], 1021 [data-name$=".aac" i], 1022 [data-name$=".opus" i] { --ft: var(--ft-audio); } 1023 [data-name$=".zip" i], 1024 [data-name$=".tar" i], 1025 [data-name$=".gz" i], 1026 [data-name$=".tgz" i], 1027 [data-name$=".bz2" i], 1028 [data-name$=".xz" i], 1029 [data-name$=".7z" i], 1030 [data-name$=".rar" i], 1031 [data-name$=".zst" i] { --ft: var(--ft-archive); } 1032 [data-name$=".js" i], 1033 [data-name$=".mjs" i], 1034 [data-name$=".cjs" i], 1035 [data-name$=".ts" i], 1036 [data-name$=".tsx" i], 1037 [data-name$=".jsx" i], 1038 [data-name$=".css" i], 1039 [data-name$=".scss" i], 1040 [data-name$=".sass" i], 1041 [data-name$=".less" i], 1042 [data-name$=".html" i], 1043 [data-name$=".htm" i], 1044 [data-name$=".py" i], 1045 [data-name$=".rb" i], 1046 [data-name$=".go" i], 1047 [data-name$=".rs" i], 1048 [data-name$=".c" i], 1049 [data-name$=".h" i], 1050 [data-name$=".cpp" i], 1051 [data-name$=".hpp" i], 1052 [data-name$=".cc" i], 1053 [data-name$=".java" i], 1054 [data-name$=".kt" i], 1055 [data-name$=".swift" i], 1056 [data-name$=".php" i], 1057 [data-name$=".sh" i], 1058 [data-name$=".bash" i], 1059 [data-name$=".zsh" i], 1060 [data-name$=".bat" i], 1061 [data-name$=".ps1" i], 1062 [data-name$=".sql" i], 1063 [data-name$=".lua" i], 1064 [data-name$=".r" i], 1065 [data-name$=".pl" i], 1066 [data-name$=".vue" i], 1067 [data-name$=".svelte" i] { --ft: var(--ft-code); } 1068 [data-name$=".pdf" i], 1069 [data-name$=".doc" i], 1070 [data-name$=".docx" i], 1071 [data-name$=".ppt" i], 1072 [data-name$=".pptx" i], 1073 [data-name$=".odt" i], 1074 [data-name$=".rtf" i], 1075 [data-name$=".md" i], 1076 [data-name$=".markdown" i], 1077 [data-name$=".txt" i], 1078 [data-name$=".epub" i], 1079 [data-name$=".rst" i], 1080 [data-name$=".tex" i] { --ft: var(--ft-doc); } 1081 [data-name$=".json" i], 1082 [data-name$=".jsonc" i], 1083 [data-name$=".csv" i], 1084 [data-name$=".tsv" i], 1085 [data-name$=".xml" i], 1086 [data-name$=".yml" i], 1087 [data-name$=".yaml" i], 1088 [data-name$=".toml" i], 1089 [data-name$=".ini" i], 1090 [data-name$=".cfg" i], 1091 [data-name$=".conf" i], 1092 [data-name$=".xls" i], 1093 [data-name$=".xlsx" i], 1094 [data-name$=".db" i], 1095 [data-name$=".sqlite" i], 1096 [data-name$=".log" i], 1097 [data-name$=".map" i] { --ft: var(--ft-data); } 1098 [data-name$=".woff" i], 1099 [data-name$=".woff2" i], 1100 [data-name$=".ttf" i], 1101 [data-name$=".otf" i], 1102 [data-name$=".eot" i] { --ft: var(--ft-font); }