drbh/compare-moe-uvnote
0
1<!DOCTYPE html>2<html lang="en">3<head>4 <meta charset="UTF-8">5 <meta name="viewport" content="width=device-width, initial-scale=1.0">6 <title>GPT-OSS vs MegaBlocks MoE Comparison</title>7 <script>8 // Apply theme immediately to prevent flicker9 (function() {10 const configTheme = 'dark';11 let theme;12 if (configTheme === 'auto') {13 theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';14 } else {15 theme = localStorage.getItem('uvnote-theme') || configTheme;16 }17 document.documentElement.setAttribute('data-theme', theme);18 })();19 </script>20 <style>21 :root[data-theme="light"] {22 --bg-primary: #ffffff;23 --bg-secondary: #f6f8fa;24 --bg-tertiary: #f8f9fa;25 --bg-code: #f8f9fa;26 --bg-error: #fdf2f2;27 --bg-artifact: #e6f3ff;28 --bg-artifact-hover: #d0e7ff;29 30 --text-primary: #333;31 --text-secondary: #656d76;32 --text-error: #c53030;33 --text-link: #0969da;34 35 --border-primary: #e1e5e9;36 --border-error: #e53e3e;37 --border-cell-failed: #d73a49;38 39 --shadow: rgba(0, 0, 0, 0.1);40 }41 42 :root[data-theme="dark"] {43 --bg-primary: #0a0a0a;44 --bg-secondary: #121212;45 --bg-tertiary: #181818;46 --bg-code: #0d0d0d;47 --bg-error: #1a0f0f;48 --bg-artifact: #151515;49 --bg-artifact-hover: #1a1a1a;50 51 --text-primary: #e0e0e0;52 --text-secondary: #888888;53 --text-error: #ff6b6b;54 --text-link: #64b5f6;55 56 --border-primary: #2a2a2a;57 --border-error: #ff6b6b;58 --border-cell-failed: #ff6b6b;59 60 --shadow: rgba(255, 255, 255, 0.05);61 }62 html {63 overscroll-behavior: none;64 }65 body {66 font-family: 'Cascadia Mono', 'Cascadia Code', 'JetBrains Mono', 'SF Mono', Monaco, 'Consolas', monospace;67 line-height: 1.4;68 max-width: 1000px;69 margin: 0 auto;70 padding: 15px;71 color: var(--text-primary);72 background: var(--bg-primary);73 transition: background-color 0.2s ease, color 0.2s ease;74 overscroll-behavior: none;75 }76 77 /* Two panel layout removed */78 79 .controls {80 position: fixed;81 top: 20px;82 right: 20px;83 display: flex;84 gap: 0.5rem;85 z-index: 1000;86 }87 88 .menu-button {89 position: relative;90 background: var(--bg-secondary);91 border: 1px solid var(--border-primary);92 padding: 8px 12px;93 border-radius: 4px;94 color: var(--text-secondary);95 cursor: pointer;96 font-family: inherit;97 font-size: 0.9rem;98 user-select: none;99 }100 101 .menu-button:hover {102 color: var(--text-primary);103 background: var(--bg-tertiary);104 }105 106 .menu-dropdown {107 position: absolute;108 top: 100%;109 right: 0;110 background: var(--bg-secondary);111 border: 1px solid var(--border-primary);112 border-radius: 4px;113 box-shadow: 0 4px 12px var(--shadow);114 min-width: 160px;115 opacity: 0;116 visibility: hidden;117 transform: translateY(-8px);118 transition: all 0.2s ease;119 z-index: 1001;120 margin-top: 4px;121 }122 123 .menu-button.active .menu-dropdown {124 opacity: 1;125 visibility: visible;126 transform: translateY(0);127 }128 129 .menu-item {130 display: block;131 padding: 8px 12px;132 color: var(--text-secondary);133 text-decoration: none;134 font-size: 0.85rem;135 border-bottom: 1px solid var(--border-primary);136 cursor: pointer;137 }138 139 .menu-item:last-child {140 border-bottom: none;141 }142 143 .menu-item:hover {144 background: var(--bg-tertiary);145 color: var(--text-primary);146 }147 148 .menu-checkbox {149 display: inline-block;150 width: 16px;151 font-family: monospace;152 color: var(--text-link);153 }154 155 .theme-toggle,156 .reset-toggle {157 background: var(--bg-secondary);158 border: 1px solid var(--border-primary);159 padding: 8px 12px;160 border-radius: 4px;161 color: var(--text-secondary);162 cursor: pointer;163 font-family: inherit;164 font-size: 0.9rem;165 user-select: none;166 }167 168 .theme-toggle:hover,169 .reset-toggle:hover {170 color: var(--text-primary);171 background: var(--bg-tertiary);172 }173 174 .system-info {175 background: var(--bg-secondary);176 border: 1px solid var(--border-primary);177 border-radius: 4px;178 padding: 8px 12px;179 margin-bottom: 16px;180 font-size: 0.85em;181 color: var(--text-secondary);182 }183 184 .system-info-header {185 font-weight: 600;186 color: var(--text-primary);187 margin-bottom: 2px;188 }189 190 .system-info-content {191 font-family: monospace;192 }193 194 .theme-toggle, .reset-toggle {195 background: var(--bg-secondary);196 border: 1px solid var(--border-primary);197 border-radius: 2px;198 padding: 0.4rem 0.6rem;199 cursor: pointer;200 font-family: inherit;201 font-size: 0.8rem;202 color: var(--text-secondary);203 user-select: none;204 transition: all 0.2s ease;205 text-transform: lowercase;206 letter-spacing: 0;207 }208 209 .theme-toggle:hover, .reset-toggle:hover {210 background: var(--bg-tertiary);211 border-color: var(--text-secondary);212 color: var(--text-primary);213 }214 215 .minimap {216 position: fixed;217 bottom: 20px;218 right: 20px;219 width: 220px;220 max-height: 400px;221 background: var(--bg-secondary);222 border: 1px solid var(--border-primary);223 border-radius: 2px;224 padding: 0.5rem;225 font-size: 0.7rem;226 overflow-y: auto;227 z-index: 100;228 opacity: 0.9;229 transition: opacity 0.2s ease;230 }231 232 .file-explorer {233 position: fixed;234 bottom: 20px; /* default; JS will stack */235 right: 20px;236 left: auto;237 top: auto;238 width: 220px;239 max-height: 400px;240 background: var(--bg-secondary);241 border: 1px solid var(--border-primary);242 border-radius: 2px;243 padding: 0.5rem;244 font-size: 0.7rem;245 overflow-y: auto;246 z-index: 100;247 opacity: 0.9;248 transition: opacity 0.2s ease;249 }250 251 /* Drawing overlay */252 .draw-overlay {253 position: fixed;254 top: 0;255 left: 0;256 width: 100vw;257 height: 100vh;258 z-index: 80; /* under widgets (100) and controls (1000) */259 display: block;260 pointer-events: none; /* enabled only when a tool is active */261 }262 263 /* Tools widget */264 .tools-widget {265 position: fixed;266 bottom: 20px; /* default; JS will stack */267 right: 20px;268 left: auto;269 top: auto;270 width: 220px;271 background: var(--bg-secondary);272 border: 1px solid var(--border-primary);273 border-radius: 2px;274 padding: 0.5rem;275 font-size: 0.7rem;276 z-index: 100;277 opacity: 0.95;278 }279 .tools-title {280 font-weight: bold;281 color: var(--text-secondary);282 margin-bottom: 0.5rem;283 padding-bottom: 0.25rem;284 border-bottom: 1px solid var(--border-primary);285 cursor: grab;286 user-select: none;287 }288 .tools-row { display: flex; gap: 0.4rem; flex-wrap: wrap; }289 .tool-button {290 background: var(--bg-tertiary);291 border: 1px solid var(--border-primary);292 border-radius: 2px;293 padding: 0.25rem 0.4rem;294 cursor: pointer;295 color: var(--text-secondary);296 font-family: inherit;297 font-size: 0.75rem;298 user-select: none;299 }300 .tool-button:hover { color: var(--text-primary); }301 .tool-button.active { color: var(--text-primary); border-color: var(--text-secondary); background: var(--bg-secondary); }302 303 .minimap:hover, .file-explorer:hover {304 opacity: 1;305 }306 307 .minimap-title {308 font-weight: bold;309 color: var(--text-secondary);310 margin-bottom: 0.5rem;311 padding-bottom: 0.25rem;312 border-bottom: 1px solid var(--border-primary);313 cursor: grab; /* drag handle */314 user-select: none;315 }316 317 .minimap-item {318 display: block;319 color: var(--text-secondary);320 text-decoration: none;321 padding: 0.15rem 0;322 border-left: 2px solid transparent;323 padding-left: 0.5rem;324 transition: all 0.2s ease;325 cursor: pointer;326 }327 328 .minimap-item:hover {329 color: var(--text-primary);330 border-left-color: var(--text-secondary);331 }332 333 .minimap-item.active {334 color: var(--text-primary);335 border-left-color: var(--text-link);336 }337 338 .minimap-heading {339 font-weight: normal;340 }341 342 .minimap-heading.h1 { padding-left: 0.5rem; }343 .minimap-heading.h2 { padding-left: 1rem; }344 .minimap-heading.h3 { padding-left: 1.5rem; }345 .minimap-heading.h4 { padding-left: 2rem; }346 .minimap-heading.h5 { padding-left: 2.5rem; }347 .minimap-heading.h6 { padding-left: 3rem; }348 349 .minimap-cell {350 color: var(--text-link);351 opacity: 0.8;352 font-style: italic;353 }354 355 .minimap-cell:hover {356 opacity: 1;357 }358 359 .file-explorer-title {360 font-weight: bold;361 color: var(--text-secondary);362 margin-bottom: 0.5rem;363 padding-bottom: 0.25rem;364 border-bottom: 1px solid var(--border-primary);365 cursor: grab; /* drag handle */366 user-select: none;367 }368 369 .file-explorer-section {370 margin-bottom: 0.75rem;371 }372 373 .file-explorer-section-title {374 font-weight: bold;375 color: var(--text-secondary);376 font-size: 0.65rem;377 margin-bottom: 0.25rem;378 text-transform: uppercase;379 letter-spacing: 0.5px;380 }381 382 .file-explorer-item {383 display: block;384 color: var(--text-secondary);385 text-decoration: none;386 padding: 0.1rem 0;387 margin-left: 0.5rem;388 transition: color 0.2s ease;389 cursor: pointer;390 font-family: monospace;391 }392 393 .file-explorer-item:hover {394 color: var(--text-primary);395 }396 397 .file-explorer-item.script {398 color: var(--text-link);399 }400 401 .file-explorer-item.artifact {402 color: var(--text-secondary);403 opacity: 0.8;404 }405 406 407 /* Hide widgets on smaller screens */408 @media (max-width: 768px) {409 .minimap, .file-explorer, .tools-widget {410 display: none;411 }412 }413 414 .cell {415 margin: 1rem 0;416 border: 1px solid var(--border-primary);417 border-radius: 2px;418 overflow: hidden;419 background: var(--bg-secondary);420 }421 .cell-header {422 background: var(--bg-secondary);423 padding: 0.5rem 1rem;424 border-bottom: 1px solid var(--border-primary);425 font-family: inherit;426 font-size: 0.85rem;427 color: var(--text-secondary);428 cursor: pointer;429 user-select: none;430 transition: background-color 0.2s ease;431 }432 .cell-header:hover {433 background: var(--bg-tertiary);434 }435 .collapse-indicators {436 color: var(--text-secondary);437 font-size: 0.8rem;438 opacity: 0.7;439 }440 .collapse-indicators span:hover {441 color: var(--text-primary);442 opacity: 1;443 }444 .cell-code {445 display: block;446 background: var(--bg-code);447 }448 .cell-code.collapsed {449 display: none;450 }451 .cell-code pre {452 margin: 0;453 padding: 0.75rem;454 background: var(--bg-code);455 overflow-x: auto;456 color: var(--text-primary);457 }458 .cell-output {459 padding: 0.75rem;460 background: var(--bg-primary);461 }462 .cell-output.collapsed {463 display: none;464 }465 .cell-stdout {466 background: var(--bg-tertiary);467 padding: 0.75rem;468 border-radius: 1px;469 margin: 0.25rem 0;470 font-family: inherit;471 font-size: 0.9rem;472 white-space: pre-wrap;473 color: var(--text-primary);474 }475 .cell-stderr {476 background: var(--bg-error);477 border-left: 2px solid var(--border-error);478 padding: 1rem;479 margin: 0.5rem 0;480 font-family: inherit;481 font-size: 0.9rem;482 color: var(--text-error);483 white-space: pre-wrap;484 }485 .uv-install-logs {486 margin: 0.5rem 0;487 }488 .uv-logs-header {489 cursor: pointer;490 padding: 0.75rem;491 border-left: 3px solid var(--border-color);492 font-family: inherit;493 font-size: 0.85rem;494 color: var(--text-secondary);495 user-select: none;496 }497 .uv-logs-content {498 background: var(--bg-secondary);499 padding: 1rem;500 border-left: 3px solid var(--border-color);501 white-space: pre-wrap;502 font-family: monospace;503 font-size: 0.85rem;504 color: var(--text-secondary);505 overflow-x: auto;506 }507 .cell-artifacts {508 margin: 1rem 0;509 }510 .cell-artifacts h4 {511 margin: 0 0 0.5rem 0;512 color: var(--text-secondary);513 font-size: 0.9rem;514 }515 .artifact {516 display: inline-block;517 background: var(--bg-artifact);518 padding: 0.25rem 0.5rem;519 border-radius: 1px;520 margin: 0.25rem 0.5rem 0.25rem 0;521 font-family: inherit;522 font-size: 0.8rem;523 color: var(--text-link);524 text-decoration: none;525 transition: background-color 0.2s ease;526 border: 1px solid var(--border-primary);527 }528 .artifact:hover {529 background: var(--bg-artifact-hover);530 }531 .artifact-preview {532 margin-top: 1rem;533 }534 .artifact-preview img {535 max-width: 100%;536 height: auto;537 border: 1px solid var(--border-primary);538 border-radius: 1px;539 }540 .artifact-preview svg {541 max-width: 100%;542 height: auto;543 border: 1px solid var(--border-primary);544 border-radius: 1px;545 display: block;546 }547 /* Style SVG text elements */548 .artifact-preview svg g {549 fill: var(--text-primary) !important;550 }551 /* Auto-theme SVG elements */552 .artifact-preview svg {553 background: transparent;554 }555 .cell-failed {556 border-color: var(--border-cell-failed);557 }558 .cell-failed .cell-header {559 background: var(--bg-error);560 color: var(--text-error);561 }562 .cell-commented {563 opacity: 0.6;564 border-style: dashed;565 }566 .cell-commented .cell-header {567 background: var(--bg-secondary);568 color: var(--text-secondary);569 font-style: italic;570 }571 .run-btn {572 background: var(--bg-tertiary);573 border: 1px solid var(--border-primary);574 padding: 2px 6px;575 border-radius: 2px;576 color: var(--text-secondary);577 cursor: pointer;578 font-size: 0.75em;579 font-family: inherit;580 margin-left: 4px;581 }582 .run-btn:hover {583 color: var(--text-primary);584 background: var(--bg-primary);585 }586 .run-btn:disabled {587 opacity: 0.6;588 cursor: not-allowed;589 }590 .copy-btn {591 background: var(--bg-tertiary);592 border: 1px solid var(--border-primary);593 padding: 2px 6px;594 border-radius: 2px;595 color: var(--text-secondary);596 cursor: pointer;597 font-size: 0.75em;598 font-family: inherit;599 margin-left: 4px;600 }601 .copy-btn:hover {602 color: var(--text-primary);603 background: var(--bg-primary);604 }605 .copy-btn:disabled {606 opacity: 0.6;607 cursor: not-allowed;608 }609 .raw-btn {610 background: var(--bg-tertiary);611 border: 1px solid var(--border-primary);612 padding: 2px 6px;613 border-radius: 2px;614 color: var(--text-secondary);615 cursor: pointer;616 font-size: 0.75em;617 font-family: inherit;618 margin-left: 4px;619 text-decoration: none;620 display: inline-block;621 }622 .raw-btn:hover {623 color: var(--text-primary);624 background: var(--bg-primary);625 text-decoration: none;626 }627 .output-stale {628 opacity: 0.5;629 position: relative;630 }631 .output-stale::after {632 content: '⏳ updating...';633 position: absolute;634 top: 8px;635 right: 8px;636 background: var(--bg-secondary);637 padding: 4px 8px;638 border-radius: 2px;639 font-size: 0.75em;640 color: var(--text-secondary);641 border: 1px solid var(--border-primary);642 }643 h1, h2, h3, h4, h5, h6 {644 margin-top: 1.5rem;645 margin-bottom: 0.75rem;646 color: var(--text-primary);647 }648 h1 {649 margin-top: 0;650 margin-bottom: 1rem;651 }652 p {653 margin: 0.75rem 0;654 color: var(--text-primary);655 }656 a {657 color: var(--text-link);658 }659 img {660 max-width: 100%;661 height: auto;662 border-radius: 1px;663 box-shadow: none;664 }665 pre, code {666 font-family: 'Cascadia Mono', 'Cascadia Code', 'JetBrains Mono', 'SF Mono', Monaco, 'Consolas', monospace;667 }668 669 /* Line numbers */670 .highlight-with-lines {671 display: flex;672 }673 .line-numbers {674 background: var(--bg-tertiary);675 padding: 0.75rem 0.5rem;676 font-family: 'Cascadia Mono', 'Cascadia Code', 'JetBrains Mono', 'SF Mono', Monaco, 'Consolas', monospace;677 font-size: 0.9rem;678 color: var(--text-secondary);679 user-select: none;680 text-align: right;681 border-right: 1px solid var(--border-primary);682 }683 .line-numbers .line-number {684 display: block;685 line-height: 1.5;686 }687 .highlight-with-lines .highlight {688 flex: 1;689 }690 .highlight-with-lines .highlight pre {691 padding-left: 0.75rem;692 }693 694 /* Collapsed code styling */695 .cell-code.collapsed {696 display: none;697 }698 .cell-code.expanded {699 display: block;700 }701 702 .cell-code {703 display: block;704 }705 706 707 pre { line-height: 125%; }708td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }709span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }710td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }711span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }712[data-theme="light"] .highlight .hll { background-color: #ffffcc }713[data-theme="light"] .highlight { background: #f8f8f8; }714[data-theme="light"] .highlight .c { color: #3D7B7B; font-style: italic } /* Comment */715[data-theme="light"] .highlight .err { border: 1px solid #F00 } /* Error */716[data-theme="light"] .highlight .k { color: #008000; font-weight: bold } /* Keyword */717[data-theme="light"] .highlight .o { color: #666 } /* Operator */718[data-theme="light"] .highlight .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */719[data-theme="light"] .highlight .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */720[data-theme="light"] .highlight .cp { color: #9C6500 } /* Comment.Preproc */721[data-theme="light"] .highlight .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */722[data-theme="light"] .highlight .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */723[data-theme="light"] .highlight .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */724[data-theme="light"] .highlight .gd { color: #A00000 } /* Generic.Deleted */725[data-theme="light"] .highlight .ge { font-style: italic } /* Generic.Emph */726[data-theme="light"] .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */727[data-theme="light"] .highlight .gr { color: #E40000 } /* Generic.Error */728[data-theme="light"] .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */729[data-theme="light"] .highlight .gi { color: #008400 } /* Generic.Inserted */730[data-theme="light"] .highlight .go { color: #717171 } /* Generic.Output */731[data-theme="light"] .highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */732[data-theme="light"] .highlight .gs { font-weight: bold } /* Generic.Strong */733[data-theme="light"] .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */734[data-theme="light"] .highlight .gt { color: #04D } /* Generic.Traceback */735[data-theme="light"] .highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */736[data-theme="light"] .highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */737[data-theme="light"] .highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */738[data-theme="light"] .highlight .kp { color: #008000 } /* Keyword.Pseudo */739[data-theme="light"] .highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */740[data-theme="light"] .highlight .kt { color: #B00040 } /* Keyword.Type */741[data-theme="light"] .highlight .m { color: #666 } /* Literal.Number */742[data-theme="light"] .highlight .s { color: #BA2121 } /* Literal.String */743[data-theme="light"] .highlight .na { color: #687822 } /* Name.Attribute */744[data-theme="light"] .highlight .nb { color: #008000 } /* Name.Builtin */745[data-theme="light"] .highlight .nc { color: #00F; font-weight: bold } /* Name.Class */746[data-theme="light"] .highlight .no { color: #800 } /* Name.Constant */747[data-theme="light"] .highlight .nd { color: #A2F } /* Name.Decorator */748[data-theme="light"] .highlight .ni { color: #717171; font-weight: bold } /* Name.Entity */749[data-theme="light"] .highlight .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */750[data-theme="light"] .highlight .nf { color: #00F } /* Name.Function */751[data-theme="light"] .highlight .nl { color: #767600 } /* Name.Label */752[data-theme="light"] .highlight .nn { color: #00F; font-weight: bold } /* Name.Namespace */753[data-theme="light"] .highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */754[data-theme="light"] .highlight .nv { color: #19177C } /* Name.Variable */755[data-theme="light"] .highlight .ow { color: #A2F; font-weight: bold } /* Operator.Word */756[data-theme="light"] .highlight .w { color: #BBB } /* Text.Whitespace */757[data-theme="light"] .highlight .mb { color: #666 } /* Literal.Number.Bin */758[data-theme="light"] .highlight .mf { color: #666 } /* Literal.Number.Float */759[data-theme="light"] .highlight .mh { color: #666 } /* Literal.Number.Hex */760[data-theme="light"] .highlight .mi { color: #666 } /* Literal.Number.Integer */761[data-theme="light"] .highlight .mo { color: #666 } /* Literal.Number.Oct */762[data-theme="light"] .highlight .sa { color: #BA2121 } /* Literal.String.Affix */763[data-theme="light"] .highlight .sb { color: #BA2121 } /* Literal.String.Backtick */764[data-theme="light"] .highlight .sc { color: #BA2121 } /* Literal.String.Char */765[data-theme="light"] .highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */766[data-theme="light"] .highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */767[data-theme="light"] .highlight .s2 { color: #BA2121 } /* Literal.String.Double */768[data-theme="light"] .highlight .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */769[data-theme="light"] .highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */770[data-theme="light"] .highlight .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */771[data-theme="light"] .highlight .sx { color: #008000 } /* Literal.String.Other */772[data-theme="light"] .highlight .sr { color: #A45A77 } /* Literal.String.Regex */773[data-theme="light"] .highlight .s1 { color: #BA2121 } /* Literal.String.Single */774[data-theme="light"] .highlight .ss { color: #19177C } /* Literal.String.Symbol */775[data-theme="light"] .highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */776[data-theme="light"] .highlight .fm { color: #00F } /* Name.Function.Magic */777[data-theme="light"] .highlight .vc { color: #19177C } /* Name.Variable.Class */778[data-theme="light"] .highlight .vg { color: #19177C } /* Name.Variable.Global */779[data-theme="light"] .highlight .vi { color: #19177C } /* Name.Variable.Instance */780[data-theme="light"] .highlight .vm { color: #19177C } /* Name.Variable.Magic */781[data-theme="light"] .highlight .il { color: #666 } /* Literal.Number.Integer.Long */782 783pre { line-height: 125%; }784td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }785span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }786td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }787span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }788[data-theme="dark"] .highlight .hll { background-color: #49483e }789[data-theme="dark"] .highlight { background: #272822; color: #F8F8F2 }790[data-theme="dark"] .highlight .c { color: #959077 } /* Comment */791[data-theme="dark"] .highlight .err { color: #ED007E; background-color: #1E0010 } /* Error */792[data-theme="dark"] .highlight .esc { color: #F8F8F2 } /* Escape */793[data-theme="dark"] .highlight .g { color: #F8F8F2 } /* Generic */794[data-theme="dark"] .highlight .k { color: #66D9EF } /* Keyword */795[data-theme="dark"] .highlight .l { color: #AE81FF } /* Literal */796[data-theme="dark"] .highlight .n { color: #F8F8F2 } /* Name */797[data-theme="dark"] .highlight .o { color: #FF4689 } /* Operator */798[data-theme="dark"] .highlight .x { color: #F8F8F2 } /* Other */799[data-theme="dark"] .highlight .p { color: #F8F8F2 } /* Punctuation */800[data-theme="dark"] .highlight .ch { color: #959077 } /* Comment.Hashbang */801[data-theme="dark"] .highlight .cm { color: #959077 } /* Comment.Multiline */802[data-theme="dark"] .highlight .cp { color: #959077 } /* Comment.Preproc */803[data-theme="dark"] .highlight .cpf { color: #959077 } /* Comment.PreprocFile */804[data-theme="dark"] .highlight .c1 { color: #959077 } /* Comment.Single */805[data-theme="dark"] .highlight .cs { color: #959077 } /* Comment.Special */806[data-theme="dark"] .highlight .gd { color: #FF4689 } /* Generic.Deleted */807[data-theme="dark"] .highlight .ge { color: #F8F8F2; font-style: italic } /* Generic.Emph */808[data-theme="dark"] .highlight .ges { color: #F8F8F2; font-weight: bold; font-style: italic } /* Generic.EmphStrong */809[data-theme="dark"] .highlight .gr { color: #F8F8F2 } /* Generic.Error */810[data-theme="dark"] .highlight .gh { color: #F8F8F2 } /* Generic.Heading */811[data-theme="dark"] .highlight .gi { color: #A6E22E } /* Generic.Inserted */812[data-theme="dark"] .highlight .go { color: #66D9EF } /* Generic.Output */813[data-theme="dark"] .highlight .gp { color: #FF4689; font-weight: bold } /* Generic.Prompt */814[data-theme="dark"] .highlight .gs { color: #F8F8F2; font-weight: bold } /* Generic.Strong */815[data-theme="dark"] .highlight .gu { color: #959077 } /* Generic.Subheading */816[data-theme="dark"] .highlight .gt { color: #F8F8F2 } /* Generic.Traceback */817[data-theme="dark"] .highlight .kc { color: #66D9EF } /* Keyword.Constant */818[data-theme="dark"] .highlight .kd { color: #66D9EF } /* Keyword.Declaration */819[data-theme="dark"] .highlight .kn { color: #FF4689 } /* Keyword.Namespace */820[data-theme="dark"] .highlight .kp { color: #66D9EF } /* Keyword.Pseudo */821[data-theme="dark"] .highlight .kr { color: #66D9EF } /* Keyword.Reserved */822[data-theme="dark"] .highlight .kt { color: #66D9EF } /* Keyword.Type */823[data-theme="dark"] .highlight .ld { color: #E6DB74 } /* Literal.Date */824[data-theme="dark"] .highlight .m { color: #AE81FF } /* Literal.Number */825[data-theme="dark"] .highlight .s { color: #E6DB74 } /* Literal.String */826[data-theme="dark"] .highlight .na { color: #A6E22E } /* Name.Attribute */827[data-theme="dark"] .highlight .nb { color: #F8F8F2 } /* Name.Builtin */828[data-theme="dark"] .highlight .nc { color: #A6E22E } /* Name.Class */829[data-theme="dark"] .highlight .no { color: #66D9EF } /* Name.Constant */830[data-theme="dark"] .highlight .nd { color: #A6E22E } /* Name.Decorator */831[data-theme="dark"] .highlight .ni { color: #F8F8F2 } /* Name.Entity */832[data-theme="dark"] .highlight .ne { color: #A6E22E } /* Name.Exception */833[data-theme="dark"] .highlight .nf { color: #A6E22E } /* Name.Function */834[data-theme="dark"] .highlight .nl { color: #F8F8F2 } /* Name.Label */835[data-theme="dark"] .highlight .nn { color: #F8F8F2 } /* Name.Namespace */836[data-theme="dark"] .highlight .nx { color: #A6E22E } /* Name.Other */837[data-theme="dark"] .highlight .py { color: #F8F8F2 } /* Name.Property */838[data-theme="dark"] .highlight .nt { color: #FF4689 } /* Name.Tag */839[data-theme="dark"] .highlight .nv { color: #F8F8F2 } /* Name.Variable */840[data-theme="dark"] .highlight .ow { color: #FF4689 } /* Operator.Word */841[data-theme="dark"] .highlight .pm { color: #F8F8F2 } /* Punctuation.Marker */842[data-theme="dark"] .highlight .w { color: #F8F8F2 } /* Text.Whitespace */843[data-theme="dark"] .highlight .mb { color: #AE81FF } /* Literal.Number.Bin */844[data-theme="dark"] .highlight .mf { color: #AE81FF } /* Literal.Number.Float */845[data-theme="dark"] .highlight .mh { color: #AE81FF } /* Literal.Number.Hex */846[data-theme="dark"] .highlight .mi { color: #AE81FF } /* Literal.Number.Integer */847[data-theme="dark"] .highlight .mo { color: #AE81FF } /* Literal.Number.Oct */848[data-theme="dark"] .highlight .sa { color: #E6DB74 } /* Literal.String.Affix */849[data-theme="dark"] .highlight .sb { color: #E6DB74 } /* Literal.String.Backtick */850[data-theme="dark"] .highlight .sc { color: #E6DB74 } /* Literal.String.Char */851[data-theme="dark"] .highlight .dl { color: #E6DB74 } /* Literal.String.Delimiter */852[data-theme="dark"] .highlight .sd { color: #E6DB74 } /* Literal.String.Doc */853[data-theme="dark"] .highlight .s2 { color: #E6DB74 } /* Literal.String.Double */854[data-theme="dark"] .highlight .se { color: #AE81FF } /* Literal.String.Escape */855[data-theme="dark"] .highlight .sh { color: #E6DB74 } /* Literal.String.Heredoc */856[data-theme="dark"] .highlight .si { color: #E6DB74 } /* Literal.String.Interpol */857[data-theme="dark"] .highlight .sx { color: #E6DB74 } /* Literal.String.Other */858[data-theme="dark"] .highlight .sr { color: #E6DB74 } /* Literal.String.Regex */859[data-theme="dark"] .highlight .s1 { color: #E6DB74 } /* Literal.String.Single */860[data-theme="dark"] .highlight .ss { color: #E6DB74 } /* Literal.String.Symbol */861[data-theme="dark"] .highlight .bp { color: #F8F8F2 } /* Name.Builtin.Pseudo */862[data-theme="dark"] .highlight .fm { color: #A6E22E } /* Name.Function.Magic */863[data-theme="dark"] .highlight .vc { color: #F8F8F2 } /* Name.Variable.Class */864[data-theme="dark"] .highlight .vg { color: #F8F8F2 } /* Name.Variable.Global */865[data-theme="dark"] .highlight .vi { color: #F8F8F2 } /* Name.Variable.Instance */866[data-theme="dark"] .highlight .vm { color: #F8F8F2 } /* Name.Variable.Magic */867[data-theme="dark"] .highlight .il { color: #AE81FF } /* Literal.Number.Integer.Long */868 869 /* Custom CSS from frontmatter */870 .cell-stderr { max-height: 200px; overflow: auto; }871.minimap { display: none !important; }872.file-explorer { display: none !important; }873.cell-code { max-height: 400px; overflow: auto; }874 875 /* Cursor for tools */876 body[data-tool="arrow"] .main-content { 877 cursor: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="%23e53935" stroke-width="2"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/><path d="M2 2l7.586 7.586"/><circle cx="11" cy="11" r="2"/></svg>') 12 12, crosshair;878 }879 body[data-tool="pen"] .main-content { 880 cursor: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="%23e53935" stroke-width="2"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/><circle cx="4" cy="20" r="2" fill="%23e53935"/></svg>') 4 20, pointer;881 }882 body[data-tool="eraser"] .main-content { 883 cursor: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="%23e53935" stroke-width="2"><path d="M20 20H7l-7-7 7-7h13v14z"/><path d="M13 13l7-7"/><path d="M13 13L9 9"/></svg>') 12 12, auto;884 }885 886 /* Color picker styles */887 .tools-section-title {888 font-weight: bold;889 color: var(--text-secondary);890 font-size: 0.65rem;891 margin: 0.75rem 0 0.5rem 0;892 text-transform: uppercase;893 letter-spacing: 0.5px;894 }895 .color-row {896 display: grid;897 grid-template-columns: repeat(6, 1fr);898 gap: 0.25rem;899 margin-bottom: 0.5rem;900 }901 .color-swatch {902 width: 18px;903 height: 18px;904 border: 2px solid var(--border-primary);905 border-radius: 3px;906 cursor: pointer;907 transition: all 0.2s ease;908 position: relative;909 }910 .color-swatch:hover {911 transform: scale(1.1);912 border-color: var(--text-secondary);913 }914 .color-swatch.selected {915 border-color: var(--text-primary);916 box-shadow: 0 0 0 2px var(--text-link);917 }918 .color-swatch.selected::after {919 content: '✓';920 position: absolute;921 top: 50%;922 left: 50%;923 transform: translate(-50%, -50%);924 color: white;925 font-size: 10px;926 font-weight: bold;927 text-shadow: 1px 1px 1px black;928 }929 .color-input {930 width: 24px;931 height: 24px;932 border: 2px solid var(--border-primary);933 border-radius: 3px;934 cursor: pointer;935 background: none;936 padding: 0;937 grid-column: span 2;938 justify-self: center;939 }940 .color-input:hover {941 border-color: var(--text-secondary);942 }943 944 /* Thickness slider styles */945 .thickness-row {946 display: flex;947 align-items: center;948 gap: 0.5rem;949 margin-top: 0.75rem;950 }951 .thickness-slider {952 flex: 1;953 -webkit-appearance: none;954 appearance: none;955 height: 4px;956 background: var(--border-primary);957 border-radius: 2px;958 outline: none;959 opacity: 0.7;960 transition: opacity 0.2s;961 }962 .thickness-slider:hover {963 opacity: 1;964 }965 .thickness-slider::-webkit-slider-thumb {966 -webkit-appearance: none;967 appearance: none;968 width: 12px;969 height: 12px;970 background: var(--text-link);971 border-radius: 50%;972 cursor: pointer;973 }974 .thickness-slider::-moz-range-thumb {975 width: 12px;976 height: 12px;977 background: var(--text-link);978 border-radius: 50%;979 cursor: pointer;980 border: none;981 }982 .thickness-value {983 font-size: 0.7rem;984 color: var(--text-secondary);985 min-width: 20px;986 text-align: right;987 }988 989 .highlight {990 background: none !important;991 }992 993 /* Loading animations */994 .loading-spinner {995 display: inline-block;996 width: 16px;997 height: 16px;998 border: 2px solid var(--border-primary);999 border-radius: 50%;1000 border-top-color: var(--text-link);1001 animation: spin 1s linear infinite;1002 margin-right: 8px;1003 vertical-align: middle;1004 }1005 1006 @keyframes spin {1007 to { transform: rotate(360deg); }1008 }1009 1010 .loading-skeleton {1011 display: inline-block;1012 background: var(--bg-tertiary);1013 background: linear-gradient(1014 90deg,1015 var(--bg-tertiary) 25%,1016 var(--bg-secondary) 50%,1017 var(--bg-tertiary) 75%1018 );1019 background-size: 200% 100%;1020 animation: loading-shimmer 2s ease-in-out infinite;1021 border-radius: 2px;1022 height: 1em;1023 width: 80px;1024 vertical-align: middle;1025 }1026 1027 @keyframes loading-shimmer {1028 0% { background-position: -200% 0; }1029 100% { background-position: 200% 0; }1030 }1031 1032 /* Loading state for cell output */1033 .cell-output:has(.loading-spinner) {1034 opacity: 0.7;1035 background: var(--bg-secondary);1036 border-left: 3px solid var(--text-link);1037 }1038 </style>1039 <script>1040 // --- Drag utilities ---1041 function clamp(val, min, max) { return Math.max(min, Math.min(max, val)); }1042 1043 function restorePosition(el, storageKey) {1044 try {1045 const raw = localStorage.getItem(storageKey);1046 if (!raw) return;1047 const pos = JSON.parse(raw);1048 if (typeof pos.left === 'number' && typeof pos.top === 'number') {1049 el.style.left = pos.left + 'px';1050 el.style.top = pos.top + 'px';1051 el.style.right = 'auto';1052 el.style.bottom = 'auto';1053 }1054 } catch (_) {}1055 }1056 1057 function savePosition(el, storageKey) {1058 try {1059 const left = parseFloat(el.style.left || 'NaN');1060 const top = parseFloat(el.style.top || 'NaN');1061 if (!Number.isNaN(left) && !Number.isNaN(top)) {1062 localStorage.setItem(storageKey, JSON.stringify({ left, top }));1063 }1064 } catch (_) {}1065 }1066 1067 1068 function makeDraggable(el, storageKey, handleEl) {1069 let dragging = false;1070 let startX = 0, startY = 0; // cursor1071 let origLeft = 0, origTop = 0; // element1072 1073 const onMove = (e) => {1074 if (!dragging) return;1075 const clientX = e.touches ? e.touches[0].clientX : e.clientX;1076 const clientY = e.touches ? e.touches[0].clientY : e.clientY;1077 const dx = clientX - startX;1078 const dy = clientY - startY;1079 const w = el.offsetWidth;1080 const h = el.offsetHeight;1081 const maxX = window.innerWidth - w;1082 const maxY = window.innerHeight - h;1083 const newLeft = clamp(origLeft + dx, 0, maxX);1084 const newTop = clamp(origTop + dy, 0, maxY);1085 el.style.left = newLeft + 'px';1086 el.style.top = newTop + 'px';1087 el.style.right = 'auto';1088 el.style.bottom = 'auto';1089 };1090 1091 const endDrag = () => {1092 if (!dragging) return;1093 dragging = false;1094 document.removeEventListener('mousemove', onMove);1095 document.removeEventListener('mouseup', endDrag);1096 document.removeEventListener('touchmove', onMove);1097 document.removeEventListener('touchend', endDrag);1098 handleEl && (handleEl.style.cursor = 'grab');1099 savePosition(el, storageKey);1100 // ensure no-overlap constraint after a drag1101 try { layoutWidgetsStackedBottomRight(); } catch (_) {}1102 };1103 1104 const startDrag = (e) => {1105 // Start from element's current on-screen rect1106 const elRect = el.getBoundingClientRect();1107 el.style.left = elRect.left + 'px';1108 el.style.top = elRect.top + 'px';1109 el.style.right = 'auto';1110 el.style.bottom = 'auto';1111 1112 dragging = true;1113 startX = e.touches ? e.touches[0].clientX : e.clientX;1114 startY = e.touches ? e.touches[0].clientY : e.clientY;1115 origLeft = elRect.left;1116 origTop = elRect.top;1117 1118 document.addEventListener('mousemove', onMove);1119 document.addEventListener('mouseup', endDrag);1120 document.addEventListener('touchmove', onMove, { passive: false });1121 document.addEventListener('touchend', endDrag);1122 handleEl && (handleEl.style.cursor = 'grabbing');1123 e.preventDefault();1124 };1125 1126 (handleEl || el).addEventListener('mousedown', startDrag);1127 (handleEl || el).addEventListener('touchstart', startDrag, { passive: false });1128 1129 // Apply any saved position on init1130 restorePosition(el, storageKey);1131 }1132 function toggleCell(cellId) {1133 const codeElement = document.getElementById('code-' + cellId);1134 const outputElement = document.getElementById('output-' + cellId);1135 1136 if (codeElement) {1137 codeElement.classList.toggle('collapsed');1138 }1139 if (outputElement) {1140 outputElement.classList.toggle('collapsed');1141 }1142 1143 updateIndicators(cellId);1144 }1145 1146 function toggleCode(cellId) {1147 const codeElement = document.getElementById('code-' + cellId);1148 if (codeElement) {1149 codeElement.classList.toggle('collapsed');1150 updateIndicators(cellId);1151 }1152 }1153 1154 function toggleOutput(cellId) {1155 const outputElement = document.getElementById('output-' + cellId);1156 if (outputElement) {1157 outputElement.classList.toggle('collapsed');1158 updateIndicators(cellId);1159 }1160 }1161 1162 function toggleUvLogs(headerElement) {1163 const contentElement = headerElement.nextElementSibling;1164 if (contentElement) {1165 const isCollapsed = contentElement.style.display === 'none';1166 contentElement.style.display = isCollapsed ? 'block' : 'none';1167 headerElement.textContent = isCollapsed ? '▼ UV Install Logs' : '▶ UV Install Logs';1168 1169 // Update the header indicator if it exists1170 const uvLogsDiv = headerElement.parentElement;1171 if (uvLogsDiv && uvLogsDiv.id && uvLogsDiv.id.startsWith('uv-logs-')) {1172 const cellId = uvLogsDiv.id.replace('uv-logs-', '');1173 const indicatorElement = document.getElementById('uv-indicator-' + cellId);1174 if (indicatorElement) {1175 indicatorElement.textContent = isCollapsed ? '▼ uv-logs' : '▶ uv-logs';1176 }1177 }1178 }1179 }1180 1181 function toggleUvLogsFromHeader(cellId) {1182 const uvLogsElement = document.getElementById('uv-logs-' + cellId);1183 const indicatorElement = document.getElementById('uv-indicator-' + cellId);1184 if (uvLogsElement) {1185 const headerElement = uvLogsElement.querySelector('.uv-logs-header');1186 const contentElement = uvLogsElement.querySelector('.uv-logs-content');1187 if (contentElement && headerElement) {1188 const isCollapsed = contentElement.style.display === 'none';1189 contentElement.style.display = isCollapsed ? 'block' : 'none';1190 headerElement.textContent = isCollapsed ? '▼ UV Install Logs' : '▶ UV Install Logs';1191 if (indicatorElement) {1192 indicatorElement.textContent = isCollapsed ? '▼ uv-logs' : '▶ uv-logs';1193 }1194 }1195 }1196 }1197 1198 function updateIndicators(cellId) {1199 const codeElement = document.getElementById('code-' + cellId);1200 const outputElement = document.getElementById('output-' + cellId);