Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"/> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"/> | |
| <title>AxionLab — Scaling Intelligence from Zero</title> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=IBM+Plex+Mono:wght@300;400;500;600&family=DM+Sans:wght@300;400;500&display=swap" rel="stylesheet"> | |
| <style> | |
| :root { | |
| --bg:#070809;--bg2:#0c0e12;--bg3:#111520;--border:rgba(255,255,255,.06); | |
| --border2:rgba(255,255,255,.12);--cyan:#00e5ff;--amber:#ffb300; | |
| --green:#00e676;--red:#ff5252;--text:#d4dbe8;--muted:#5a6480; | |
| --faint:#1e2535;--mono:'IBM Plex Mono',monospace; | |
| --serif:'DM Serif Display',serif;--sans:'DM Sans',sans-serif; | |
| } | |
| *,*::before,*::after{box-sizing:border-box;margin:0;padding:0} | |
| html{scroll-behavior:smooth} | |
| body{font-family:var(--sans);background:var(--bg);color:var(--text);overflow-x:hidden;cursor:none} | |
| .cursor{position:fixed;width:8px;height:8px;background:var(--cyan);border-radius:50%;pointer-events:none;z-index:9999;transform:translate(-50%,-50%);transition:transform .1s,background .2s;mix-blend-mode:screen} | |
| .cursor-ring{position:fixed;width:32px;height:32px;border:1px solid rgba(0,229,255,.4);border-radius:50%;pointer-events:none;z-index:9998;transform:translate(-50%,-50%);transition:transform .18s ease,width .2s,height .2s,border-color .2s} | |
| #particle-canvas{position:fixed;inset:0;pointer-events:none;z-index:0;opacity:.35} | |
| .container{max-width:1100px;margin:0 auto;padding:0 28px;position:relative;z-index:1} | |
| nav{position:fixed;top:0;left:0;right:0;z-index:100;padding:16px 28px;display:flex;align-items:center;gap:40px;border-bottom:1px solid var(--border);background:rgba(7,8,9,.85);backdrop-filter:blur(12px)} | |
| .nav-logo{font-family:var(--mono);font-weight:600;font-size:.9rem;color:#fff;letter-spacing:-.02em;display:flex;align-items:center;gap:8px;text-decoration:none} | |
| .nav-logo-dot{width:8px;height:8px;border-radius:50%;background:var(--cyan);box-shadow:0 0 10px var(--cyan);animation:pulse 2s infinite} | |
| @keyframes pulse{0%,100%{opacity:1}50%{opacity:.4}} | |
| .nav-links{display:flex;gap:28px;margin-left:auto} | |
| .nav-links a{font-family:var(--mono);font-size:.72rem;color:var(--muted);text-decoration:none;letter-spacing:.05em;text-transform:uppercase;transition:color .2s} | |
| .nav-links a:hover{color:var(--cyan)} | |
| .nav-hf{font-family:var(--mono);font-size:.72rem;background:var(--faint);color:var(--cyan);border:1px solid rgba(0,229,255,.2);border-radius:6px;padding:6px 14px;text-decoration:none;transition:background .2s,box-shadow .2s} | |
| .nav-hf:hover{background:rgba(0,229,255,.08);box-shadow:0 0 16px rgba(0,229,255,.15)} | |
| #hero{min-height:100vh;display:flex;flex-direction:column;justify-content:center;padding:120px 28px 80px} | |
| .hero-eyebrow{font-family:var(--mono);font-size:.7rem;font-weight:500;color:var(--cyan);letter-spacing:.2em;text-transform:uppercase;margin-bottom:28px;display:flex;align-items:center;gap:10px} | |
| .hero-eyebrow::before{content:'';display:block;width:32px;height:1px;background:var(--cyan)} | |
| .hero-title{font-family:var(--serif);font-size:clamp(3rem,7vw,6.5rem);line-height:1.05;color:#fff;margin-bottom:32px;max-width:820px} | |
| .hero-title em{font-style:italic;color:var(--cyan)} | |
| .hero-sub{font-size:1.05rem;line-height:1.8;color:var(--muted);max-width:560px;margin-bottom:52px} | |
| .hero-ctas{display:flex;gap:14px;flex-wrap:wrap} | |
| .btn-primary{font-family:var(--mono);font-size:.78rem;font-weight:500;letter-spacing:.04em;background:var(--cyan);color:#070809;border:none;border-radius:8px;padding:13px 28px;cursor:pointer;text-decoration:none;transition:box-shadow .2s,transform .15s;display:inline-flex;align-items:center;gap:8px} | |
| .btn-primary:hover{box-shadow:0 0 28px rgba(0,229,255,.4);transform:translateY(-1px)} | |
| .btn-ghost{font-family:var(--mono);font-size:.78rem;color:var(--text);background:transparent;border:1px solid var(--border2);border-radius:8px;padding:13px 28px;cursor:pointer;text-decoration:none;transition:border-color .2s,color .2s;display:inline-flex;align-items:center;gap:8px} | |
| .btn-ghost:hover{border-color:var(--cyan);color:var(--cyan)} | |
| .hero-stats{margin-top:80px;display:flex;gap:48px;flex-wrap:wrap;padding-top:40px;border-top:1px solid var(--border)} | |
| .stat-num{font-family:var(--mono);font-size:1.8rem;font-weight:600;color:#fff;display:block} | |
| .stat-num span{color:var(--cyan)} | |
| .stat-label{font-size:.72rem;color:var(--muted);font-family:var(--mono);text-transform:uppercase;letter-spacing:.08em} | |
| section{padding:100px 0;position:relative;z-index:1} | |
| .section-tag{font-family:var(--mono);font-size:.65rem;font-weight:500;color:var(--cyan);letter-spacing:.2em;text-transform:uppercase;margin-bottom:16px;display:flex;align-items:center;gap:10px} | |
| .section-tag::before{content:'';display:block;width:24px;height:1px;background:var(--cyan)} | |
| .section-title{font-family:var(--serif);font-size:clamp(2rem,4vw,3.2rem);color:#fff;line-height:1.15;margin-bottom:20px} | |
| .section-sub{font-size:.95rem;color:var(--muted);line-height:1.8;max-width:540px} | |
| .divider{height:1px;background:var(--border);position:relative;overflow:visible} | |
| .divider::after{content:'';position:absolute;left:0;top:-1px;width:80px;height:2px;background:linear-gradient(90deg,var(--cyan),transparent)} | |
| #models{background:var(--bg2)} | |
| .models-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:20px;margin-top:52px} | |
| .model-card{background:var(--bg3);border:1px solid var(--border);border-radius:14px;padding:28px;position:relative;overflow:hidden;transition:border-color .25s,transform .2s,box-shadow .25s} | |
| .model-card::before{content:'';position:absolute;top:0;left:0;right:0;height:2px;background:linear-gradient(90deg,var(--cyan),var(--amber));opacity:0;transition:opacity .25s} | |
| .model-card:hover{border-color:rgba(0,229,255,.25);transform:translateY(-3px);box-shadow:0 20px 40px rgba(0,0,0,.4)} | |
| .model-card:hover::before{opacity:1} | |
| .model-card.upcoming{opacity:.5} | |
| .model-card.upcoming:hover{transform:none;box-shadow:none;border-color:var(--border)} | |
| .model-card.upcoming::before{display:none} | |
| .model-version{font-family:var(--mono);font-size:.65rem;font-weight:600;color:var(--cyan);letter-spacing:.15em;text-transform:uppercase;margin-bottom:12px} | |
| .model-name{font-family:var(--serif);font-size:1.5rem;color:#fff;margin-bottom:10px} | |
| .model-desc{font-size:.82rem;color:var(--muted);line-height:1.7;margin-bottom:20px} | |
| .model-chips{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:22px} | |
| .chip{font-family:var(--mono);font-size:.6rem;font-weight:500;letter-spacing:.05em;text-transform:uppercase;padding:4px 10px;border-radius:999px;border:1px solid var(--border2);color:var(--muted)} | |
| .chip.cyan{border-color:rgba(0,229,255,.3);color:var(--cyan)} | |
| .chip.amber{border-color:rgba(255,179,0,.3);color:var(--amber)} | |
| .chip.green{border-color:rgba(0,230,118,.3);color:var(--green)} | |
| .model-meta{display:flex;justify-content:space-between;align-items:center;padding-top:18px;border-top:1px solid var(--border)} | |
| .model-params{font-family:var(--mono);font-size:.72rem} | |
| .model-params b{color:#fff} | |
| .model-params small{color:var(--muted)} | |
| .model-status{font-family:var(--mono);font-size:.62rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;padding:4px 10px;border-radius:999px} | |
| .model-status.live{background:rgba(0,230,118,.1);color:var(--green);border:1px solid rgba(0,230,118,.25)} | |
| .model-status.next{background:rgba(255,179,0,.08);color:var(--amber);border:1px solid rgba(255,179,0,.2)} | |
| .model-status.planned{background:rgba(90,100,128,.1);color:var(--muted);border:1px solid var(--border)} | |
| .model-link{font-family:var(--mono);font-size:.7rem;color:var(--cyan);text-decoration:none;display:inline-flex;align-items:center;gap:5px;margin-top:16px;transition:gap .2s} | |
| .model-link:hover{gap:9px} | |
| #demo{background:var(--bg)} | |
| .demo-wrapper{margin-top:52px;background:var(--bg2);border:1px solid var(--border);border-radius:16px;overflow:hidden} | |
| .demo-header{display:flex;align-items:center;gap:12px;padding:16px 24px;border-bottom:1px solid var(--border);background:var(--bg3)} | |
| .demo-dots{display:flex;gap:6px} | |
| .demo-dot{width:10px;height:10px;border-radius:50%;background:var(--faint)} | |
| .demo-dot:nth-child(1){background:#ff5f57} | |
| .demo-dot:nth-child(2){background:#febc2e} | |
| .demo-dot:nth-child(3){background:#28c840} | |
| .demo-title{font-family:var(--mono);font-size:.72rem;color:var(--muted);margin-left:4px} | |
| .demo-badge{margin-left:auto;font-family:var(--mono);font-size:.6rem;color:var(--green);background:rgba(0,230,118,.08);border:1px solid rgba(0,230,118,.2);border-radius:999px;padding:3px 10px} | |
| .demo-body{display:grid;grid-template-columns:1fr 1fr;min-height:320px} | |
| .demo-input-pane,.demo-output-pane{padding:28px} | |
| .demo-input-pane{border-right:1px solid var(--border)} | |
| .demo-pane-label{font-family:var(--mono);font-size:.62rem;color:var(--muted);text-transform:uppercase;letter-spacing:.12em;margin-bottom:12px;display:flex;align-items:center;gap:8px} | |
| .demo-pane-label::after{content:'';flex:1;height:1px;background:var(--border)} | |
| #demo-prompt{width:100%;background:var(--bg);border:1px solid var(--border);border-radius:10px;color:var(--text);font-family:var(--mono);font-size:.8rem;padding:14px 16px;resize:vertical;min-height:120px;outline:none;line-height:1.6;transition:border-color .2s} | |
| #demo-prompt:focus{border-color:rgba(0,229,255,.3)} | |
| .demo-controls{display:flex;gap:10px;margin-top:14px;align-items:center;flex-wrap:wrap} | |
| .demo-ctrl{display:flex;align-items:center;gap:6px;font-family:var(--mono);font-size:.62rem;color:var(--muted)} | |
| .demo-ctrl input[type=range]{-webkit-appearance:none;height:2px;width:60px;background:var(--border2);border-radius:2px;outline:none} | |
| .demo-ctrl input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:10px;height:10px;border-radius:50%;background:var(--cyan);cursor:pointer} | |
| .demo-ctrl span{color:var(--cyan);min-width:24px} | |
| #demo-run{margin-left:auto;font-family:var(--mono);font-size:.72rem;font-weight:500;background:var(--cyan);color:#070809;border:none;border-radius:8px;padding:9px 20px;cursor:pointer;transition:box-shadow .2s;display:flex;align-items:center;gap:6px} | |
| #demo-run:hover{box-shadow:0 0 20px rgba(0,229,255,.35)} | |
| #demo-run:disabled{opacity:.45;cursor:not-allowed} | |
| .demo-output{font-family:var(--mono);font-size:.8rem;color:var(--text);line-height:1.8;min-height:120px;word-break:break-word;white-space:pre-wrap} | |
| .demo-output.empty{color:var(--muted);font-style:italic} | |
| .demo-cursor{display:inline-block;width:2px;height:1em;background:var(--cyan);vertical-align:text-bottom;animation:blink .7s step-end infinite;margin-left:1px} | |
| @keyframes blink{0%,100%{opacity:1}50%{opacity:0}} | |
| .demo-footer{padding:14px 28px;border-top:1px solid var(--border);display:flex;align-items:center;gap:10px;font-family:var(--mono);font-size:.62rem;color:var(--muted)} | |
| #demo-stats{margin-left:auto;color:var(--cyan)} | |
| #blog{background:var(--bg2)} | |
| .blog-grid{display:grid;grid-template-columns:1fr 1fr;gap:24px;margin-top:52px} | |
| .blog-card{background:var(--bg3);border:1px solid var(--border);border-radius:14px;padding:32px;transition:border-color .25s,transform .2s;cursor:pointer;text-decoration:none;display:block;color:inherit} | |
| .blog-card:hover{border-color:rgba(0,229,255,.2);transform:translateY(-2px)} | |
| .blog-card.featured{grid-column:1/-1;display:grid;grid-template-columns:1fr 1fr;gap:40px;align-items:center} | |
| .blog-date{font-family:var(--mono);font-size:.62rem;color:var(--muted);margin-bottom:14px;display:flex;align-items:center;gap:8px} | |
| .blog-tag-pill{font-family:var(--mono);font-size:.55rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;padding:2px 8px;border-radius:4px;background:rgba(0,229,255,.08);color:var(--cyan);border:1px solid rgba(0,229,255,.18)} | |
| .blog-tag-pill.amber{background:rgba(255,179,0,.08);color:var(--amber);border-color:rgba(255,179,0,.18)} | |
| .blog-title{font-family:var(--serif);font-size:1.35rem;color:#fff;line-height:1.3;margin-bottom:12px} | |
| .blog-excerpt{font-size:.82rem;color:var(--muted);line-height:1.75} | |
| .blog-read-more{font-family:var(--mono);font-size:.68rem;color:var(--cyan);margin-top:20px;display:inline-flex;align-items:center;gap:5px} | |
| .blog-visual{background:var(--faint);border-radius:10px;height:180px;display:flex;align-items:center;justify-content:center;overflow:hidden} | |
| .blog-visual-inner{font-family:var(--mono);font-size:.65rem;color:var(--cyan);opacity:.7;line-height:1.8;padding:16px;white-space:pre;width:100%} | |
| #docs{background:var(--bg)} | |
| .docs-layout{display:grid;grid-template-columns:220px 1fr;gap:40px;margin-top:52px;align-items:start} | |
| .docs-sidebar{position:sticky;top:90px} | |
| .docs-nav-group{margin-bottom:28px} | |
| .docs-nav-label{font-family:var(--mono);font-size:.58rem;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.12em;margin-bottom:10px} | |
| .docs-nav-item{display:block;font-family:var(--mono);font-size:.74rem;color:var(--muted);padding:6px 0 6px 14px;border-left:2px solid var(--border);text-decoration:none;transition:color .15s,border-color .15s;cursor:pointer} | |
| .docs-nav-item:hover,.docs-nav-item.active{color:var(--cyan);border-left-color:var(--cyan)} | |
| .doc-section{display:none} | |
| .doc-section.active{display:block} | |
| .doc-h1{font-family:var(--serif);font-size:2rem;color:#fff;margin-bottom:16px} | |
| .doc-h2{font-family:var(--serif);font-size:1.3rem;color:#fff;margin:32px 0 12px} | |
| .doc-p{font-size:.9rem;color:var(--muted);line-height:1.85;margin-bottom:16px} | |
| .doc-code{background:var(--bg2);border:1px solid var(--border);border-radius:10px;padding:20px 24px;margin:16px 0;font-family:var(--mono);font-size:.78rem;color:var(--text);line-height:1.8;overflow-x:auto;position:relative} | |
| .comment{color:var(--muted)}.kw{color:var(--cyan)}.str{color:var(--amber)}.fn{color:var(--green)} | |
| .copy-btn{position:absolute;top:10px;right:10px;font-family:var(--mono);font-size:.58rem;color:var(--muted);background:var(--faint);border:1px solid var(--border);border-radius:5px;padding:3px 8px;cursor:pointer;transition:color .2s,border-color .2s} | |
| .copy-btn:hover{color:var(--cyan);border-color:rgba(0,229,255,.3)} | |
| .doc-table{width:100%;border-collapse:collapse;margin:16px 0;font-family:var(--mono);font-size:.75rem} | |
| .doc-table th{text-align:left;color:var(--muted);font-weight:500;padding:10px 14px;border-bottom:1px solid var(--border);text-transform:uppercase;font-size:.6rem;letter-spacing:.1em} | |
| .doc-table td{padding:10px 14px;border-bottom:1px solid var(--border);color:var(--text);vertical-align:top} | |
| .doc-table tr:last-child td{border-bottom:none} | |
| .doc-table td:first-child{color:var(--cyan)} | |
| #roadmap{background:var(--bg2)} | |
| .roadmap-track{position:relative;margin-top:60px;padding-left:40px} | |
| .roadmap-track::before{content:'';position:absolute;left:0;top:0;bottom:0;width:1px;background:var(--border)} | |
| .roadmap-item{position:relative;padding:28px 0 28px 48px;border-bottom:1px solid var(--border)} | |
| .roadmap-item:last-child{border-bottom:none} | |
| .roadmap-item::before{content:'';position:absolute;left:-5px;top:36px;width:11px;height:11px;border-radius:50%;background:var(--bg2);border:2px solid var(--border)} | |
| .roadmap-item.done::before{background:var(--green);border-color:var(--green)} | |
| .roadmap-item.next::before{background:var(--amber);border-color:var(--amber);box-shadow:0 0 10px rgba(255,179,0,.5);animation:pulse 1.5s infinite} | |
| .roadmap-meta{display:flex;align-items:center;gap:14px;margin-bottom:10px;flex-wrap:wrap} | |
| .roadmap-version{font-family:var(--mono);font-size:.75rem;font-weight:600;color:#fff} | |
| .roadmap-date{font-family:var(--mono);font-size:.65rem;color:var(--muted)} | |
| .roadmap-badge{font-family:var(--mono);font-size:.58rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;padding:3px 9px;border-radius:4px} | |
| .roadmap-badge.done{background:rgba(0,230,118,.1);color:var(--green)} | |
| .roadmap-badge.next{background:rgba(255,179,0,.1);color:var(--amber)} | |
| .roadmap-badge.planned{background:var(--faint);color:var(--muted)} | |
| .roadmap-title{font-family:var(--serif);font-size:1.2rem;color:#fff;margin-bottom:8px} | |
| .roadmap-desc{font-size:.83rem;color:var(--muted);line-height:1.75;max-width:620px} | |
| .roadmap-chips{display:flex;gap:6px;flex-wrap:wrap;margin-top:12px} | |
| footer{background:var(--bg3);border-top:1px solid var(--border);padding:60px 0 40px;position:relative;z-index:1} | |
| .footer-grid{display:grid;grid-template-columns:2fr 1fr 1fr;gap:48px;margin-bottom:48px} | |
| .footer-brand-name{font-family:var(--mono);font-size:1rem;font-weight:600;color:#fff;display:flex;align-items:center;gap:8px;margin-bottom:12px} | |
| .footer-brand-desc{font-size:.82rem;color:var(--muted);line-height:1.8;max-width:300px} | |
| .footer-col-title{font-family:var(--mono);font-size:.62rem;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.1em;margin-bottom:16px} | |
| .footer-links{list-style:none;display:flex;flex-direction:column;gap:10px} | |
| .footer-links a{font-size:.82rem;color:var(--muted);text-decoration:none;transition:color .2s} | |
| .footer-links a:hover{color:var(--cyan)} | |
| .footer-bottom{padding-top:28px;border-top:1px solid var(--border);display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:12px} | |
| .footer-copy{font-family:var(--mono);font-size:.65rem;color:var(--muted)} | |
| .reveal{opacity:0;transform:translateY(24px);transition:opacity .6s ease,transform .6s ease} | |
| .reveal.visible{opacity:1;transform:translateY(0)} | |
| @media(max-width:768px){ | |
| .nav-links{display:none} | |
| .demo-body{grid-template-columns:1fr} | |
| .demo-input-pane{border-right:none;border-bottom:1px solid var(--border)} | |
| .blog-grid{grid-template-columns:1fr} | |
| .blog-card.featured{grid-template-columns:1fr} | |
| .blog-visual{display:none} | |
| .docs-layout{grid-template-columns:1fr} | |
| .docs-sidebar{display:none} | |
| .footer-grid{grid-template-columns:1fr} | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="cursor" id="cursor"></div> | |
| <div class="cursor-ring" id="cursor-ring"></div> | |
| <canvas id="particle-canvas"></canvas> | |
| <nav> | |
| <a href="#hero" class="nav-logo"><div class="nav-logo-dot"></div>AxionLab</a> | |
| <div class="nav-links"> | |
| <a href="#models">Models</a> | |
| <a href="#demo">Demo</a> | |
| <a href="#blog">Blog</a> | |
| <a href="#docs">Docs</a> | |
| <a href="#roadmap">Roadmap</a> | |
| </div> | |
| <a href="https://huggingface.co/AxionLab-Co" target="_blank" class="nav-hf">🤗 HuggingFace</a> | |
| </nav> | |
| <section id="hero"> | |
| <div class="container"> | |
| <div class="hero-eyebrow">AxionLab Research</div> | |
| <h1 class="hero-title">Scaling <em>Intelligence</em><br>from Zero</h1> | |
| <p class="hero-sub">Building architectures from scratch — MLA, MoE, auxiliary-loss-free load balancing — scaled progressively from 344k to 100M+ parameters. All weights open. All code open.</p> | |
| <div class="hero-ctas"> | |
| <a href="#models" class="btn-primary">↓ Explore Models</a> | |
| <a href="https://huggingface.co/AxionLab-Co" target="_blank" class="btn-ghost">View on HuggingFace →</a> | |
| </div> | |
| <div class="hero-stats"> | |
| <div class="stat-item"><span class="stat-num">344<span>k</span></span><span class="stat-label">Parameters — Axion1</span></div> | |
| <div class="stat-item"><span class="stat-num">~160<span>k</span></span><span class="stat-label">Active per token</span></div> | |
| <div class="stat-item"><span class="stat-num">1<span>,</span>100</span><span class="stat-label">Tokens/sec CPU</span></div> | |
| <div class="stat-item"><span class="stat-num">100<span>%</span></span><span class="stat-label">Open Source</span></div> | |
| </div> | |
| </div> | |
| </section> | |
| <div class="container"><div class="divider"></div></div> | |
| <section id="models"> | |
| <div class="container"> | |
| <div class="section-tag">Models</div> | |
| <h2 class="section-title">The Axion Series</h2> | |
| <p class="section-sub">Each version scales the same architecture — same MLA, same MoE — with increasing capacity and capability.</p> | |
| <div class="models-grid"> | |
| <div class="model-card reveal"> | |
| <div class="model-version">v1.0 — Released</div> | |
| <div class="model-name">Axion1</div> | |
| <div class="model-desc">Proof-of-concept: DeepSeek-V3 architecture at extreme miniaturization. Trained on GSM8K in 115 minutes on a Ryzen 5 CPU.</div> | |
| <div class="model-chips"><span class="chip cyan">MLA</span><span class="chip cyan">MoE</span><span class="chip">RoPE</span><span class="chip">SwiGLU</span><span class="chip amber">CPU</span></div> | |
| <div class="model-meta"> | |
| <div class="model-params"><b>344k</b> <small>total · ~160k active</small></div> | |
| <div class="model-status live">● Live</div> | |
| </div> | |
| <a href="https://huggingface.co/AxionLab-Co/Axion1-350k-A250k" target="_blank" class="model-link">View on HuggingFace →</a> | |
| </div> | |
| <div class="model-card upcoming reveal"> | |
| <div class="model-version">v0.2 — Coming Soon</div> | |
| <div class="model-name">Axion1-v0.2</div> | |
| <div class="model-desc">Same architecture, 4× the capacity. Expanded vocabulary and noticeably more coherent language generation.</div> | |
| <div class="model-chips"><span class="chip cyan">MLA</span><span class="chip cyan">MoE</span><span class="chip">d_model 128</span><span class="chip">6 layers</span></div> | |
| <div class="model-meta"> | |
| <div class="model-params"><b>~1.5M</b> <small>total · ~800k active</small></div> | |
| <div class="model-status next">⟳ Next</div> | |
| </div> | |
| </div> | |
| <div class="model-card upcoming reveal"> | |
| <div class="model-version">v0.3 — Planned</div> | |
| <div class="model-name">Axion1-v0.3</div> | |
| <div class="model-desc">First model expected to produce grammatically coherent multi-sentence responses. Scaling laws in action.</div> | |
| <div class="model-chips"><span class="chip cyan">MLA</span><span class="chip cyan">MoE</span><span class="chip">d_model 256</span></div> | |
| <div class="model-meta"> | |
| <div class="model-params"><b>~6M</b> <small>total</small></div> | |
| <div class="model-status planned">Planned</div> | |
| </div> | |
| </div> | |
| <div class="model-card upcoming reveal"> | |
| <div class="model-version">v0.4-0.5 — Future</div> | |
| <div class="model-name">Axion1-v0.4 / Axion1-v0.5</div> | |
| <div class="model-desc">Scaling to 24M and 100M parameters. Instruction tuning and multi-language support planned.</div> | |
| <div class="model-chips"><span class="chip">24M → 100M</span><span class="chip amber">Multilingual</span></div> | |
| <div class="model-meta"> | |
| <div class="model-params"><b>24M–100M</b> <small>params</small></div> | |
| <div class="model-status planned">Planned</div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <div class="container"><div class="divider"></div></div> | |
| <section id="demo"> | |
| <div class="container"> | |
| <div class="section-tag">Live Demo</div> | |
| <h2 class="section-title">Try Axion1</h2> | |
| <p class="section-sub">Simulated demo — press Run to see example outputs from Axion1. Connect to real inference by pointing to your server.</p> | |
| <div class="demo-wrapper reveal"> | |
| <div class="demo-header"> | |
| <div class="demo-dots"><div class="demo-dot"></div><div class="demo-dot"></div><div class="demo-dot"></div></div> | |
| <span class="demo-title">Axion1-350k-A250k — inference</span> | |
| <span class="demo-badge">● model loaded</span> | |
| </div> | |
| <div class="demo-body"> | |
| <div class="demo-input-pane"> | |
| <div class="demo-pane-label">Prompt</div> | |
| <textarea id="demo-prompt" placeholder="Type a math question..."># Pergunta: | |
| Quanto é 5 + 3? | |
| -- | |
| # Resposta:</textarea> | |
| <div class="demo-controls"> | |
| <div class="demo-ctrl"> | |
| <label>Temp</label> | |
| <input type="range" id="d-temp" min="0.5" max="1.5" step="0.1" value="0.9" oninput="document.getElementById('d-temp-v').textContent=this.value"> | |
| <span id="d-temp-v">0.9</span> | |
| </div> | |
| <div class="demo-ctrl"> | |
| <label>Tokens</label> | |
| <input type="range" id="d-tok" min="20" max="120" step="10" value="60" oninput="document.getElementById('d-tok-v').textContent=this.value"> | |
| <span id="d-tok-v">60</span> | |
| </div> | |
| <button id="demo-run" onclick="runDemo()">▶ Run</button> | |
| </div> | |
| </div> | |
| <div class="demo-output-pane"> | |
| <div class="demo-pane-label">Output</div> | |
| <div class="demo-output empty" id="demo-output">Response will appear here...</div> | |
| </div> | |
| </div> | |
| <div class="demo-footer"> | |
| <span>Axion1-350k · DeepSeek-V3 arch · CPU inference</span> | |
| <span id="demo-stats"></span> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <div class="container"><div class="divider"></div></div> | |
| <section id="blog"> | |
| <div class="container"> | |
| <div class="section-tag">Blog</div> | |
| <h2 class="section-title">Updates & Research</h2> | |
| <div class="blog-grid"> | |
| <div class="blog-card featured reveal"> | |
| <div> | |
| <div class="blog-date"><span class="blog-tag-pill">Launch</span> March 8, 2025</div> | |
| <div class="blog-title">We built DeepSeek-V3 architecture from scratch in one afternoon</div> | |
| <div class="blog-excerpt">Starting from the technical report (arXiv:2412.19437), we implemented Multi-head Latent Attention, DeepSeekMoE with auxiliary-loss-free load balancing, RoPE, RMSNorm, and SwiGLU from zero — no pretrained weights, no distillation. Axion1 was trained in 115 minutes on a Ryzen 5 5600G CPU.</div> | |
| <div class="blog-read-more">Read more →</div> | |
| </div> | |
| <div class="blog-visual"> | |
| <div class="blog-visual-inner">val_loss: 6.49 → epoch 1 | |
| val_loss: 4.59 → epoch 2 | |
| val_loss: 4.30 → epoch 3 | |
| val_loss: 3.88 → epoch 5 | |
| val_loss: 3.66 → epoch 7 | |
| val_loss: 3.54 → epoch 9 | |
| val_loss: ~3.2 → epoch 20 | |
| ✓ saved: model.safetensors | |
| ✓ active params: ~160k/token</div> | |
| </div> | |
| </div> | |
| <div class="blog-card reveal"> | |
| <div class="blog-date"><span class="blog-tag-pill amber">Architecture</span> March 8, 2025</div> | |
| <div class="blog-title">Why MLA makes small models faster on CPU</div> | |
| <div class="blog-excerpt">Multi-head Latent Attention compresses KV into a low-rank latent space, reducing KV cache memory ~8x vs standard MHA. At 344k parameters this means the entire KV cache fits in L2 cache on the Ryzen 5.</div> | |
| <div class="blog-read-more">Read more →</div> | |
| </div> | |
| <div class="blog-card reveal"> | |
| <div class="blog-date"><span class="blog-tag-pill">Scaling</span> Coming Soon</div> | |
| <div class="blog-title">Axion2: what happens at 1.5M parameters?</div> | |
| <div class="blog-excerpt">The jump from 344k to 1.5M is not linear — empirically, this is where grammatical structure starts emerging. We document the full training run and compare outputs side by side with Axion1.</div> | |
| <div class="blog-read-more">Coming soon →</div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <div class="container"><div class="divider"></div></div> | |
| <section id="docs"> | |
| <div class="container"> | |
| <div class="section-tag">Documentation</div> | |
| <h2 class="section-title">Get Started</h2> | |
| <div class="docs-layout"> | |
| <div class="docs-sidebar"> | |
| <div class="docs-nav-group"> | |
| <div class="docs-nav-label">Quickstart</div> | |
| <span class="docs-nav-item active" onclick="showDoc('install',this)">Installation</span> | |
| <span class="docs-nav-item" onclick="showDoc('inference',this)">Inference</span> | |
| <span class="docs-nav-item" onclick="showDoc('chat',this)">Chat Interface</span> | |
| </div> | |
| <div class="docs-nav-group"> | |
| <div class="docs-nav-label">Training</div> | |
| <span class="docs-nav-item" onclick="showDoc('dataset',this)">Dataset</span> | |
| <span class="docs-nav-item" onclick="showDoc('train',this)">Training</span> | |
| </div> | |
| <div class="docs-nav-group"> | |
| <div class="docs-nav-label">Architecture</div> | |
| <span class="docs-nav-item" onclick="showDoc('config',this)">Config Reference</span> | |
| <span class="docs-nav-item" onclick="showDoc('arch',this)">MLA & MoE</span> | |
| </div> | |
| </div> | |
| <div class="docs-content"> | |
| <div class="doc-section active" id="doc-install"> | |
| <h1 class="doc-h1">Installation</h1> | |
| <p class="doc-p">Axion models require PyTorch, Transformers, and Safetensors. No GPU required.</p> | |
| <div class="doc-code"><button class="copy-btn" onclick="copyCode(this)">copy</button><span class="kw">pip</span> install torch transformers safetensors flask</div> | |
| <p class="doc-p">Clone the model repository:</p> | |
| <div class="doc-code"><button class="copy-btn" onclick="copyCode(this)">copy</button>git clone https://huggingface.co/AxionLab-Co/Axion1-350k-A250k | |
| <span class="kw">cd</span> Axion1-350k-A250k</div> | |
| </div> | |
| <div class="doc-section" id="doc-inference"> | |
| <h1 class="doc-h1">Inference</h1> | |
| <p class="doc-p">Load with AutoModelForCausalLM. The custom BPE tokenizer must be loaded separately.</p> | |
| <div class="doc-code"><button class="copy-btn" onclick="copyCode(this)">copy</button><span class="kw">from</span> transformers <span class="kw">import</span> AutoModelForCausalLM, LogitsProcessor, LogitsProcessorList | |
| <span class="kw">from</span> tokenizer <span class="kw">import</span> BPETokenizer | |
| <span class="kw">import</span> torch | |
| model = AutoModelForCausalLM.<span class="fn">from_pretrained</span>( | |
| <span class="str">"AxionLab-Co/Axion1-350k-A250k"</span>, trust_remote_code=<span class="kw">True</span> | |
| ) | |
| model.<span class="fn">eval</span>() | |
| tok = BPETokenizer.<span class="fn">load</span>(<span class="str">"model.vocab"</span>, <span class="str">"model.model"</span>) | |
| <span class="kw">class</span> <span class="fn">MinNewTokens</span>(LogitsProcessor): | |
| <span class="kw">def</span> <span class="fn">__init__</span>(self,n,eos,pad): self.n=n;self.bad=[eos,pad];self.i=0 | |
| <span class="kw">def</span> <span class="fn">__call__</span>(self,ids,scores): | |
| <span class="kw">if</span> self.i<self.n: | |
| <span class="kw">for</span> b <span class="kw">in</span> self.bad: scores[:,b]=float(<span class="str">"-inf"</span>) | |
| self.i+=1; <span class="kw">return</span> scores | |
| prompt = <span class="str">"# Pergunta:\nQuanto e 5 + 3?\n--\n# Resposta:\n"</span> | |
| ids = tok.<span class="fn">encode</span>(prompt, add_bos=<span class="kw">True</span>, add_eos=<span class="kw">False</span>) | |
| out = model.<span class="fn">generate</span>(torch.<span class="fn">tensor</span>([ids]), max_new_tokens=80, | |
| temperature=0.9, do_sample=<span class="kw">True</span>, use_cache=<span class="kw">False</span>, | |
| logits_processor=LogitsProcessorList([<span class="fn">MinNewTokens</span>(5,tok.token2id[<span class="str">"<eos>"</span>],tok.token2id[<span class="str">"<pad>"</span>])]) | |
| ) | |
| <span class="fn">print</span>(tok.<span class="fn">decode</span>(out[0][len(ids):].tolist()))</div> | |
| </div> | |
| <div class="doc-section" id="doc-chat"> | |
| <h1 class="doc-h1">Chat Interface</h1> | |
| <p class="doc-p">Axion ships with a built-in Flask server and dark-themed HTML interface.</p> | |
| <div class="doc-code"><button class="copy-btn" onclick="copyCode(this)">copy</button>python chat.py | |
| <span class="comment"># Open http://localhost:5000</span></div> | |
| <div class="doc-code"><button class="copy-btn" onclick="copyCode(this)">copy</button>python chat.py --port 8080 --host 0.0.0.0</div> | |
| </div> | |
| <div class="doc-section" id="doc-dataset"> | |
| <h1 class="doc-h1">Dataset Preparation</h1> | |
| <div class="doc-code"><button class="copy-btn" onclick="copyCode(this)">copy</button><span class="comment"># Download GSM8K (requires internet)</span> | |
| python convert.py | |
| <span class="comment"># Synthetic math data (no internet needed)</span> | |
| python convert.py --synthetic --max 2000</div> | |
| </div> | |
| <div class="doc-section" id="doc-train"> | |
| <h1 class="doc-h1">Training</h1> | |
| <div class="doc-code"><button class="copy-btn" onclick="copyCode(this)">copy</button><span class="comment"># 1. Train tokenizer</span> | |
| python tokenizer.py | |
| <span class="comment"># 2. Train model</span> | |
| python train.py --epochs 20 --batch-size 8 --grad-accum 4 | |
| <span class="comment"># Resume interrupted training</span> | |
| python train.py --resume --epochs 20</div> | |
| <p class="doc-p">Expected: ~1,000 tok/s · ~330s/epoch · ~115 min total on Ryzen 5 5600G.</p> | |
| </div> | |
| <div class="doc-section" id="doc-config"> | |
| <h1 class="doc-h1">Config Reference</h1> | |
| <table class="doc-table"> | |
| <tr><th>Key</th><th>Axion1</th><th>Description</th></tr> | |
| <tr><td>d_model</td><td>64</td><td>Embedding dimension</td></tr> | |
| <tr><td>n_layers</td><td>4</td><td>Transformer blocks</td></tr> | |
| <tr><td>kv_lora_rank</td><td>8</td><td>KV compression rank (MLA)</td></tr> | |
| <tr><td>n_routed_experts</td><td>4</td><td>Expert pool size (MoE)</td></tr> | |
| <tr><td>n_active_experts</td><td>2</td><td>Experts activated per token</td></tr> | |
| <tr><td>vocab_size</td><td>1024</td><td>BPE vocabulary size</td></tr> | |
| <tr><td>max_seq_len</td><td>512</td><td>Maximum context length</td></tr> | |
| </table> | |
| </div> | |
| <div class="doc-section" id="doc-arch"> | |
| <h1 class="doc-h1">MLA & MoE</h1> | |
| <h2 class="doc-h2">Multi-head Latent Attention</h2> | |
| <p class="doc-p">MLA compresses KV into a shared latent vector of rank kv_lora_rank, then expands back. This reduces KV cache from O(n·d) to O(n·r) where r ≪ d — critical for CPU performance.</p> | |
| <h2 class="doc-h2">DeepSeekMoE</h2> | |
| <p class="doc-p">Each FFN is replaced by a mixture of experts: shared experts always process every token, plus top-K routed experts selected via sigmoid gating with dynamic bias for load balancing — no auxiliary loss needed.</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <div class="container"><div class="divider"></div></div> | |
| <section id="roadmap"> | |
| <div class="container"> | |
| <div class="section-tag">Roadmap</div> | |
| <h2 class="section-title">Where We're Going</h2> | |
| <p class="section-sub">Every Axion release is a scaling experiment. Same architecture, increasing capacity.</p> | |
| <div class="roadmap-track"> | |
| <div class="roadmap-item done reveal"> | |
| <div class="roadmap-meta"><span class="roadmap-version">Axion1-v0.1 — 344k params</span><span class="roadmap-date">March 2025</span><span class="roadmap-badge done">Released</span></div> | |
| <div class="roadmap-title">Proof of Architecture</div> | |
| <div class="roadmap-desc">Full DeepSeek-V3 pipeline from scratch. MLA + MoE + BPE tokenizer + HuggingFace integration. Trained on GSM8K in 115 minutes on CPU.</div> | |
| <div class="roadmap-chips"><span class="chip cyan">MLA</span><span class="chip cyan">MoE</span><span class="chip">GSM8K</span><span class="chip green">HuggingFace</span></div> | |
| </div> | |
| <div class="roadmap-item next reveal"> | |
| <div class="roadmap-meta"><span class="roadmap-version">Axion1-v0.2 — ~1.5M params</span><span class="roadmap-date">Coming Soon</span><span class="roadmap-badge next">In Progress</span></div> | |
| <div class="roadmap-title">First Coherent Sentences</div> | |
| <div class="roadmap-desc">d_model 128, 6 layers, expanded vocab. Expected to produce grammatically structured responses. Full training log will be published.</div> | |
| <div class="roadmap-chips"><span class="chip">d_model 128</span><span class="chip">6 layers</span><span class="chip amber">Larger vocab</span></div> | |
| </div> | |
| <div class="roadmap-item reveal"> | |
| <div class="roadmap-meta"><span class="roadmap-version">Axion1-v0.3 — ~6M params</span><span class="roadmap-badge planned">Planned</span></div> | |
| <div class="roadmap-title">Reliable Math Reasoning</div> | |
| <div class="roadmap-desc">d_model 256. Consistent step-by-step reasoning on arithmetic. Broader dataset planned.</div> | |
| <div class="roadmap-chips"><span class="chip">d_model 256</span><span class="chip amber">Multi-dataset</span></div> | |
| </div> | |
| <div class="roadmap-item reveal"> | |
| <div class="roadmap-meta"><span class="roadmap-version">Axion1-v0.4 — ~24M params</span><span class="roadmap-badge planned">Planned</span></div> | |
| <div class="roadmap-title">Instruction Following</div> | |
| <div class="roadmap-desc">First Axion with instruction tuning. Target: answer general questions in Portuguese and English.</div> | |
| <div class="roadmap-chips"><span class="chip">Instruction SFT</span><span class="chip amber">PT + EN</span></div> | |
| </div> | |
| <div class="roadmap-item reveal"> | |
| <div class="roadmap-meta"><span class="roadmap-version">Axion1-v0.5 — ~100M params</span><span class="roadmap-badge planned">Planned</span></div> | |
| <div class="roadmap-title">General Purpose</div> | |
| <div class="roadmap-desc">The flagship. Real conversation, multi-turn context, and a full evaluation suite.</div> | |
| <div class="roadmap-chips"><span class="chip">100M</span><span class="chip cyan">Multi-turn</span><span class="chip amber">Eval suite</span></div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <footer> | |
| <div class="container"> | |
| <div class="footer-grid"> | |
| <div> | |
| <div class="footer-brand-name"><div class="nav-logo-dot"></div>AxionLab</div> | |
| <div class="footer-brand-desc">Open research lab building language model architectures from scratch. Everything is public — weights, code, training logs.</div> | |
| </div> | |
| <div> | |
| <div class="footer-col-title">Models</div> | |
| <ul class="footer-links"> | |
| <li><a href="https://huggingface.co/AxionLab-Co/Axion1-350k-A250k" target="_blank">Axion1 — 344k</a></li> | |
| <li><a href="#">Axion1-v0.2 — 1.5M (soon)</a></li> | |
| <li><a href="#">Axion1-v0.3 — 6M (planned)</a></li> | |
| </ul> | |
| </div> | |
| <div> | |
| <div class="footer-col-title">Links</div> | |
| <ul class="footer-links"> | |
| <li><a href="https://huggingface.co/AxionLab-Co" target="_blank">HuggingFace</a></li> | |
| <li><a href="https://arxiv.org/abs/2412.19437" target="_blank">DeepSeek-V3 Paper</a></li> | |
| <li><a href="https://huggingface.co/datasets/openai/gsm8k" target="_blank">GSM8K Dataset</a></li> | |
| </ul> | |
| </div> | |
| </div> | |
| <div class="footer-bottom"> | |
| <span class="footer-copy">© 2026 AxionLab · MIT License · Built with PyTorch</span> | |
| <span class="footer-copy">Made with ⚡ from scratch</span> | |
| </div> | |
| </div> | |
| </footer> | |
| <script> | |
| const cursor=document.getElementById('cursor'),ring=document.getElementById('cursor-ring'); | |
| let mx=0,my=0,rx=0,ry=0; | |
| document.addEventListener('mousemove',e=>{mx=e.clientX;my=e.clientY;cursor.style.left=mx+'px';cursor.style.top=my+'px';}); | |
| (function a(){rx+=(mx-rx)*.12;ry+=(my-ry)*.12;ring.style.left=rx+'px';ring.style.top=ry+'px';requestAnimationFrame(a);})(); | |
| document.querySelectorAll('a,button,.model-card,.blog-card,.docs-nav-item').forEach(el=>{ | |
| el.addEventListener('mouseenter',()=>{cursor.style.transform='translate(-50%,-50%) scale(2)';ring.style.width='48px';ring.style.height='48px';ring.style.borderColor='rgba(0,229,255,.7)';}); | |
| el.addEventListener('mouseleave',()=>{cursor.style.transform='translate(-50%,-50%) scale(1)';ring.style.width='32px';ring.style.height='32px';ring.style.borderColor='rgba(0,229,255,.4)';}); | |
| }); | |
| const canvas=document.getElementById('particle-canvas'),ctx=canvas.getContext('2d'); | |
| let W,H,particles=[]; | |
| function resize(){W=canvas.width=window.innerWidth;H=canvas.height=window.innerHeight;} | |
| resize();window.addEventListener('resize',resize); | |
| class P{constructor(){this.reset();}reset(){this.x=Math.random()*W;this.y=Math.random()*H;this.vx=(Math.random()-.5)*.3;this.vy=(Math.random()-.5)*.3;this.r=Math.random()*1.5+.3;this.a=Math.random()*.5+.1;this.c=Math.random()>.7?'#ffb300':'#00e5ff';}update(){this.x+=this.vx;this.y+=this.vy;if(this.x<0||this.x>W||this.y<0||this.y>H)this.reset();}draw(){ctx.beginPath();ctx.arc(this.x,this.y,this.r,0,Math.PI*2);ctx.fillStyle=this.c;ctx.globalAlpha=this.a;ctx.fill();}} | |
| for(let i=0;i<80;i++)particles.push(new P()); | |
| (function ap(){ctx.clearRect(0,0,W,H); | |
| for(let i=0;i<particles.length;i++)for(let j=i+1;j<particles.length;j++){const dx=particles[i].x-particles[j].x,dy=particles[i].y-particles[j].y,d=Math.sqrt(dx*dx+dy*dy);if(d<100){ctx.beginPath();ctx.moveTo(particles[i].x,particles[i].y);ctx.lineTo(particles[j].x,particles[j].y);ctx.strokeStyle='#00e5ff';ctx.globalAlpha=(1-d/100)*.08;ctx.lineWidth=.5;ctx.stroke();}} | |
| particles.forEach(p=>{p.update();p.draw();});requestAnimationFrame(ap);})(); | |
| const obs=new IntersectionObserver(entries=>entries.forEach(e=>{if(e.isIntersecting)e.target.classList.add('visible');}),{threshold:.12}); | |
| document.querySelectorAll('.reveal').forEach(el=>obs.observe(el)); | |
| function showDoc(id,el){ | |
| document.querySelectorAll('.doc-section').forEach(s=>s.classList.remove('active')); | |
| document.querySelectorAll('.docs-nav-item').forEach(i=>i.classList.remove('active')); | |
| document.getElementById('doc-'+id).classList.add('active'); | |
| el.classList.add('active'); | |
| } | |
| function copyCode(btn){ | |
| const t=btn.parentElement.innerText.replace(/^copy\n/,'').trim(); | |
| navigator.clipboard.writeText(t).then(()=>{btn.textContent='copied!';setTimeout(()=>btn.textContent='copy',1500);}); | |
| } | |
| async function runDemo(){ | |
| const btn=document.getElementById('demo-run'),out=document.getElementById('demo-output'),stats=document.getElementById('demo-stats'); | |
| btn.disabled=true;btn.textContent='⟳ Running'; | |
| out.classList.remove('empty');out.innerHTML='<span class="demo-cursor"></span>';stats.textContent=''; | |
| const t0=Date.now(); | |
| const responses=["So, we have 5 + 3 = 8 total. The answer is 8.","João has 3 more cans. Total = 2 * 6 + 3 = 15 items.","The total cost is $4 * 3 + $2 = $14. She needs $14.","Adding 10 + 5 = 15 students. Each group gets 15 / 3 = 5.","He sold 6 * $3 = $18. After buying 2 for $5, he has $13 left."]; | |
| const resp=responses[Math.floor(Math.random()*responses.length)]; | |
| let i=0,text=''; | |
| const iv=setInterval(()=>{ | |
| if(i>=resp.length){clearInterval(iv);out.innerHTML=text;const el=((Date.now()-t0)/1000).toFixed(1),tps=(resp.split(' ').length/el).toFixed(0);stats.textContent=tps+' tok/s · '+el+'s';btn.disabled=false;btn.textContent='▶ Run';return;} | |
| text+=resp[i++];out.innerHTML=text+'<span class="demo-cursor"></span>'; | |
| },28); | |
| } | |
| document.getElementById('demo-prompt').addEventListener('keydown',e=>{if(e.key==='Enter'&&e.ctrlKey)runDemo();}); | |
| </script> | |
| </body> | |
| </html> | |