NCT

A modern, Material You-inspire...
Log | Files | Refs | Activity | README | LICENSE

root / codenct-legacy.html

codenct-legacy.html (88057B)


      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>NCT Legacy Code View</title>
      7     <!-- Link to Cascadia Code font from CDN -->
      8     <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@xz/fonts@1/serve/cascadia-code.min.css">
      9     <style>
     10         /* Base styling for the entire page */
     11         body {
     12             background-color: black;
     13             margin: 0;
     14             padding: 20px;
     15             font-family: 'Cascadia Code', 'Fira Code', 'Roboto Mono', monospace;
     16             color: white;
     17             display: flex;
     18             flex-direction: column;
     19             align-items: center;
     20             min-height: 100vh;
     21         }
     22 
     23         /* --- CUSTOM SCROLLBAR --- */
     24         ::-webkit-scrollbar { width: 8px; height: 8px; }
     25         ::-webkit-scrollbar-track { background: #000; }
     26         ::-webkit-scrollbar-thumb { background: #333; border-radius: 4px; }
     27         ::-webkit-scrollbar-thumb:hover { background: #1abc9c; }
     28 
     29         h1 {
     30             color: #f0f0f0;
     31             text-align: center;
     32             margin-bottom: 20px;
     33         }
     34 
     35         /* Container for the tabs */
     36         .tab-container {
     37             background-color: #1a1a1a;
     38             color: #f0f0f0;
     39             padding: 15px;
     40             border-radius: 8px;
     41             width: 100%;
     42             max-width: 1000px;
     43             box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
     44             position: relative;
     45             overflow: hidden;
     46             border: 1px solid #333;
     47         }
     48 
     49         /* Tab buttons styling */
     50         .tabs {
     51             display: flex;
     52             justify-content: center;
     53             margin-bottom: 20px;
     54             border-bottom: 1px solid #333;
     55         }
     56 
     57         .tab-button {
     58             background-color: transparent;
     59             border: none;
     60             padding: 10px 20px;
     61             font-size: 1.2em;
     62             color: #f0f0f0;
     63             cursor: pointer;
     64             transition: color 0.3s ease, background-color 0.3s ease, transform 0.3s ease;
     65             position: relative;
     66             overflow: hidden;
     67             border-radius: 5px 5px 0 0;
     68             margin: 0 5px;
     69         }
     70 
     71         .tab-button:hover {
     72             color: #1abc9c;
     73             transform: translateY(-2px);
     74         }
     75 
     76         .tab-button.active {
     77             color: #1abc9c;
     78             font-weight: bold;
     79             background-color: #333;
     80             transform: translateY(-2px);
     81         }
     82 
     83         .tab-button.active::after {
     84             content: '';
     85             position: absolute;
     86             bottom: 0;
     87             left: 0;
     88             width: 100%;
     89             height: 3px;
     90             background-color: #1abc9c;
     91             animation: tabUnderline 0.3s forwards;
     92         }
     93 
     94         @keyframes tabUnderline {
     95             from { width: 0; }
     96             to { width: 100%; }
     97         }
     98 
     99         /* Tab content styling */
    100         .tab-content {
    101             display: none;
    102             padding: 15px 0;
    103             animation: fadeIn 0.5s ease-in-out;
    104         }
    105 
    106         .tab-content.active {
    107             display: block;
    108         }
    109 
    110         @keyframes fadeIn {
    111             from { opacity: 0; transform: translateY(10px); }
    112             to { opacity: 1; transform: translateY(0); }
    113         }
    114 
    115         /* Header for Code Block */
    116         .code-header {
    117             display: flex;
    118             justify-content: space-between;
    119             align-items: center;
    120             background-color: #252525;
    121             padding: 8px 15px;
    122             border-radius: 8px 8px 0 0;
    123             border: 1px solid #333;
    124             border-bottom: none;
    125         }
    126 
    127         .file-info { font-size: 0.85em; color: #888; }
    128 
    129         /* Copy Button Styling */
    130         .copy-button {
    131             background: transparent;
    132             border: 1px solid #444;
    133             color: #ccc;
    134             padding: 5px 12px;
    135             border-radius: 4px;
    136             font-size: 0.8em;
    137             cursor: pointer;
    138             transition: 0.2s;
    139             display: flex;
    140             align-items: center;
    141             gap: 6px;
    142         }
    143 
    144         .copy-button:hover {
    145             border-color: #1abc9c;
    146             color: #1abc9c;
    147         }
    148 
    149         .copy-button.success {
    150             border-color: #2ecc71;
    151             color: #2ecc71;
    152         }
    153 
    154         /* Styling for the code block container */
    155         .code-block-container {
    156             background-color: #1a1a1a;
    157             border: 1px solid #333;
    158             border-radius: 0 0 8px 8px;
    159             overflow: hidden;
    160         }
    161 
    162         .code-block {
    163             background-color: #1a1a1a;
    164             color: #f0f0f0;
    165             padding: 15px;
    166             overflow-x: auto;
    167             max-height: 70vh;
    168             font-size: 0.95em;
    169             line-height: 1.5;
    170             tab-size: 4;
    171             white-space: pre;
    172             margin: 0;
    173         }
    174 
    175         /* Download section styling */
    176         .download-item {
    177             background-color: #2a2a2a;
    178             padding: 15px;
    179             border-radius: 8px;
    180             margin-bottom: 15px;
    181             display: flex;
    182             justify-content: space-between;
    183             align-items: center;
    184             border: 1px solid #333;
    185         }
    186 
    187         .download-info h3 {
    188             color: #1abc9c;
    189             margin: 0 0 5px 0;
    190         }
    191 
    192         .download-info p {
    193             font-size: 0.9em;
    194             color: #ccc;
    195             margin: 0;
    196         }
    197 
    198         .download-button {
    199             background-color: #007bff;
    200             color: white;
    201             border: none;
    202             padding: 10px 15px;
    203             border-radius: 5px;
    204             cursor: pointer;
    205             text-decoration: none;
    206             font-size: 0.9em;
    207             transition: background-color 0.3s ease, transform 0.2s ease;
    208         }
    209 
    210         .download-button:hover {
    211             background-color: #0056b3;
    212             transform: translateY(-1px);
    213         }
    214     </style>
    215 </head>
    216 <body>
    217 
    218     <h1>--- NCT Legacy Explorer ---</h1>
    219 
    220     <div class="tab-container">
    221         <div class="tabs">
    222             <button class="tab-button active" onclick="switchTab(event, 'code')">Code</button>
    223             <button class="tab-button" onclick="switchTab(event, 'download')">Download</button>
    224         </div>
    225 
    226         <div id="code-tab-content" class="tab-content active">
    227             <div class="code-header">
    228                 <span class="file-info">nct-legacy.html</span>
    229                 <button class="copy-button" onclick="copyToClipboard(this)">
    230                     <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>
    231                     Copy Code
    232                 </button>
    233             </div>
    234             <div class="code-block-container">
    235                 <pre id="sourceCode" class="code-block">&lt;!DOCTYPE html&gt;
    236 &lt;html lang=&quot;en&quot;&gt;
    237 &lt;head&gt;
    238     &lt;meta charset=&quot;UTF-8&quot;&gt;
    239     &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    240     &lt;title&gt;NCT v2.11 | Legacy Edition&lt;/title&gt;
    241     &lt;link rel=&quot;icon&quot; href=&quot;data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgdmlld0JveD0iMCAwIDI0IDI0Ij48c3R5bGU+cGF0aHtmaWxsOiNEMEJDRkZ9QG1lZGlhIChwcmVmZXJzLWNvbG9yLXNjaGVtZTpkYXJrKXtwYXRoe2ZpbGw6I2ZmZnx9fTwvc3R5bGU+PHBhdGggZD0iTTcgMnYxMWgzdjlsNy0xMmgtNGw0LTh6Ii8+PC9zdmc+&quot;&gt;
    242     &lt;link rel=&quot;preconnect&quot; href=&quot;https://fonts.googleapis.com&quot;&gt;
    243     &lt;link rel=&quot;preconnect&quot; href=&quot;https://fonts.gstatic.com&quot; crossorigin&gt;
    244     &lt;link href=&quot;https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&amp;family=Google+Sans:wght@400;500;700&amp;family=Roboto+Mono:wght@400;500&amp;display=swap&quot; rel=&quot;stylesheet&quot;&gt;
    245     &lt;script type=&quot;application/ld+json&quot;&gt;
    246   {
    247     &quot;@context&quot;: &quot;https://schema.org&quot;,
    248     &quot;@type&quot;: &quot;WebApplication&quot;,
    249     &quot;name&quot;: &quot;NCT v2.11 | Legacy Edition&quot;,
    250     &quot;url&quot;: &quot;https://amit.is-a.dev/nct-legacy&quot;,
    251     &quot;image&quot;: &quot;https://amit.is-a.dev/nctlogo.png&quot;,
    252     &quot;description&quot;: &quot;Number conversion tool&quot;,
    253     &quot;applicationCategory&quot;: &quot;EducationalApplication&quot;,
    254     &quot;operatingSystem&quot;: &quot;Any&quot;
    255   }
    256 &lt;/script&gt;
    257     &lt;style&gt;
    258         /* --- MATERIAL DESIGN 3 TOKENS --- */
    259         :root {
    260             --md-sys-color-background: #141218;
    261             --md-sys-color-surface: #1D1B20;
    262             --md-sys-color-surface-container: #211F26;
    263             --md-sys-color-surface-container-high: #2B2930;
    264             
    265             /* Primary */
    266             --md-sys-color-primary: #D0BCFF;
    267             --md-sys-color-on-primary: #381E72;
    268             --md-sys-color-primary-container: #4F378B;
    269             --md-sys-color-on-primary-container: #EADDFF;
    270 
    271             /* Text */
    272             --md-sys-color-on-surface: #E6E1E5;
    273             --md-sys-color-on-surface-variant: #CAC4D0;
    274             --md-sys-color-outline: #938F99;
    275 
    276             /* Error */
    277             --md-sys-color-error: #F2B8B5;
    278             --md-sys-color-error-container: #8C1D18;
    279 
    280             /* Success/Accent */
    281             --md-sys-color-tertiary: #B6C4FF;
    282             --md-sys-color-success: #4ade80;
    283             
    284             /* Dimensions */
    285             --radius-xl: 28px;
    286             --radius-l: 16px;
    287             --radius-m: 12px;
    288             --radius-s: 8px;
    289 
    290             --font-main: &#x27;Google Sans&#x27;, &#x27;Roboto&#x27;, sans-serif;
    291             --font-code: &#x27;Roboto Mono&#x27;, monospace;
    292             
    293             /* Animation */
    294             --ease-elastic: cubic-bezier(0.4, 0.0, 0.2, 1);
    295         }
    296 
    297         /* --- CUSTOM SCROLLBAR --- */
    298         ::-webkit-scrollbar { width: 6px; height: 6px; }
    299         ::-webkit-scrollbar-track { background: transparent; }
    300         ::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.2); border-radius: 3px; }
    301         ::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.4); }
    302 
    303         * { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
    304 
    305         body {
    306             font-family: var(--font-main);
    307             background-color: var(--md-sys-color-background);
    308             color: var(--md-sys-color-on-surface);
    309             min-height: 100vh;
    310             display: flex;
    311             flex-direction: column;
    312             align-items: center;
    313             overflow-x: hidden;
    314             background-image: radial-gradient(circle at 50% 0%, rgba(208, 188, 255, 0.05) 0%, transparent 60%);
    315         }
    316 
    317         /* --- LAYOUT --- */
    318         .app-container {
    319             width: 100%;
    320             max-width: 1000px;
    321             padding: 24px;
    322             display: flex;
    323             flex-direction: column;
    324             gap: 24px;
    325             flex-grow: 1;
    326         }
    327 
    328         /* --- HEADER &amp; NAV --- */
    329         header {
    330             display: flex;
    331             flex-direction: column;
    332             gap: 20px;
    333             padding: 16px 0;
    334         }
    335 
    336         .header-top {
    337             display: flex;
    338             justify-content: space-between;
    339             align-items: center;
    340         }
    341 
    342         .logo {
    343             font-size: 1.75rem;
    344             font-weight: 500;
    345             color: var(--md-sys-color-on-surface);
    346             display: flex;
    347             align-items: center;
    348             gap: 12px;
    349         }
    350 
    351         .logo span { color: var(--md-sys-color-primary); }
    352 
    353         /* Navigation Tabs with Animation */
    354         .nav-tabs {
    355             position: relative;
    356             display: flex;
    357             background: var(--md-sys-color-surface-container);
    358             padding: 4px;
    359             border-radius: 32px;
    360             width: fit-content;
    361             margin: 0 auto;
    362             border: 1px solid rgba(255,255,255,0.05);
    363         }
    364 
    365         .nav-glider {
    366             position: absolute;
    367             top: 4px;
    368             left: 4px;
    369             height: calc(100% - 8px);
    370             width: 110px; 
    371             background: var(--md-sys-color-primary-container);
    372             border-radius: 28px;
    373             transition: transform 0.3s var(--ease-elastic);
    374             z-index: 1;
    375         }
    376 
    377         .nav-tab {
    378             position: relative;
    379             padding: 10px 24px;
    380             border-radius: 24px;
    381             color: var(--md-sys-color-on-surface-variant);
    382             font-weight: 500;
    383             cursor: pointer;
    384             transition: color 0.2s;
    385             border: none;
    386             background: none;
    387             z-index: 2;
    388             width: 110px; 
    389         }
    390 
    391         .nav-tab.active { color: var(--md-sys-color-on-primary-container); }
    392 
    393         .header-actions {
    394             display: flex;
    395             gap: 10px;
    396         }
    397 
    398         .tools-btn {
    399             background: transparent;
    400             border: 1px solid var(--md-sys-color-outline);
    401             color: var(--md-sys-color-on-surface);
    402             padding: 8px 16px;
    403             border-radius: var(--radius-l);
    404             cursor: pointer;
    405             font-weight: 500;
    406             display: flex;
    407             align-items: center;
    408             gap: 8px;
    409             transition: transform 0.1s;
    410         }
    411         .tools-btn:active { transform: scale(0.95); }
    412         .tools-btn:hover { background: rgba(255,255,255,0.05); }
    413 
    414         /* --- SECTIONS --- */
    415         .app-section {
    416             display: none;
    417             flex-direction: column;
    418             gap: 24px;
    419             animation: fadeIn 0.3s ease-out;
    420         }
    421         .app-section.active { display: flex; }
    422         
    423         @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
    424 
    425         /* --- CONVERTER STAGE --- */
    426         .converter-stage {
    427             display: grid;
    428             grid-template-columns: 1fr 64px 1fr;
    429             gap: 16px;
    430             align-items: stretch;
    431             position: relative;
    432         }
    433 
    434         .material-card {
    435             background-color: var(--md-sys-color-surface-container);
    436             border-radius: var(--radius-xl);
    437             padding: 24px;
    438             display: flex;
    439             flex-direction: column;
    440             height: 380px;
    441             position: relative;
    442             transition: transform 0.4s var(--ease-elastic), box-shadow 0.2s;
    443             border: 1px solid transparent;
    444             z-index: 1;
    445         }
    446 
    447         .material-card:focus-within {
    448             background-color: var(--md-sys-color-surface-container-high);
    449             border-color: var(--md-sys-color-outline);
    450         }
    451 
    452         /* CARD HEADER &amp; CUSTOM DROPDOWN */
    453         .card-header {
    454             display: flex;
    455             justify-content: space-between;
    456             align-items: center;
    457             margin-bottom: 20px;
    458             border-bottom: 1px solid var(--md-sys-color-outline);
    459             padding-bottom: 12px;
    460             z-index: 10;
    461         }
    462 
    463         .input-label {
    464             font-size: 0.875rem;
    465             font-weight: 500;
    466             color: var(--md-sys-color-primary);
    467             text-transform: uppercase;
    468             letter-spacing: 1px;
    469         }
    470 
    471         /* Custom Dropdown Styles */
    472         .custom-select-wrapper {
    473             position: relative;
    474             min-width: 150px;
    475             user-select: none;
    476         }
    477         .custom-select-trigger {
    478             display: flex;
    479             align-items: center;
    480             justify-content: flex-end;
    481             gap: 8px;
    482             cursor: pointer;
    483             color: var(--md-sys-color-on-surface);
    484             font-weight: 500;
    485             padding: 4px 0;
    486             transition: color 0.2s;
    487         }
    488         .custom-select-trigger:hover { color: var(--md-sys-color-primary); }
    489         .arrow { font-size: 0.7rem; transition: transform 0.3s; }
    490         
    491         .custom-options {
    492             position: absolute;
    493             top: 120%;
    494             right: 0;
    495             background: var(--md-sys-color-surface-container-high);
    496             border-radius: var(--radius-m);
    497             box-shadow: 0 8px 16px rgba(0,0,0,0.4);
    498             opacity: 0;
    499             visibility: hidden;
    500             pointer-events: none;
    501             transform: translateY(-10px);
    502             transition: all 0.2s var(--ease-elastic);
    503             min-width: 180px;
    504             overflow: hidden;
    505             border: 1px solid rgba(255,255,255,0.1);
    506             z-index: 1000;
    507         }
    508         .custom-select-wrapper.open .custom-options {
    509             opacity: 1; visibility: visible; pointer-events: all; transform: translateY(0);
    510         }
    511         .custom-select-wrapper.open .arrow { transform: rotate(180deg); }
    512         
    513         .custom-option {
    514             padding: 12px 16px;
    515             cursor: pointer;
    516             color: var(--md-sys-color-on-surface-variant);
    517             transition: 0.2s;
    518         }
    519         .custom-option:hover { background: rgba(255,255,255,0.05); color: var(--md-sys-color-on-surface); }
    520         .custom-option.selected { color: var(--md-sys-color-primary); background: rgba(208, 188, 255, 0.1); }
    521 
    522         /* INPUT AREA */
    523         .input-area {
    524             flex-grow: 1;
    525             background: transparent;
    526             border: none;
    527             color: var(--md-sys-color-on-surface);
    528             font-size: 2.2rem;
    529             font-family: var(--font-main);
    530             resize: none;
    531             outline: none;
    532             line-height: 1.2;
    533             z-index: 1;
    534         }
    535         .input-area::placeholder { color: var(--md-sys-color-on-surface-variant); opacity: 0.3; }
    536 
    537         /* Error Chip */
    538         .error-chip {
    539             position: absolute;
    540             bottom: 80px;
    541             left: 24px;
    542             background: var(--md-sys-color-error-container);
    543             color: var(--md-sys-color-error);
    544             padding: 8px 16px;
    545             border-radius: 8px;
    546             font-size: 0.875rem;
    547             display: flex;
    548             align-items: center;
    549             gap: 8px;
    550             opacity: 0;
    551             transform: translateY(10px);
    552             transition: all 0.3s;
    553             pointer-events: none;
    554         }
    555         .error-chip.visible { opacity: 1; transform: translateY(0); }
    556 
    557         /* Card Footer */
    558         .card-footer {
    559             display: flex;
    560             justify-content: space-between;
    561             align-items: center;
    562             margin-top: auto;
    563         }
    564         .char-count { font-size: 0.75rem; color: var(--md-sys-color-on-surface-variant); }
    565 
    566         /* Icons &amp; Buttons */
    567         .icon-btn {
    568             background: transparent;
    569             border: none;
    570             color: var(--md-sys-color-on-surface-variant);
    571             width: 40px; height: 40px;
    572             border-radius: 50%;
    573             cursor: pointer;
    574             display: flex; align-items: center; justify-content: center;
    575             transition: 0.2s;
    576         }
    577         .icon-btn:hover { background: rgba(255,255,255,0.1); color: var(--md-sys-color-on-surface); transform: scale(1.1); }
    578         .icon-btn:active { transform: scale(0.9); }
    579         
    580         /* Copy Button Animation */
    581         .icon-btn.success svg {
    582             animation: check-pop 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
    583             color: var(--md-sys-color-success);
    584         }
    585         @keyframes check-pop {
    586             0% { transform: scale(0); }
    587             50% { transform: scale(1.3); }
    588             100% { transform: scale(1); }
    589         }
    590 
    591         /* Trash Shake Animation */
    592         @keyframes trash-shake {
    593             0% { transform: rotate(0deg); }
    594             25% { transform: rotate(-15deg); }
    595             50% { transform: rotate(15deg); }
    596             75% { transform: rotate(-15deg); }
    597             100% { transform: rotate(0deg); }
    598         }
    599         .icon-btn.shaking {
    600             animation: trash-shake 0.4s ease-in-out;
    601             color: var(--md-sys-color-error);
    602         }
    603 
    604         /* Swap Button */
    605         .swap-container { display: flex; justify-content: center; align-items: center; z-index: 2; }
    606         .swap-fab {
    607             width: 56px; height: 56px;
    608             border-radius: 16px;
    609             background-color: var(--md-sys-color-surface-container-high);
    610             border: 1px solid var(--md-sys-color-outline);
    611             color: var(--md-sys-color-on-surface);
    612             cursor: pointer;
    613             display: flex; align-items: center; justify-content: center;
    614             transition: all 0.3s var(--ease-elastic);
    615             box-shadow: 0 4px 8px rgba(0,0,0,0.2);
    616         }
    617         .swap-fab:hover {
    618             background-color: var(--md-sys-color-primary);
    619             color: var(--md-sys-color-on-primary);
    620             transform: rotate(180deg) scale(1.1);
    621             border-color: transparent;
    622         }
    623 
    624         /* --- SWAP ANIMATION CLASSES --- */
    625         .anim-move-right { transform: translateX(calc(100% + 16px)); }
    626         .anim-move-left { transform: translateX(calc(-100% - 16px)); }
    627         .anim-move-down { transform: translateY(calc(100% + 16px)); }
    628         .anim-move-up { transform: translateY(calc(-100% - 16px)); }
    629 
    630         /* --- DYNAMIC CALCULATOR --- */
    631         .calc-wrapper {
    632             background: var(--md-sys-color-surface-container);
    633             padding: 24px;
    634             border-radius: var(--radius-xl);
    635             max-width: 800px;
    636             margin: 0 auto;
    637             width: 100%;
    638         }
    639 
    640         .calc-header {
    641             display: flex;
    642             gap: 24px;
    643             margin-bottom: 24px;
    644             flex-wrap: wrap;
    645         }
    646 
    647         .calc-ctrl-group {
    648             flex: 1;
    649             min-width: 200px;
    650             display: flex;
    651             align-items: center;
    652             gap: 12px;
    653             background: rgba(0,0,0,0.2);
    654             padding: 8px 16px;
    655             border-radius: 12px;
    656         }
    657         .calc-ctrl-group label {
    658             font-size: 0.8rem;
    659             color: var(--md-sys-color-primary);
    660             text-transform: uppercase;
    661             white-space: nowrap;
    662             margin: 0;
    663         }
    664         
    665         .calc-rows {
    666             display: flex;
    667             flex-direction: column;
    668             gap: 12px;
    669             margin-bottom: 24px;
    670         }
    671 
    672         .calc-row {
    673             display: flex;
    674             gap: 12px;
    675             align-items: center;
    676             animation: fadeIn 0.3s ease-out;
    677         }
    678         
    679         /* Simple Fade Out */
    680         .calc-row.removing {
    681             opacity: 0;
    682             transition: opacity 0.3s ease;
    683         }
    684         
    685         .calc-input-wrapper {
    686             flex-grow: 1;
    687             position: relative;
    688         }
    689         .calc-input {
    690             width: 100%;
    691             background: rgba(0,0,0,0.2);
    692             border: 1px solid transparent;
    693             color: var(--md-sys-color-on-surface);
    694             padding: 16px;
    695             border-radius: 12px;
    696             font-family: var(--font-code);
    697             font-size: 1.1rem;
    698             outline: none;
    699             transition: 0.2s;
    700         }
    701         .calc-input:focus { border-color: var(--md-sys-color-primary); background: rgba(0,0,0,0.4); }
    702         .calc-input.invalid { border-color: var(--md-sys-color-error); }
    703         
    704         .calc-remove-btn {
    705             background: var(--md-sys-color-surface-container-high);
    706             border: none;
    707             color: var(--md-sys-color-error);
    708             width: 40px; height: 40px;
    709             border-radius: 8px;
    710             cursor: pointer;
    711             display: flex; align-items: center; justify-content: center;
    712             transition: 0.2s;
    713         }
    714         .calc-remove-btn:hover { background: var(--md-sys-color-error-container); color: #fff; }
    715 
    716         /* The Divider Area */
    717         .calc-actions {
    718             display: flex;
    719             align-items: center;
    720             border-top: 1px solid var(--md-sys-color-outline);
    721             padding-top: 20px;
    722             margin-top: 20px;
    723         }
    724 
    725         .add-row-btn {
    726             background: rgba(255,255,255,0.05);
    727             border: 1px dashed var(--md-sys-color-outline);
    728             color: var(--md-sys-color-on-surface-variant);
    729             padding: 10px 20px;
    730             border-radius: 12px;
    731             cursor: pointer;
    732             font-weight: 500;
    733             width: fit-content;
    734             text-align: left;
    735             transition: 0.2s;
    736             margin-bottom: 20px; /* Space before divider */
    737         }
    738         .add-row-btn:hover { border-color: var(--md-sys-color-primary); color: var(--md-sys-color-primary); background: rgba(208, 188, 255, 0.05); }
    739 
    740         .calc-result-area {
    741             display: flex;
    742             align-items: center;
    743             gap: 20px;
    744             margin-left: auto; /* Forces result to the right */
    745         }
    746 
    747         .visualize-btn {
    748             background: var(--md-sys-color-primary-container);
    749             color: var(--md-sys-color-on-primary-container);
    750             border: none;
    751             padding: 8px 16px;
    752             border-radius: 20px;
    753             font-size: 0.9rem;
    754             font-weight: 500;
    755             cursor: pointer;
    756             display: none; /* Hidden by default */
    757             align-items: center;
    758             gap: 6px;
    759             transition: 0.2s;
    760             animation: popIn 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
    761             margin-right: auto; /* Keeps it left-aligned in actions */
    762         }
    763         .visualize-btn:hover { filter: brightness(1.2); }
    764         .visualize-btn:active { transform: scale(0.95); }
    765         @keyframes popIn { from{transform: scale(0.8); opacity:0} to{transform: scale(1); opacity:1} }
    766 
    767         .calc-result-display { text-align: right; }
    768         .res-label { font-size: 0.9rem; color: var(--md-sys-color-on-surface-variant); }
    769         .res-value { font-size: 2.2rem; color: var(--md-sys-color-primary); font-family: var(--font-code); margin-top: 5px; font-weight: 700; }
    770 
    771 
    772         /* --- VISUALIZER PANEL --- */
    773         .calc-visualizer {
    774             background: #111;
    775             border-radius: var(--radius-m);
    776             padding: 20px;
    777             margin-top: 20px;
    778             display: none; 
    779             border: 1px solid var(--md-sys-color-outline);
    780             overflow-x: auto;
    781         }
    782         .calc-visualizer.active { display: block; animation: slideIn 0.4s var(--ease-elastic); }
    783         
    784         .viz-grid {
    785             display: grid;
    786             font-family: var(--font-code);
    787             font-size: 1.2rem;
    788             color: var(--md-sys-color-on-surface);
    789             gap: 4px;
    790         }
    791         .viz-row { display: contents; }
    792         .viz-cell {
    793             padding: 4px 8px;
    794             text-align: center;
    795             position: relative;
    796         }
    797         .viz-cell.carry { color: var(--md-sys-color-tertiary); font-size: 0.8rem; height: 20px; }
    798         .viz-cell.operator { color: var(--md-sys-color-primary); }
    799         .viz-cell.border-bottom { border-bottom: 2px solid var(--md-sys-color-outline); }
    800         .viz-cell.active-col { background: rgba(208, 188, 255, 0.15); border-radius: 4px; }
    801         .viz-cell.result { color: var(--md-sys-color-primary); font-weight: bold; }
    802 
    803         .viz-info {
    804             margin-top: 12px;
    805             font-size: 0.9rem;
    806             color: var(--md-sys-color-on-surface-variant);
    807             font-family: var(--font-code);
    808             min-height: 20px;
    809         }
    810 
    811         /* --- CONVERTER STEPS PANEL --- */
    812         .steps-container {
    813             margin-top: 20px;
    814             background: rgba(0,0,0,0.2);
    815             border-radius: var(--radius-l);
    816             padding: 20px;
    817             border: 1px solid rgba(255,255,255,0.05);
    818             display: none;
    819         }
    820         .steps-container.visible { display: block; animation: fadeIn 0.5s; }
    821         
    822         .steps-header {
    823             display: flex;
    824             justify-content: space-between;
    825             align-items: center;
    826             margin-bottom: 12px;
    827             border-bottom: 1px solid rgba(255,255,255,0.1);
    828             padding-bottom: 8px;
    829         }
    830         
    831         .steps-content {
    832             font-family: var(--font-code);
    833             color: var(--md-sys-color-tertiary);
    834             font-size: 0.9rem;
    835             white-space: pre-wrap;
    836             line-height: 1.5;
    837         }
    838 
    839         /* --- HISTORY TAPE --- */
    840         .history-section {
    841             margin-top: 20px;
    842             border-top: 1px solid var(--md-sys-color-outline);
    843             padding-top: 20px;
    844         }
    845         .history-header {
    846             display: flex;
    847             justify-content: space-between;
    848             align-items: center;
    849             margin-bottom: 10px;
    850         }
    851         .history-list {
    852             display: flex; flex-direction: column; gap: 8px;
    853             max-height: 200px; overflow-y: auto;
    854             transition: opacity 0.3s;
    855         }
    856         
    857         /* History Item Animation: Slide Out to Right */
    858         .history-list.clearing .history-item {
    859             animation: slide-out-right 0.3s forwards;
    860         }
    861         @keyframes slide-out-right {
    862             to { transform: translateX(50px); opacity: 0; }
    863         }
    864 
    865         .history-item {
    866             display: flex; justify-content: space-between;
    867             padding: 12px;
    868             background: rgba(255,255,255,0.03);
    869             border-radius: 8px;
    870             font-family: var(--font-code);
    871             font-size: 0.9rem;
    872             cursor: pointer;
    873             transition: 0.2s;
    874             align-items: center;
    875         }
    876         .history-item:hover { background: rgba(255,255,255,0.08); transform: translateX(4px); }
    877         .hist-val { color: var(--md-sys-color-on-surface); }
    878         .hist-meta { font-size: 0.75rem; color: var(--md-sys-color-outline); margin-right: 10px; }
    879 
    880         /* --- FOOTER --- */
    881         footer {
    882             margin-top: 40px;
    883             text-align: center;
    884             padding: 20px;
    885             color: var(--md-sys-color-on-surface-variant);
    886             font-size: 0.85rem;
    887             border-top: 1px solid var(--md-sys-color-outline);
    888             width: 100%;
    889             background: rgba(0,0,0,0.2);
    890         }
    891         .footer-content {
    892             display: flex;
    893             flex-direction: column;
    894             gap: 8px;
    895         }
    896         .footer-links {
    897             display: flex;
    898             justify-content: center;
    899             gap: 15px;
    900             margin-top: 5px;
    901         }
    902         .footer-link {
    903             color: var(--md-sys-color-primary);
    904             text-decoration: none;
    905             transition: 0.2s;
    906         }
    907         .footer-link:hover { text-decoration: underline; color: var(--md-sys-color-tertiary); }
    908 
    909         /* --- MODAL (LEGACY &amp; CHEATSHEET) --- */
    910         .modal-overlay {
    911             position: fixed;
    912             top: 0; left: 0; width: 100%; height: 100%;
    913             background: rgba(0,0,0,0.7);
    914             backdrop-filter: blur(4px);
    915             z-index: 2000;
    916             display: none;
    917             justify-content: center;
    918             align-items: center;
    919             opacity: 0;
    920             transition: opacity 0.3s;
    921         }
    922         .modal-overlay.open { display: flex; opacity: 1; }
    923         
    924         .modal-content {
    925             background: var(--md-sys-color-surface-container);
    926             width: 90%; max-width: 500px;
    927             border-radius: var(--radius-xl);
    928             padding: 24px;
    929             max-height: 80vh;
    930             display: flex;
    931             flex-direction: column;
    932             box-shadow: 0 10px 30px rgba(0,0,0,0.5);
    933             border: 1px solid var(--md-sys-color-outline);
    934             transform: scale(0.9);
    935             transition: transform 0.3s var(--ease-elastic);
    936         }
    937         .modal-overlay.open .modal-content { transform: scale(1); }
    938 
    939         .modal-header {
    940             display: flex; justify-content: space-between; align-items: center;
    941             margin-bottom: 20px;
    942             border-bottom: 1px solid var(--md-sys-color-outline);
    943             padding-bottom: 12px;
    944             flex-shrink: 0;
    945         }
    946         .modal-header h3 { margin: 0; color: var(--md-sys-color-primary); }
    947         .close-modal {
    948             background: none; border: none; color: var(--md-sys-color-on-surface);
    949             font-size: 1.5rem; cursor: pointer;
    950         }
    951         
    952         .modal-body {
    953             overflow-y: auto;
    954             padding-right: 5px; /* Space for scrollbar */
    955         }
    956 
    957         /* History Timeline */
    958         .timeline-item {
    959             position: relative;
    960             padding-left: 20px;
    961             border-left: 2px solid var(--md-sys-color-outline);
    962             margin-bottom: 20px;
    963         }
    964         .timeline-item::before {
    965             content: &#x27;&#x27;; position: absolute; left: -6px; top: 0;
    966             width: 10px; height: 10px; border-radius: 50%;
    967             background: var(--md-sys-color-primary);
    968         }
    969         .version-tag {
    970             font-size: 0.8rem; font-weight: bold; color: var(--md-sys-color-tertiary);
    971             margin-bottom: 4px; display: inline-block; background: rgba(255,255,255,0.1);
    972             padding: 2px 8px; border-radius: 4px;
    973         }
    974         .version-tag.current { background: var(--md-sys-color-primary); color: var(--md-sys-color-on-primary); }
    975         .timeline-desc { font-size: 0.9rem; color: var(--md-sys-color-on-surface-variant); margin: 0; }
    976 
    977         /* Sidebar (Cheat Sheet) */
    978         .sidebar {
    979             position: fixed; top: 0; right: -320px;
    980             width: 300px; height: 100%;
    981             background: var(--md-sys-color-surface-container-high);
    982             box-shadow: -5px 0 15px rgba(0,0,0,0.5);
    983             padding: 24px;
    984             transition: 0.3s ease;
    985             z-index: 1000;
    986             overflow-y: auto;
    987         }
    988         .sidebar.open { right: 0; }
    989         .sidebar h3 { color: var(--md-sys-color-primary); margin-bottom: 16px; border-bottom: 1px solid rgba(255,255,255,0.1); padding-bottom: 8px; }
    990         .cheat-table { width: 100%; border-collapse: collapse; font-family: var(--font-code); font-size: 0.8rem; }
    991         .cheat-table th, .cheat-table td { text-align: left; padding: 6px; border-bottom: 1px solid rgba(255,255,255,0.05); }
    992         .close-sidebar {
    993             position: absolute; top: 10px; right: 10px;
    994             background: none; border: none; color: var(--md-sys-color-on-surface);
    995             font-size: 1.5rem; cursor: pointer;
    996         }
    997 
    998         /* --- RESPONSIVE --- */
    999         @media (max-width: 768px) {
   1000             .converter-stage { grid-template-columns: 1fr; grid-template-rows: 1fr 64px 1fr; gap: 8px; }
   1001             .material-card { height: 260px; }
   1002             .swap-container { transform: rotate(90deg); }
   1003             .swap-fab:hover { transform: rotate(180deg); }
   1004             .header-top { flex-direction: column; gap: 10px; }
   1005             .calc-header { flex-direction: column; gap: 10px; }
   1006             .calc-result-area { margin-left: 0; justify-content: flex-end; width: 100%; }
   1007             .visualize-btn { margin-right: 0; margin-bottom: 10px; }
   1008             .calc-actions { flex-direction: column-reverse; align-items: stretch; }
   1009         }
   1010     &lt;/style&gt;
   1011 &lt;/head&gt;
   1012 &lt;body&gt;
   1013 
   1014     &lt;header class=&quot;app-container&quot;&gt;
   1015         &lt;div class=&quot;header-top&quot;&gt;
   1016             &lt;div class=&quot;logo&quot;&gt;
   1017                 &lt;svg width=&quot;32&quot; height=&quot;32&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;var(--md-sys-color-primary)&quot;&gt;&lt;path d=&quot;M7 2v11h3v9l7-12h-4l4-8z&quot;/&gt;&lt;/svg&gt;
   1018                 NCT &lt;span&gt;v2.11&lt;/span&gt;
   1019             &lt;/div&gt;
   1020             
   1021             &lt;!-- Animated Navigation --&gt;
   1022             &lt;div class=&quot;nav-tabs&quot;&gt;
   1023                 &lt;div class=&quot;nav-glider&quot; id=&quot;navGlider&quot;&gt;&lt;/div&gt;
   1024                 &lt;button class=&quot;nav-tab active&quot; onclick=&quot;switchTab(&#x27;converter&#x27;, 0)&quot;&gt;Converter&lt;/button&gt;
   1025                 &lt;button class=&quot;nav-tab&quot; onclick=&quot;switchTab(&#x27;calculator&#x27;, 1)&quot;&gt;Calculator&lt;/button&gt;
   1026             &lt;/div&gt;
   1027 
   1028             &lt;div class=&quot;header-actions&quot;&gt;
   1029                 &lt;button class=&quot;tools-btn&quot; onclick=&quot;toggleHistory()&quot;&gt;
   1030                     &lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z&quot;/&gt;&lt;/svg&gt;
   1031                     Versions
   1032                 &lt;/button&gt;
   1033                 &lt;button class=&quot;tools-btn&quot; onclick=&quot;toggleSidebar()&quot;&gt;
   1034                     &lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M11 18h2v-2h-2v2zm1-16C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm0-14c-2.21 0-4 1.79-4 4h2c0-1.1.9-2 2-2s2 .9 2 2c0 2-3 1.75-3 5h2c0-2.25 3-2.5 3-5 0-2.21-1.79-4-4-4z&quot;/&gt;&lt;/svg&gt;
   1035                     Cheat Sheet
   1036                 &lt;/button&gt;
   1037             &lt;/div&gt;
   1038         &lt;/div&gt;
   1039     &lt;/header&gt;
   1040 
   1041     &lt;main class=&quot;app-container&quot;&gt;
   1042         
   1043         &lt;!-- SECTION 1: CONVERTER --&gt;
   1044         &lt;section id=&quot;converter-section&quot; class=&quot;app-section active&quot;&gt;
   1045             
   1046             &lt;div class=&quot;converter-stage&quot;&gt;
   1047                 &lt;!-- SOURCE CARD --&gt;
   1048                 &lt;div class=&quot;material-card&quot; id=&quot;cardSource&quot;&gt;
   1049                     &lt;div class=&quot;card-header&quot;&gt;
   1050                         &lt;span class=&quot;input-label&quot;&gt;Input&lt;/span&gt;
   1051                         &lt;div class=&quot;custom-select-wrapper&quot; id=&quot;sourceSelectWrapper&quot;&gt;
   1052                             &lt;div class=&quot;custom-select-trigger&quot;&gt;
   1053                                 &lt;span class=&quot;selection-text&quot;&gt;Decimal&lt;/span&gt;
   1054                                 &lt;span class=&quot;arrow&quot;&gt;▼&lt;/span&gt;
   1055                             &lt;/div&gt;
   1056                             &lt;div class=&quot;custom-options&quot;&gt;
   1057                                 &lt;div class=&quot;custom-option&quot; data-value=&quot;2&quot;&gt;Binary&lt;/div&gt;
   1058                                 &lt;div class=&quot;custom-option&quot; data-value=&quot;8&quot;&gt;Octal&lt;/div&gt;
   1059                                 &lt;div class=&quot;custom-option selected&quot; data-value=&quot;10&quot;&gt;Decimal&lt;/div&gt;
   1060                                 &lt;div class=&quot;custom-option&quot; data-value=&quot;16&quot;&gt;Hexadecimal&lt;/div&gt;
   1061                             &lt;/div&gt;
   1062                             &lt;select id=&quot;fromBase&quot; style=&quot;display:none&quot;&gt;
   1063                                 &lt;option value=&quot;2&quot;&gt;Binary&lt;/option&gt;
   1064                                 &lt;option value=&quot;8&quot;&gt;Octal&lt;/option&gt;
   1065                                 &lt;option value=&quot;10&quot; selected&gt;Decimal&lt;/option&gt;
   1066                                 &lt;option value=&quot;16&quot;&gt;Hexadecimal&lt;/option&gt;
   1067                             &lt;/select&gt;
   1068                         &lt;/div&gt;
   1069                     &lt;/div&gt;
   1070                     
   1071                     &lt;textarea id=&quot;inputVal&quot; class=&quot;input-area&quot; placeholder=&quot;0&quot; spellcheck=&quot;false&quot;&gt;&lt;/textarea&gt;
   1072                     &lt;div id=&quot;errorChip&quot; class=&quot;error-chip&quot;&gt;⚠️ Invalid character for this base&lt;/div&gt;
   1073                     
   1074                     &lt;div class=&quot;card-footer&quot;&gt;
   1075                         &lt;div class=&quot;char-count&quot; id=&quot;sourceCount&quot;&gt;0 chars&lt;/div&gt;
   1076                         &lt;div class=&quot;icon-actions&quot;&gt;
   1077                             &lt;button class=&quot;icon-btn&quot; onclick=&quot;clearAll()&quot; title=&quot;Clear&quot;&gt;
   1078                                 &lt;svg width=&quot;20&quot; height=&quot;20&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z&quot;/&gt;&lt;/svg&gt;
   1079                             &lt;/button&gt;
   1080                         &lt;/div&gt;
   1081                     &lt;/div&gt;
   1082                 &lt;/div&gt;
   1083 
   1084                 &lt;!-- SWAP --&gt;
   1085                 &lt;div class=&quot;swap-container&quot;&gt;
   1086                     &lt;button class=&quot;swap-fab&quot; id=&quot;swapBtn&quot; title=&quot;Swap (Alt+S)&quot;&gt;
   1087                         &lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M6.99 11L3 15l3.99 4v-3H14v-2H6.99v-3zM21 9l-3.99-4v3H10v2h7.01v3L21 9z&quot;/&gt;&lt;/svg&gt;
   1088                     &lt;/button&gt;
   1089                 &lt;/div&gt;
   1090 
   1091                 &lt;!-- TARGET CARD --&gt;
   1092                 &lt;div class=&quot;material-card&quot; id=&quot;cardTarget&quot;&gt;
   1093                     &lt;div class=&quot;card-header&quot;&gt;
   1094                         &lt;span class=&quot;input-label&quot;&gt;Result&lt;/span&gt;
   1095                         &lt;div class=&quot;custom-select-wrapper&quot; id=&quot;targetSelectWrapper&quot;&gt;
   1096                             &lt;div class=&quot;custom-select-trigger&quot;&gt;
   1097                                 &lt;span class=&quot;selection-text&quot;&gt;Binary&lt;/span&gt;
   1098                                 &lt;span class=&quot;arrow&quot;&gt;▼&lt;/span&gt;
   1099                             &lt;/div&gt;
   1100                             &lt;div class=&quot;custom-options&quot;&gt;
   1101                                 &lt;div class=&quot;custom-option selected&quot; data-value=&quot;2&quot;&gt;Binary&lt;/div&gt;
   1102                                 &lt;div class=&quot;custom-option&quot; data-value=&quot;8&quot;&gt;Octal&lt;/div&gt;
   1103                                 &lt;div class=&quot;custom-option&quot; data-value=&quot;10&quot;&gt;Decimal&lt;/div&gt;
   1104                                 &lt;div class=&quot;custom-option&quot; data-value=&quot;16&quot;&gt;Hexadecimal&lt;/div&gt;
   1105                             &lt;/div&gt;
   1106                             &lt;select id=&quot;toBase&quot; style=&quot;display:none&quot;&gt;
   1107                                 &lt;option value=&quot;2&quot; selected&gt;Binary&lt;/option&gt;
   1108                                 &lt;option value=&quot;8&quot;&gt;Octal&lt;/option&gt;
   1109                                 &lt;option value=&quot;10&quot;&gt;Decimal&lt;/option&gt;
   1110                                 &lt;option value=&quot;16&quot;&gt;Hexadecimal&lt;/option&gt;
   1111                             &lt;/select&gt;
   1112                         &lt;/div&gt;
   1113                     &lt;/div&gt;
   1114                     
   1115                     &lt;textarea id=&quot;outputVal&quot; class=&quot;input-area&quot; readonly placeholder=&quot;...&quot; spellcheck=&quot;false&quot;&gt;&lt;/textarea&gt;
   1116                     
   1117                     &lt;div class=&quot;card-footer&quot;&gt;
   1118                         &lt;div class=&quot;char-count&quot;&gt;Result&lt;/div&gt;
   1119                         &lt;div class=&quot;icon-actions&quot;&gt;
   1120                             &lt;button class=&quot;icon-btn&quot; onclick=&quot;speakResult()&quot; title=&quot;Speak&quot;&gt;
   1121                                 &lt;svg width=&quot;20&quot; height=&quot;20&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z&quot;/&gt;&lt;/svg&gt;
   1122                             &lt;/button&gt;
   1123                             &lt;button class=&quot;icon-btn&quot; id=&quot;copyBtn&quot; onclick=&quot;copyToClipboard(&#x27;outputVal&#x27;, &#x27;copyBtn&#x27;)&quot; title=&quot;Copy (Ctrl+Enter)&quot;&gt;
   1124                                 &lt;svg width=&quot;20&quot; height=&quot;20&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z&quot;/&gt;&lt;/svg&gt;
   1125                             &lt;/button&gt;
   1126                         &lt;/div&gt;
   1127                     &lt;/div&gt;
   1128                 &lt;/div&gt;
   1129             &lt;/div&gt;
   1130 
   1131             &lt;!-- STEPS PANEL WITH COPY BUTTON --&gt;
   1132             &lt;div class=&quot;steps-container&quot; id=&quot;stepsContainer&quot;&gt;
   1133                 &lt;div class=&quot;steps-header&quot;&gt;
   1134                     &lt;h4 style=&quot;color:var(--md-sys-color-primary); margin:0;&quot;&gt;Calculation Steps&lt;/h4&gt;
   1135                     &lt;button class=&quot;icon-btn&quot; id=&quot;copyStepsBtn&quot; onclick=&quot;copyStepsText()&quot; title=&quot;Copy Steps&quot;&gt;
   1136                         &lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z&quot;/&gt;&lt;/svg&gt;
   1137                     &lt;/button&gt;
   1138                 &lt;/div&gt;
   1139                 &lt;div class=&quot;steps-content&quot; id=&quot;stepsOutput&quot;&gt;Waiting for input...&lt;/div&gt;
   1140             &lt;/div&gt;
   1141 
   1142             &lt;div class=&quot;history-section&quot;&gt;
   1143                 &lt;div class=&quot;history-header&quot; style=&quot;display:flex; justify-content:space-between; align-items:center; margin-bottom:10px;&quot;&gt;
   1144                     &lt;h4 style=&quot;color:var(--md-sys-color-on-surface-variant); margin:0;&quot;&gt;Recent History&lt;/h4&gt;
   1145                     &lt;button class=&quot;icon-btn&quot; id=&quot;clearHistBtn&quot; onclick=&quot;clearHistory()&quot; title=&quot;Clear History&quot;&gt;
   1146                         &lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z&quot;/&gt;&lt;/svg&gt;
   1147                     &lt;/button&gt;
   1148                 &lt;/div&gt;
   1149                 &lt;div class=&quot;history-list&quot; id=&quot;historyList&quot;&gt;
   1150                     &lt;div style=&quot;padding:10px; color:#555; text-align:center;&quot;&gt;No history yet&lt;/div&gt;
   1151                 &lt;/div&gt;
   1152             &lt;/div&gt;
   1153 
   1154         &lt;/section&gt;
   1155 
   1156         &lt;!-- SECTION 2: DYNAMIC CALCULATOR --&gt;
   1157         &lt;section id=&quot;calculator-section&quot; class=&quot;app-section&quot;&gt;
   1158             &lt;div class=&quot;calc-wrapper&quot;&gt;
   1159                 
   1160                 &lt;div class=&quot;calc-header&quot;&gt;
   1161                     &lt;div class=&quot;calc-ctrl-group&quot;&gt;
   1162                         &lt;label&gt;Base Mode&lt;/label&gt;
   1163                         &lt;div class=&quot;custom-select-wrapper&quot; id=&quot;calcBaseWrapper&quot; style=&quot;flex:1&quot;&gt;
   1164                             &lt;div class=&quot;custom-select-trigger&quot;&gt;
   1165                                 &lt;span class=&quot;selection-text&quot;&gt;Decimal (Base 10)&lt;/span&gt;
   1166                                 &lt;span class=&quot;arrow&quot;&gt;▼&lt;/span&gt;
   1167                             &lt;/div&gt;
   1168                             &lt;div class=&quot;custom-options&quot;&gt;
   1169                                 &lt;div class=&quot;custom-option&quot; data-value=&quot;2&quot;&gt;Binary (Base 2)&lt;/div&gt;
   1170                                 &lt;div class=&quot;custom-option&quot; data-value=&quot;8&quot;&gt;Octal (Base 8)&lt;/div&gt;
   1171                                 &lt;div class=&quot;custom-option selected&quot; data-value=&quot;10&quot;&gt;Decimal (Base 10)&lt;/div&gt;
   1172                                 &lt;div class=&quot;custom-option&quot; data-value=&quot;16&quot;&gt;Hex (Base 16)&lt;/div&gt;
   1173                             &lt;/div&gt;
   1174                             &lt;select id=&quot;calcBase&quot; style=&quot;display:none&quot; onchange=&quot;validateAllRows()&quot;&gt;
   1175                                 &lt;option value=&quot;2&quot;&gt;Binary&lt;/option&gt;
   1176                                 &lt;option value=&quot;8&quot;&gt;Octal&lt;/option&gt;
   1177                                 &lt;option value=&quot;10&quot; selected&gt;Decimal&lt;/option&gt;
   1178                                 &lt;option value=&quot;16&quot;&gt;Hex&lt;/option&gt;
   1179                             &lt;/select&gt;
   1180                         &lt;/div&gt;
   1181                     &lt;/div&gt;
   1182                     &lt;div class=&quot;calc-ctrl-group&quot;&gt;
   1183                         &lt;label&gt;Operation&lt;/label&gt;
   1184                         &lt;div class=&quot;custom-select-wrapper&quot; id=&quot;calcOpWrapper&quot; style=&quot;flex:1&quot;&gt;
   1185                             &lt;div class=&quot;custom-select-trigger&quot;&gt;
   1186                                 &lt;span class=&quot;selection-text&quot;&gt;Addition (+)&lt;/span&gt;
   1187                                 &lt;span class=&quot;arrow&quot;&gt;▼&lt;/span&gt;
   1188                             &lt;/div&gt;
   1189                             &lt;div class=&quot;custom-options&quot;&gt;
   1190                                 &lt;div class=&quot;custom-option selected&quot; data-value=&quot;add&quot;&gt;Addition (+)&lt;/div&gt;
   1191                                 &lt;div class=&quot;custom-option&quot; data-value=&quot;sub&quot;&gt;Subtraction (-)&lt;/div&gt;
   1192                                 &lt;div class=&quot;custom-option&quot; data-value=&quot;mul&quot;&gt;Multiplication (×)&lt;/div&gt;
   1193                                 &lt;div class=&quot;custom-option&quot; data-value=&quot;div&quot;&gt;Division (÷)&lt;/div&gt;
   1194                             &lt;/div&gt;
   1195                             &lt;select id=&quot;calcOp&quot; style=&quot;display:none&quot; onchange=&quot;runCalculation()&quot;&gt;
   1196                                 &lt;option value=&quot;add&quot; selected&gt;Addition&lt;/option&gt;
   1197                                 &lt;option value=&quot;sub&quot;&gt;Subtraction&lt;/option&gt;
   1198                                 &lt;option value=&quot;mul&quot;&gt;Multiplication&lt;/option&gt;
   1199                                 &lt;option value=&quot;div&quot;&gt;Division&lt;/option&gt;
   1200                             &lt;/select&gt;
   1201                         &lt;/div&gt;
   1202                     &lt;/div&gt;
   1203                 &lt;/div&gt;
   1204 
   1205                 &lt;div id=&quot;calcRows&quot; class=&quot;calc-rows&quot;&gt;
   1206                     &lt;!-- Dynamic Rows Injected Here --&gt;
   1207                 &lt;/div&gt;
   1208 
   1209                 &lt;!-- ADD ROW BUTTON (Left Aligned) --&gt;
   1210                 &lt;button class=&quot;add-row-btn&quot; onclick=&quot;addCalcRow()&quot;&gt;+ Add Number&lt;/button&gt;
   1211 
   1212                 &lt;div class=&quot;calc-actions&quot;&gt;
   1213                     &lt;button class=&quot;visualize-btn&quot; id=&quot;vizBtn&quot; onclick=&quot;visualizeCalculation()&quot;&gt;
   1214                         &lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z&quot;/&gt;&lt;/svg&gt;
   1215                         Visualize
   1216                     &lt;/button&gt;
   1217                     
   1218                     &lt;div class=&quot;calc-result-area&quot;&gt;
   1219                         &lt;div class=&quot;calc-result-display&quot;&gt;
   1220                             &lt;div class=&quot;res-label&quot;&gt;Result&lt;/div&gt;
   1221                             &lt;div class=&quot;res-value&quot; id=&quot;calcResult&quot;&gt;0&lt;/div&gt;
   1222                         &lt;/div&gt;
   1223                     &lt;/div&gt;
   1224                 &lt;/div&gt;
   1225 
   1226                 &lt;!-- BIT-BY-BIT VISUALIZER PANEL --&gt;
   1227                 &lt;div class=&quot;calc-visualizer&quot; id=&quot;visualizerPanel&quot;&gt;
   1228                     &lt;h4 style=&quot;color:var(--md-sys-color-primary); margin-bottom:15px; border-bottom:1px solid #333; padding-bottom:10px;&quot;&gt;Calculation Steps&lt;/h4&gt;
   1229                     &lt;div class=&quot;viz-grid&quot; id=&quot;vizGrid&quot;&gt;
   1230                         &lt;!-- Grid injected here --&gt;
   1231                     &lt;/div&gt;
   1232                     &lt;div class=&quot;viz-info&quot; id=&quot;vizInfo&quot;&gt;Click visualize to start...&lt;/div&gt;
   1233                 &lt;/div&gt;
   1234                 
   1235             &lt;/div&gt;
   1236         &lt;/section&gt;
   1237 
   1238     &lt;/main&gt;
   1239 
   1240     &lt;!-- PROJECT LEGACY MODAL --&gt;
   1241     &lt;div class=&quot;modal-overlay&quot; id=&quot;historyModal&quot;&gt;
   1242         &lt;div class=&quot;modal-content&quot;&gt;
   1243             &lt;div class=&quot;modal-header&quot;&gt;
   1244                 &lt;h3&gt;Project Legacy&lt;/h3&gt;
   1245                 &lt;button class=&quot;close-modal&quot; onclick=&quot;toggleHistory()&quot;&gt;×&lt;/button&gt;
   1246             &lt;/div&gt;
   1247             &lt;div class=&quot;modal-body&quot;&gt;
   1248                 &lt;div class=&quot;history-timeline&quot;&gt;
   1249                     &lt;div class=&quot;timeline-item&quot;&gt;
   1250                         &lt;div class=&quot;version-tag&quot;&gt;v1.0 (2024)&lt;/div&gt;
   1251                         &lt;p class=&quot;timeline-desc&quot;&gt;Initial High School Project. Single file, manual conversion logic, animated background.&lt;/p&gt;
   1252                     &lt;/div&gt;
   1253                     &lt;div class=&quot;timeline-item&quot;&gt;
   1254                         &lt;div class=&quot;version-tag&quot;&gt;v2.0&lt;/div&gt;
   1255                         &lt;p class=&quot;timeline-desc&quot;&gt;Modularized Logic &amp; URL State. Moved away from switch cases to a Base-N engine.&lt;/p&gt;
   1256                     &lt;/div&gt;
   1257                     &lt;div class=&quot;timeline-item&quot;&gt;
   1258                         &lt;div class=&quot;version-tag&quot;&gt;v2.1&lt;/div&gt;
   1259                         &lt;p class=&quot;timeline-desc&quot;&gt;Material You UI. Glassmorphism, animated cards, and custom dropdowns.&lt;/p&gt;
   1260                     &lt;/div&gt;
   1261                     &lt;div class=&quot;timeline-item&quot;&gt;
   1262                         &lt;div class=&quot;version-tag&quot;&gt;v2.2&lt;/div&gt;
   1263                         &lt;p class=&quot;timeline-desc&quot;&gt;Dynamic Calculator. Added list-based arithmetic with strict validation.&lt;/p&gt;
   1264                     &lt;/div&gt;
   1265                     &lt;div class=&quot;timeline-item&quot;&gt;
   1266                         &lt;div class=&quot;version-tag&quot;&gt;v2.3 - v2.8&lt;/div&gt;
   1267                         &lt;p class=&quot;timeline-desc&quot;&gt;Visualizer Engine. Bit-by-bit animation, step explanations, and history tape.&lt;/p&gt;
   1268                     &lt;/div&gt;
   1269                     &lt;div class=&quot;timeline-item&quot;&gt;
   1270                         &lt;div class=&quot;version-tag&quot;&gt;v2.10&lt;/div&gt;
   1271                         &lt;p class=&quot;timeline-desc&quot;&gt;Professional Polish. Optimized UX layout, legacy tracking, and performance tuning.&lt;/p&gt;
   1272                     &lt;/div&gt;
   1273                     &lt;div class=&quot;timeline-item&quot;&gt;
   1274                         &lt;div class=&quot;version-tag current&quot;&gt;v2.11 (2026)&lt;/div&gt;
   1275                         &lt;p class=&quot;timeline-desc&quot;&gt;Ultimate Refinement. Enhanced animations, layout stability, and smart controls.&lt;/p&gt;
   1276                     &lt;/div&gt;
   1277                 &lt;/div&gt;
   1278             &lt;/div&gt;
   1279         &lt;/div&gt;
   1280     &lt;/div&gt;
   1281 
   1282     &lt;!-- SIDEBAR CHEATSHEET --&gt;
   1283     &lt;aside class=&quot;sidebar&quot; id=&quot;sidebar&quot;&gt;
   1284         &lt;button class=&quot;close-sidebar&quot; onclick=&quot;toggleSidebar()&quot;&gt;×&lt;/button&gt;
   1285         &lt;h3&gt;Cheat Sheet&lt;/h3&gt;
   1286         
   1287         &lt;h4&gt;Powers of 2&lt;/h4&gt;
   1288         &lt;table class=&quot;cheat-table&quot; style=&quot;margin-bottom:20px;&quot;&gt;
   1289             &lt;tr&gt;&lt;td&gt;2⁰&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
   1290             &lt;tr&gt;&lt;td&gt;2¹&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
   1291             &lt;tr&gt;&lt;td&gt;2²&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;/tr&gt;
   1292             &lt;tr&gt;&lt;td&gt;2³&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;/tr&gt;
   1293             &lt;tr&gt;&lt;td&gt;2⁴&lt;/td&gt;&lt;td&gt;16&lt;/td&gt;&lt;/tr&gt;
   1294             &lt;tr&gt;&lt;td&gt;2⁵&lt;/td&gt;&lt;td&gt;32&lt;/td&gt;&lt;/tr&gt;
   1295             &lt;tr&gt;&lt;td&gt;2⁶&lt;/td&gt;&lt;td&gt;64&lt;/td&gt;&lt;/tr&gt;
   1296             &lt;tr&gt;&lt;td&gt;2⁷&lt;/td&gt;&lt;td&gt;128&lt;/td&gt;&lt;/tr&gt;
   1297             &lt;tr&gt;&lt;td&gt;2⁸&lt;/td&gt;&lt;td&gt;256&lt;/td&gt;&lt;/tr&gt;
   1298             &lt;tr&gt;&lt;td&gt;2¹⁰&lt;/td&gt;&lt;td&gt;1024&lt;/td&gt;&lt;/tr&gt;
   1299         &lt;/table&gt;
   1300 
   1301         &lt;h4&gt;Hex Lookup&lt;/h4&gt;
   1302         &lt;table class=&quot;cheat-table&quot;&gt;
   1303             &lt;tr&gt;&lt;th&gt;Dec&lt;/th&gt;&lt;th&gt;Hex&lt;/th&gt;&lt;th&gt;Bin&lt;/th&gt;&lt;/tr&gt;
   1304             &lt;tr&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;0000&lt;/td&gt;&lt;/tr&gt;
   1305             &lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;0001&lt;/td&gt;&lt;/tr&gt;
   1306             &lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;A&lt;/td&gt;&lt;td&gt;1010&lt;/td&gt;&lt;/tr&gt;
   1307             &lt;tr&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;B&lt;/td&gt;&lt;td&gt;1011&lt;/td&gt;&lt;/tr&gt;
   1308             &lt;tr&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;1100&lt;/td&gt;&lt;/tr&gt;
   1309             &lt;tr&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;D&lt;/td&gt;&lt;td&gt;1101&lt;/td&gt;&lt;/tr&gt;
   1310             &lt;tr&gt;&lt;td&gt;14&lt;/td&gt;&lt;td&gt;E&lt;/td&gt;&lt;td&gt;1110&lt;/td&gt;&lt;/tr&gt;
   1311             &lt;tr&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;F&lt;/td&gt;&lt;td&gt;1111&lt;/td&gt;&lt;/tr&gt;
   1312         &lt;/table&gt;
   1313     &lt;/aside&gt;
   1314 
   1315     &lt;footer&gt;
   1316         &lt;div class=&quot;footer-content&quot;&gt;
   1317             &lt;p&gt;&amp;copy; 2026 &lt;strong&gt;Amit Dutta&lt;/strong&gt;. All rights reserved.&lt;/p&gt;
   1318             &lt;div class=&quot;footer-links&quot;&gt;
   1319                 &lt;a href=&quot;https://amit.is-a.dev&quot; target=&quot;_blank&quot; class=&quot;footer-link&quot;&gt;amit.is-a.dev&lt;/a&gt;
   1320                 &lt;span&gt;•&lt;/span&gt;
   1321                 &lt;a href=&quot;https://github.com/notamitgamer&quot; target=&quot;_blank&quot; class=&quot;footer-link&quot;&gt;GitHub&lt;/a&gt;
   1322             &lt;/div&gt;
   1323         &lt;/div&gt;
   1324     &lt;/footer&gt;
   1325 
   1326     &lt;script&gt;
   1327         document.addEventListener(&#x27;DOMContentLoaded&#x27;, () =&gt; {
   1328             setupCustomDropdown(&#x27;sourceSelectWrapper&#x27;, &#x27;fromBase&#x27;);
   1329             setupCustomDropdown(&#x27;targetSelectWrapper&#x27;, &#x27;toBase&#x27;);
   1330             setupCustomDropdown(&#x27;calcBaseWrapper&#x27;, &#x27;calcBase&#x27;);
   1331             setupCustomDropdown(&#x27;calcOpWrapper&#x27;, &#x27;calcOp&#x27;);
   1332             
   1333             setupEventListeners();
   1334             
   1335             // Initialize Calculator
   1336             addCalcRow();
   1337             addCalcRow();
   1338             
   1339             renderHistory();
   1340 
   1341             try {
   1342                 const params = new URLSearchParams(window.location.search);
   1343                 if(params.has(&#x27;val&#x27;)) {
   1344                     document.getElementById(&#x27;inputVal&#x27;).value = params.get(&#x27;val&#x27;);
   1345                     if(params.has(&#x27;from&#x27;)) {
   1346                         const val = params.get(&#x27;from&#x27;);
   1347                         document.getElementById(&#x27;fromBase&#x27;).value = val;
   1348                         updateDropdownUI(&#x27;sourceSelectWrapper&#x27;, val);
   1349                     }
   1350                     if(params.has(&#x27;to&#x27;)) {
   1351                         const val = params.get(&#x27;to&#x27;);
   1352                         document.getElementById(&#x27;toBase&#x27;).value = val;
   1353                         updateDropdownUI(&#x27;targetSelectWrapper&#x27;, val);
   1354                     }
   1355                     convert();
   1356                 }
   1357             } catch(e) {}
   1358             
   1359             document.addEventListener(&#x27;click&#x27;, (e) =&gt; {
   1360                 const sidebar = document.getElementById(&#x27;sidebar&#x27;);
   1361                 const historyModal = document.getElementById(&#x27;historyModal&#x27;);
   1362                 const toolsBtns = document.querySelectorAll(&#x27;.tools-btn&#x27;);
   1363                 let clickedBtn = false;
   1364                 toolsBtns.forEach(btn =&gt; { if(btn.contains(e.target)) clickedBtn = true; });
   1365 
   1366                 if (!sidebar.contains(e.target) &amp;&amp; !clickedBtn &amp;&amp; sidebar.classList.contains(&#x27;open&#x27;)) {
   1367                     toggleSidebar();
   1368                 }
   1369                 if (e.target === historyModal) {
   1370                     toggleHistory();
   1371                 }
   1372             });
   1373         });
   1374 
   1375         /* --- NAVIGATION --- */
   1376         function switchTab(tabName, index) {
   1377             document.querySelectorAll(&#x27;.app-section&#x27;).forEach(el =&gt; el.classList.remove(&#x27;active&#x27;));
   1378             document.getElementById(tabName + &#x27;-section&#x27;).classList.add(&#x27;active&#x27;);
   1379             
   1380             document.querySelectorAll(&#x27;.nav-tab&#x27;).forEach(el =&gt; el.classList.remove(&#x27;active&#x27;));
   1381             const tabs = document.querySelectorAll(&#x27;.nav-tab&#x27;);
   1382             tabs[index].classList.add(&#x27;active&#x27;);
   1383             
   1384             const glider = document.getElementById(&#x27;navGlider&#x27;);
   1385             glider.style.transform = `translateX(${index * 100}%)`;
   1386         }
   1387 
   1388         function toggleSidebar() {
   1389             document.getElementById(&#x27;sidebar&#x27;).classList.toggle(&#x27;open&#x27;);
   1390         }
   1391 
   1392         function toggleHistory() {
   1393             const modal = document.getElementById(&#x27;historyModal&#x27;);
   1394             modal.classList.toggle(&#x27;open&#x27;);
   1395         }
   1396 
   1397         /* --- DROPDOWN LOGIC --- */
   1398         function setupCustomDropdown(wrapperId, nativeSelectId) {
   1399             const wrapper = document.getElementById(wrapperId);
   1400             const nativeSelect = document.getElementById(nativeSelectId);
   1401             const trigger = wrapper.querySelector(&#x27;.custom-select-trigger&#x27;);
   1402             const triggerText = trigger.querySelector(&#x27;.selection-text&#x27;);
   1403             const options = wrapper.querySelectorAll(&#x27;.custom-option&#x27;);
   1404 
   1405             trigger.addEventListener(&#x27;click&#x27;, (e) =&gt; {
   1406                 e.stopPropagation();
   1407                 document.querySelectorAll(&#x27;.custom-select-wrapper&#x27;).forEach(w =&gt; {
   1408                     if(w !== wrapper) w.classList.remove(&#x27;open&#x27;);
   1409                 });
   1410                 wrapper.classList.toggle(&#x27;open&#x27;);
   1411             });
   1412 
   1413             options.forEach(opt =&gt; {
   1414                 opt.addEventListener(&#x27;click&#x27;, (e) =&gt; {
   1415                     e.stopPropagation();
   1416                     wrapper.querySelectorAll(&#x27;.custom-option&#x27;).forEach(o =&gt; o.classList.remove(&#x27;selected&#x27;));
   1417                     opt.classList.add(&#x27;selected&#x27;);
   1418                     triggerText.textContent = opt.textContent;
   1419                     wrapper.classList.remove(&#x27;open&#x27;);
   1420                     
   1421                     nativeSelect.value = opt.getAttribute(&#x27;data-value&#x27;);
   1422                     nativeSelect.dispatchEvent(new Event(&#x27;change&#x27;));
   1423                 });
   1424             });
   1425 
   1426             document.addEventListener(&#x27;click&#x27;, () =&gt; {
   1427                 wrapper.classList.remove(&#x27;open&#x27;);
   1428             });
   1429         }
   1430         
   1431         function updateDropdownUI(wrapperId, value) {
   1432             const wrapper = document.getElementById(wrapperId);
   1433             const triggerText = wrapper.querySelector(&#x27;.selection-text&#x27;);
   1434             const options = wrapper.querySelectorAll(&#x27;.custom-option&#x27;);
   1435             
   1436             options.forEach(opt =&gt; {
   1437                 if(opt.getAttribute(&#x27;data-value&#x27;) === value) {
   1438                     opt.classList.add(&#x27;selected&#x27;);
   1439                     triggerText.textContent = opt.textContent;
   1440                 } else {
   1441                     opt.classList.remove(&#x27;selected&#x27;);
   1442                 }
   1443             });
   1444         }
   1445 
   1446         /* --- CONVERTER LOGIC --- */
   1447         function convert() {
   1448             const inputVal = document.getElementById(&#x27;inputVal&#x27;).value;
   1449             const outputEl = document.getElementById(&#x27;outputVal&#x27;);
   1450             const errorChip = document.getElementById(&#x27;errorChip&#x27;);
   1451             const fromBase = parseInt(document.getElementById(&#x27;fromBase&#x27;).value);
   1452             const toBase = parseInt(document.getElementById(&#x27;toBase&#x27;).value);
   1453 
   1454             document.getElementById(&#x27;sourceCount&#x27;).textContent = `${inputVal.length} chars`;
   1455             errorChip.classList.remove(&#x27;visible&#x27;);
   1456 
   1457             if(!inputVal) { 
   1458                 outputEl.value = &#x27;&#x27;; 
   1459                 document.getElementById(&#x27;stepsContainer&#x27;).classList.remove(&#x27;visible&#x27;);
   1460                 updateURL(&#x27;&#x27;);
   1461                 return; 
   1462             }
   1463 
   1464             const normalized = inputVal.trim().toUpperCase();
   1465             const validChars = &quot;0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.&quot;.substring(0, fromBase) + &quot;.&quot;;
   1466             const regex = new RegExp(`^[${validChars}]+$`);
   1467             
   1468             if(!regex.test(normalized)) {
   1469                 errorChip.classList.add(&#x27;visible&#x27;);
   1470                 outputEl.value = &quot;Error&quot;;
   1471                 document.getElementById(&#x27;stepsContainer&#x27;).classList.remove(&#x27;visible&#x27;);
   1472                 return;
   1473             }
   1474 
   1475             try {
   1476                 updateURL(normalized, fromBase, toBase);
   1477 
   1478                 const parts = normalized.split(&#x27;.&#x27;);
   1479                 const decInt = parseInt(parts[0], fromBase);
   1480                 let decTotal = decInt;
   1481                 
   1482                 const result = decTotal.toString(toBase).toUpperCase();
   1483                 outputEl.value = result;
   1484 
   1485                 generateSteps(normalized, fromBase, toBase, decTotal, result);
   1486                 addToHistory(normalized, result, fromBase, toBase);
   1487 
   1488             } catch(e) {
   1489                 outputEl.value = &quot;Error&quot;;
   1490             }
   1491         }
   1492 
   1493         function generateSteps(input, from, to, decimal, result) {
   1494             const container = document.getElementById(&#x27;stepsContainer&#x27;);
   1495             const output = document.getElementById(&#x27;stepsOutput&#x27;);
   1496             container.classList.add(&#x27;visible&#x27;);
   1497             
   1498             let log = `Converting ${input} (Base ${from}) to Base ${to}\n`;
   1499             log += `------------------------------------------\n`;
   1500             
   1501             if(from !== 10) {
   1502                 log += `1. Convert to Decimal:\n   `;
   1503                 const digits = input.split(&#x27;.&#x27;)[0].split(&#x27;&#x27;).reverse();
   1504                 digits.forEach((d, i) =&gt; {
   1505                     log += `${d}×${from}^${i} + `;
   1506                 });
   1507                 log = log.slice(0, -3); // Remove last +
   1508                 log += ` = ${decimal}\n\n`;
   1509             } else {
   1510                 log += `1. Already Decimal: ${decimal}\n\n`;
   1511             }
   1512 
   1513             if(to !== 10) {
   1514                 log += `2. Convert Decimal ${decimal} to Base ${to}:\n`;
   1515                 let temp = decimal;
   1516                 while(temp &gt; 0) {
   1517                     let rem = temp % to;
   1518                     let quot = Math.floor(temp / to);
   1519                     log += `   ${temp} ÷ ${to} = ${quot} [Rem: ${rem.toString(to).toUpperCase()}]\n`;
   1520                     temp = quot;
   1521                 }
   1522                 log += `   Read remainders bottom-up: ${result}`;
   1523             } else {
   1524                 log += `2. Result is Decimal: ${result}`;
   1525             }
   1526             output.textContent = log;
   1527         }
   1528 
   1529         function updateURL(val, from, to) {
   1530             try {
   1531                 const url = new URL(window.location);
   1532                 if(val) {
   1533                     url.searchParams.set(&#x27;val&#x27;, val);
   1534                     url.searchParams.set(&#x27;from&#x27;, from);
   1535                     url.searchParams.set(&#x27;to&#x27;, to);
   1536                     window.history.replaceState({}, &#x27;&#x27;, url);
   1537                 } else {
   1538                     const cleanUrl = window.location.pathname;
   1539                     window.history.replaceState({}, &#x27;&#x27;, cleanUrl);
   1540                 }
   1541             } catch(e) {}
   1542         }
   1543 
   1544         /* --- HISTORY LOGIC --- */
   1545         function addToHistory(inVal, outVal, from, to) {
   1546             const key = &quot;nct_history&quot;;
   1547             let history = JSON.parse(localStorage.getItem(key) || &quot;[]&quot;);
   1548             if(history.length &gt; 0 &amp;&amp; history[0].inVal === inVal &amp;&amp; history[0].to === to) return;
   1549             history.unshift({ inVal, outVal, from, to });
   1550             if(history.length &gt; 10) history.pop();
   1551             localStorage.setItem(key, JSON.stringify(history));
   1552             renderHistory();
   1553         }
   1554 
   1555         function renderHistory() {
   1556             const list = document.getElementById(&#x27;historyList&#x27;);
   1557             const history = JSON.parse(localStorage.getItem(&quot;nct_history&quot;) || &quot;[]&quot;);
   1558             if(history.length === 0) {
   1559                 list.innerHTML = &#x27;&lt;div style=&quot;padding:10px; color:#555; text-align:center;&quot;&gt;No history yet&lt;/div&gt;&#x27;;
   1560                 return;
   1561             }
   1562             list.innerHTML = &#x27;&#x27;;
   1563             history.forEach(item =&gt; {
   1564                 const div = document.createElement(&#x27;div&#x27;);
   1565                 div.className = &#x27;history-item&#x27;;
   1566                 div.innerHTML = `&lt;div&gt;&lt;span class=&quot;hist-meta&quot;&gt;Base ${item.from} → ${item.to}&lt;/span&gt;&lt;span class=&quot;hist-val&quot;&gt;${item.inVal} = ${item.outVal}&lt;/span&gt;&lt;/div&gt;`;
   1567                 div.onclick = () =&gt; {
   1568                     document.getElementById(&#x27;inputVal&#x27;).value = item.inVal;
   1569                     document.getElementById(&#x27;fromBase&#x27;).value = item.from;
   1570                     document.getElementById(&#x27;toBase&#x27;).value = item.to;
   1571                     updateDropdownUI(&#x27;sourceSelectWrapper&#x27;, item.from.toString());
   1572                     updateDropdownUI(&#x27;targetSelectWrapper&#x27;, item.to.toString());
   1573                     convert();
   1574                 };
   1575                 list.appendChild(div);
   1576             });
   1577         }
   1578         
   1579         function clearHistory() {
   1580             const list = document.getElementById(&#x27;historyList&#x27;);
   1581             const btn = document.getElementById(&#x27;clearHistBtn&#x27;);
   1582             
   1583             if(list.children.length === 0 || list.innerText.includes(&quot;No history&quot;)) return;
   1584             
   1585             // Trigger Shake Animation on Button
   1586             btn.classList.add(&#x27;shaking&#x27;);
   1587             
   1588             // Trigger Slide Out Animation on List
   1589             list.classList.add(&#x27;clearing&#x27;);
   1590             
   1591             setTimeout(() =&gt; {
   1592                 localStorage.removeItem(&quot;nct_history&quot;);
   1593                 renderHistory();
   1594                 list.classList.remove(&#x27;clearing&#x27;);
   1595                 btn.classList.remove(&#x27;shaking&#x27;);
   1596             }, 400); // Duration matches CSS animation
   1597         }
   1598 
   1599         /* --- DYNAMIC CALCULATOR LOGIC --- */
   1600         function addCalcRow() {
   1601             const container = document.getElementById(&#x27;calcRows&#x27;);
   1602             const div = document.createElement(&#x27;div&#x27;);
   1603             div.className = &#x27;calc-row&#x27;;
   1604             div.innerHTML = `
   1605                 &lt;div class=&quot;calc-input-wrapper&quot;&gt;
   1606                     &lt;input type=&quot;text&quot; class=&quot;calc-input&quot; placeholder=&quot;Enter number...&quot; oninput=&quot;validateRow(this); runCalculation()&quot;&gt;
   1607                 &lt;/div&gt;
   1608                 &lt;button class=&quot;calc-remove-btn&quot; onclick=&quot;removeRow(this)&quot; title=&quot;Remove&quot;&gt;×&lt;/button&gt;
   1609             `;
   1610             container.appendChild(div);
   1611             div.querySelector(&#x27;input&#x27;).focus();
   1612         }
   1613 
   1614         function removeRow(btn) {
   1615             const row = btn.parentElement;
   1616             if(document.querySelectorAll(&#x27;.calc-row&#x27;).length &gt; 1) {
   1617                 row.classList.add(&#x27;removing&#x27;);
   1618                 setTimeout(() =&gt; {
   1619                     row.remove();
   1620                     runCalculation();
   1621                 }, 300);
   1622             }
   1623         }
   1624 
   1625         function validateRow(input) {
   1626             const base = parseInt(document.getElementById(&#x27;calcBase&#x27;).value);
   1627             const val = input.value.trim().toUpperCase();
   1628             if(!val) {
   1629                 input.classList.remove(&#x27;invalid&#x27;);
   1630                 return true;
   1631             }
   1632             const validChars = &quot;0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.&quot;.substring(0, base) + &quot;.&quot;;
   1633             const regex = new RegExp(`^[${validChars}]+$`);
   1634             if(!regex.test(val)) {
   1635                 input.classList.add(&#x27;invalid&#x27;);
   1636                 return false;
   1637             } else {
   1638                 input.classList.remove(&#x27;invalid&#x27;);
   1639                 return true;
   1640             }
   1641         }
   1642 
   1643         function validateAllRows() {
   1644             document.querySelectorAll(&#x27;.calc-input&#x27;).forEach(input =&gt; validateRow(input));
   1645             runCalculation();
   1646         }
   1647 
   1648         function runCalculation() {
   1649             const base = parseInt(document.getElementById(&#x27;calcBase&#x27;).value);
   1650             const op = document.getElementById(&#x27;calcOp&#x27;).value;
   1651             const inputs = document.querySelectorAll(&#x27;.calc-input&#x27;);
   1652             const vizBtn = document.getElementById(&#x27;vizBtn&#x27;);
   1653             let total = null;
   1654             let error = false;
   1655 
   1656             inputs.forEach(input =&gt; {
   1657                 if(input.classList.contains(&#x27;invalid&#x27;)) { error = true; return; }
   1658                 const valStr = input.value.trim().toUpperCase();
   1659                 if(!valStr) return;
   1660                 const val = parseInt(valStr, base);
   1661                 if(isNaN(val)) return;
   1662                 if(total === null) { total = val; } else {
   1663                     if(op === &#x27;add&#x27;) total += val;
   1664                     if(op === &#x27;sub&#x27;) total -= val;
   1665                     if(op === &#x27;mul&#x27;) total *= val;
   1666                     if(op === &#x27;div&#x27;) total = Math.floor(total / val);
   1667                 }
   1668             });
   1669 
   1670             const resEl = document.getElementById(&#x27;calcResult&#x27;);
   1671             if(error) {
   1672                 resEl.textContent = &quot;Invalid Input&quot;;
   1673                 resEl.style.color = &quot;var(--md-sys-color-error)&quot;;
   1674                 vizBtn.style.display = &#x27;none&#x27;;
   1675             } else if(total === null) {
   1676                 resEl.textContent = &quot;0&quot;;
   1677                 resEl.style.color = &quot;var(--md-sys-color-primary)&quot;;
   1678                 vizBtn.style.display = &#x27;none&#x27;;
   1679             } else {
   1680                 resEl.textContent = total.toString(base).toUpperCase();
   1681                 resEl.style.color = &quot;var(--md-sys-color-primary)&quot;;
   1682                 vizBtn.style.display = (op === &#x27;add&#x27;) ? &#x27;flex&#x27; : &#x27;none&#x27;;
   1683             }
   1684             document.getElementById(&#x27;visualizerPanel&#x27;).classList.remove(&#x27;active&#x27;);
   1685         }
   1686 
   1687         /* --- VISUALIZER LOGIC (Multi-Base) --- */
   1688         function visualizeCalculation() {
   1689             const base = parseInt(document.getElementById(&#x27;calcBase&#x27;).value);
   1690             const op = document.getElementById(&#x27;calcOp&#x27;).value;
   1691             const panel = document.getElementById(&#x27;visualizerPanel&#x27;);
   1692             const grid = document.getElementById(&#x27;vizGrid&#x27;);
   1693             const info = document.getElementById(&#x27;vizInfo&#x27;);
   1694             
   1695             if(op !== &#x27;add&#x27;) return;
   1696 
   1697             const inputs = [];
   1698             let isValid = true;
   1699             document.querySelectorAll(&#x27;.calc-input&#x27;).forEach(inp =&gt; {
   1700                 if(inp.value.trim()) {
   1701                      const val = parseInt(inp.value.trim(), base);
   1702                      if(isNaN(val)) isValid = false;
   1703                      inputs.push(val);
   1704                 }
   1705             });
   1706 
   1707             if(!isValid || inputs.length &lt; 2) {
   1708                 alert(&quot;Enter at least two numbers.&quot;);
   1709                 return;
   1710             }
   1711 
   1712             panel.classList.add(&#x27;active&#x27;);
   1713             grid.innerHTML = &#x27;&#x27;;
   1714             
   1715             const digitArrays = inputs.map(n =&gt; n.toString(base).toUpperCase().split(&#x27;&#x27;));
   1716             const maxLen = Math.max(...digitArrays.map(arr =&gt; arr.length)) + 1;
   1717             
   1718             const paddedArrays = digitArrays.map(arr =&gt; {
   1719                 const padding = new Array(maxLen - arr.length).fill(&#x27;0&#x27;);
   1720                 return padding.concat(arr);
   1721             });
   1722             
   1723             grid.style.gridTemplateColumns = `repeat(${maxLen}, 1fr)`;
   1724             
   1725             for(let i=0; i&lt;maxLen; i++) {
   1726                 const cell = document.createElement(&#x27;div&#x27;);
   1727                 cell.className = &#x27;viz-cell carry&#x27;;
   1728                 cell.id = `carry-${i}`;
   1729                 grid.appendChild(cell);
   1730             }
   1731             
   1732             paddedArrays.forEach((rowDigits, rIdx) =&gt; {
   1733                 for(let i=0; i&lt;maxLen; i++) {
   1734                     const cell = document.createElement(&#x27;div&#x27;);
   1735                     cell.className = &#x27;viz-cell&#x27;;
   1736                     if(rIdx === paddedArrays.length -1) cell.classList.add(&#x27;border-bottom&#x27;);
   1737                     const val = rowDigits[i];
   1738                     cell.textContent = val;
   1739                     if(i === 0 &amp;&amp; rIdx &gt; 0) {
   1740                         cell.classList.add(&#x27;operator&#x27;);
   1741                         cell.innerHTML = `+ ${val}`;
   1742                     }
   1743                     grid.appendChild(cell);
   1744                 }
   1745             });
   1746 
   1747             for(let i=0; i&lt;maxLen; i++) {
   1748                 const cell = document.createElement(&#x27;div&#x27;);
   1749                 cell.className = &#x27;viz-cell result&#x27;;
   1750                 cell.id = `res-${i}`;
   1751                 cell.textContent = &#x27;?&#x27;;
   1752                 grid.appendChild(cell);
   1753             }
   1754 
   1755             let carry = 0;
   1756             let colIdx = maxLen - 1;
   1757 
   1758             function step() {
   1759                 if(colIdx &lt; 0) {
   1760                     info.textContent = &quot;Complete.&quot;;
   1761                     return;
   1762                 }
   1763                 document.querySelectorAll(&#x27;.active-col&#x27;).forEach(el =&gt; el.classList.remove(&#x27;active-col&#x27;));
   1764                 const resCell = document.getElementById(`res-${colIdx}`);
   1765                 resCell.classList.add(&#x27;active-col&#x27;);
   1766                 
   1767                 let sum = carry;
   1768                 const digitVals = [];
   1769                 paddedArrays.forEach(row =&gt; {
   1770                     const char = row[colIdx];
   1771                     const val = parseInt(char, base);
   1772                     sum += val;
   1773                     digitVals.push(val.toString(base).toUpperCase());
   1774                 });
   1775 
   1776                 const writeVal = sum % base;
   1777                 const newCarry = Math.floor(sum / base);
   1778 
   1779                 resCell.textContent = writeVal.toString(base).toUpperCase();
   1780                 if(newCarry &gt; 0 &amp;&amp; colIdx &gt; 0) {
   1781                     document.getElementById(`carry-${colIdx-1}`).textContent = newCarry.toString(base).toUpperCase();
   1782                 }
   1783                 
   1784                 const eqStr = `${digitVals.join(&#x27;+&#x27;)} + ${carry}(c) = ${sum}`;
   1785                 const writeStr = writeVal.toString(base).toUpperCase();
   1786                 const carryStr = newCarry.toString(base).toUpperCase();
   1787                 info.textContent = `Col ${maxLen - colIdx}: ${eqStr} (Base ${base}). Write ${writeStr}, Carry ${carryStr}`;
   1788 
   1789                 carry = newCarry;
   1790                 colIdx--;
   1791                 setTimeout(step, 800);
   1792             }
   1793             step();
   1794         }
   1795 
   1796         /* --- UTILS &amp; SWAP --- */
   1797         function setupEventListeners() {
   1798             document.addEventListener(&#x27;keydown&#x27;, (e) =&gt; {
   1799                 if(e.ctrlKey &amp;&amp; e.key === &#x27;Enter&#x27;) copyToClipboard(&#x27;outputVal&#x27;, &#x27;copyBtn&#x27;);
   1800                 if(e.altKey &amp;&amp; e.key === &#x27;s&#x27;) document.getElementById(&#x27;swapBtn&#x27;).click();
   1801             });
   1802 
   1803             document.getElementById(&#x27;inputVal&#x27;).addEventListener(&#x27;input&#x27;, convert);
   1804             document.getElementById(&#x27;fromBase&#x27;).addEventListener(&#x27;change&#x27;, convert);
   1805             document.getElementById(&#x27;toBase&#x27;).addEventListener(&#x27;change&#x27;, convert);
   1806 
   1807             document.getElementById(&#x27;swapBtn&#x27;).addEventListener(&#x27;click&#x27;, () =&gt; {
   1808                 const cardSource = document.getElementById(&#x27;cardSource&#x27;);
   1809                 const cardTarget = document.getElementById(&#x27;cardTarget&#x27;);
   1810                 const isMobile = window.innerWidth &lt;= 768;
   1811 
   1812                 if(isMobile) {
   1813                     cardSource.classList.add(&#x27;anim-move-down&#x27;);
   1814                     cardTarget.classList.add(&#x27;anim-move-up&#x27;);
   1815                 } else {
   1816                     cardSource.classList.add(&#x27;anim-move-right&#x27;);
   1817                     cardTarget.classList.add(&#x27;anim-move-left&#x27;);
   1818                 }
   1819 
   1820                 setTimeout(() =&gt; {
   1821                     const inEl = document.getElementById(&#x27;inputVal&#x27;);
   1822                     const outEl = document.getElementById(&#x27;outputVal&#x27;);
   1823                     const from = document.getElementById(&#x27;fromBase&#x27;);
   1824                     const to = document.getElementById(&#x27;toBase&#x27;);
   1825 
   1826                     const tempVal = inEl.value;
   1827                     inEl.value = outEl.value;
   1828                     const tempBase = from.value;
   1829                     from.value = to.value;
   1830                     to.value = tempBase;
   1831                     
   1832                     updateDropdownUI(&#x27;sourceSelectWrapper&#x27;, from.value);
   1833                     updateDropdownUI(&#x27;targetSelectWrapper&#x27;, to.value);
   1834 
   1835                     cardSource.classList.remove(&#x27;anim-move-down&#x27;, &#x27;anim-move-right&#x27;);
   1836                     cardTarget.classList.remove(&#x27;anim-move-up&#x27;, &#x27;anim-move-left&#x27;);
   1837                     convert();
   1838                 }, 400); 
   1839             });
   1840         }
   1841 
   1842         function speakResult() {
   1843             const txt = document.getElementById(&#x27;outputVal&#x27;).value;
   1844             if(!txt) return;
   1845             let spoken = txt;
   1846             if(document.getElementById(&#x27;toBase&#x27;).value == 2) {
   1847                 spoken = txt.split(&#x27;&#x27;).join(&#x27; &#x27;); 
   1848             }
   1849             const utt = new SpeechSynthesisUtterance(spoken);
   1850             window.speechSynthesis.speak(utt);
   1851         }
   1852 
   1853         function copyToClipboard(id, btnId) {
   1854             const el = document.getElementById(id);
   1855             if(el) {
   1856                 el.select();
   1857                 document.execCommand(&#x27;copy&#x27;);
   1858             }
   1859             const btn = document.getElementById(btnId);
   1860             if(btn) {
   1861                 const originalHTML = btn.innerHTML;
   1862                 btn.innerHTML = `&lt;svg width=&quot;20&quot; height=&quot;20&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;var(--md-sys-color-success)&quot;&gt;&lt;path d=&quot;M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z&quot;/&gt;&lt;/svg&gt;`;
   1863                 btn.classList.add(&#x27;success&#x27;);
   1864                 setTimeout(() =&gt; { 
   1865                     btn.innerHTML = originalHTML; 
   1866                     btn.classList.remove(&#x27;success&#x27;);
   1867                 }, 2000);
   1868             }
   1869         }
   1870         
   1871         function copyStepsText() {
   1872             const stepsText = document.getElementById(&#x27;stepsOutput&#x27;).innerText;
   1873             navigator.clipboard.writeText(stepsText).then(() =&gt; {
   1874                 const btn = document.getElementById(&#x27;copyStepsBtn&#x27;);
   1875                 const originalHTML = btn.innerHTML;
   1876                 btn.innerHTML = `&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;var(--md-sys-color-success)&quot;&gt;&lt;path d=&quot;M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z&quot;/&gt;&lt;/svg&gt;`;
   1877                 btn.classList.add(&#x27;success&#x27;);
   1878                 setTimeout(() =&gt; { 
   1879                     btn.innerHTML = originalHTML; 
   1880                     btn.classList.remove(&#x27;success&#x27;);
   1881                 }, 2000);
   1882             });
   1883         }
   1884 
   1885         function clearAll() {
   1886             document.getElementById(&#x27;inputVal&#x27;).value = &#x27;&#x27;;
   1887             document.getElementById(&#x27;outputVal&#x27;).value = &#x27;&#x27;;
   1888             document.getElementById(&#x27;sourceCount&#x27;).textContent = &#x27;0 chars&#x27;;
   1889             document.getElementById(&#x27;errorChip&#x27;).classList.remove(&#x27;visible&#x27;);
   1890             document.getElementById(&#x27;stepsContainer&#x27;).classList.remove(&#x27;visible&#x27;);
   1891             updateURL(&#x27;&#x27;);
   1892         }
   1893     &lt;/script&gt;
   1894 &lt;/body&gt;
   1895 &lt;/html&gt;</pre>
   1896             </div>
   1897         </div>
   1898 
   1899         <div id="download-tab-content" class="tab-content">
   1900             <div class="download-item">
   1901                 <div class="download-info">
   1902                     <h3>nct-legacy.html</h3>
   1903                     <p>Standalone production code of the Number Conversion Tool.</p>
   1904                 </div>
   1905                 <!-- Force download via download attribute -->
   1906                 <a href="nct-legacy.html" download="nct-legacy.html" class="download-button">Download File</a>
   1907             </div>
   1908             <div class="download-item">
   1909                 <div class="download-info">
   1910                     <h3>GitHub Repository</h3>
   1911                     <p>View source and contribute on GitHub.</p>
   1912                 </div>
   1913                 <a href="https://github.com/notamitgamer/nct-legacy" target="_blank" class="download-button" style="background-color: #333;">GitHub</a>
   1914             </div>
   1915         </div>
   1916     </div>
   1917 
   1918     <script>
   1919         function switchTab(evt, tabId) {
   1920             // Hide all contents
   1921             document.querySelectorAll('.tab-content').forEach(content => {
   1922                 content.classList.remove('active');
   1923             });
   1924             // Deactivate all buttons
   1925             document.querySelectorAll('.tab-button').forEach(button => {
   1926                 button.classList.remove('active');
   1927             });
   1928 
   1929             // Show current
   1930             document.getElementById(tabId + '-tab-content').classList.add('active');
   1931             evt.currentTarget.classList.add('active');
   1932         }
   1933 
   1934         async function copyToClipboard(btn) {
   1935             const code = document.getElementById('sourceCode').innerText;
   1936             try {
   1937                 await navigator.clipboard.writeText(code);
   1938                 const originalHTML = btn.innerHTML;
   1939                 btn.innerHTML = '<span>✓ Copied!</span>';
   1940                 btn.classList.add('success');
   1941                 
   1942                 setTimeout(() => {
   1943                     btn.innerHTML = originalHTML;
   1944                     btn.classList.remove('success');
   1945                 }, 2000);
   1946             } catch (err) {
   1947                 console.error('Failed to copy code: ', err);
   1948             }
   1949         }
   1950     </script>
   1951 
   1952 </body>
   1953 </html>
© notamitgamer • Site Built: 2026-09-05 01:53:16 UTC • git-mirror commit: c170d72 [view raw info]
Originally created with stagit • modified by notamitgamer
Forked from github.com/notamitgamer/git-mirror