v2
Browse files- index.html +118 -10
index.html
CHANGED
|
@@ -771,12 +771,96 @@
|
|
| 771 |
.k-ty { color: #6fb3ff; }
|
| 772 |
.k-at { color: #ffb074; }
|
| 773 |
.k-nu { color: #7ee787; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 774 |
.kx-code::-webkit-scrollbar, .kx-list::-webkit-scrollbar { width: 10px; height: 10px; }
|
| 775 |
.kx-code::-webkit-scrollbar-thumb, .kx-list::-webkit-scrollbar-thumb { background: var(--line); border: 3px solid #0a0a0c; border-radius: 10px; }
|
| 776 |
/* while the overlay is open, lock the page behind it so only the overlay's panes scroll */
|
| 777 |
body.kx-locked { overflow: hidden; }
|
| 778 |
@keyframes kxFade { from { opacity: 0; } to { opacity: 1; } }
|
| 779 |
@keyframes kxRise { from { opacity: 0; transform: translateY(12px) scale(0.99); } to { opacity: 1; transform: none; } }
|
|
|
|
|
|
|
| 780 |
|
| 781 |
@media (max-width: 760px) {
|
| 782 |
.kx { padding: 0; }
|
|
@@ -860,7 +944,7 @@
|
|
| 860 |
<div class="hero-row anim">
|
| 861 |
<div class="hero-main">
|
| 862 |
<p class="hero-sub">
|
| 863 |
-
<b>Gemma 4 E2B (QAT Mobile)</b> —
|
| 864 |
fully on-device with WebGPU. Weights cache locally after the first load, and nothing you
|
| 865 |
type ever leaves your machine.
|
| 866 |
</p>
|
|
@@ -964,14 +1048,33 @@
|
|
| 964 |
<div class="kx-body">
|
| 965 |
<div class="kx-side"><div class="kx-list" id="kxList"></div></div>
|
| 966 |
<div class="kx-view">
|
| 967 |
-
<div class="kx-
|
| 968 |
-
<
|
| 969 |
-
|
| 970 |
-
|
| 971 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 972 |
</div>
|
|
|
|
| 973 |
</div>
|
| 974 |
-
<pre class="kx-code"><code id="kxCode"></code></pre>
|
| 975 |
</div>
|
| 976 |
</div>
|
| 977 |
</div>
|
|
@@ -1222,11 +1325,14 @@
|
|
| 1222 |
item.addEventListener("click", () => selectKernel(i));
|
| 1223 |
list.appendChild(item);
|
| 1224 |
});
|
| 1225 |
-
|
| 1226 |
-
|
|
|
|
|
|
|
|
|
|
| 1227 |
kernelsOverlay.hidden = false;
|
| 1228 |
document.body.classList.add("kx-locked");
|
| 1229 |
-
|
| 1230 |
requestAnimationFrame(updateListFade);
|
| 1231 |
}
|
| 1232 |
|
|
@@ -1241,6 +1347,8 @@
|
|
| 1241 |
function selectKernel(i) {
|
| 1242 |
const k = kernels[i];
|
| 1243 |
if (!k) return;
|
|
|
|
|
|
|
| 1244 |
[...$("kxList").children].forEach((el, j) => el.classList.toggle("active", j === i));
|
| 1245 |
$("kxName").textContent = k.name;
|
| 1246 |
$("kxLines").textContent = `${k.source.split("\n").length} lines`;
|
|
|
|
| 771 |
.k-ty { color: #6fb3ff; }
|
| 772 |
.k-at { color: #ffb074; }
|
| 773 |
.k-nu { color: #7ee787; }
|
| 774 |
+
|
| 775 |
+
/* explanation shown until a kernel is picked (swaps in/out with the source view) */
|
| 776 |
+
.kx-source { flex: 1; min-height: 0; display: flex; flex-direction: column; }
|
| 777 |
+
.kx-source[hidden] { display: none; }
|
| 778 |
+
.kx-intro {
|
| 779 |
+
flex: 1;
|
| 780 |
+
min-height: 0;
|
| 781 |
+
overflow-y: auto;
|
| 782 |
+
display: flex;
|
| 783 |
+
align-items: center;
|
| 784 |
+
justify-content: center;
|
| 785 |
+
padding: 34px 30px;
|
| 786 |
+
}
|
| 787 |
+
.kx-intro[hidden] { display: none; }
|
| 788 |
+
.kx-intro-inner {
|
| 789 |
+
max-width: 540px;
|
| 790 |
+
text-align: center;
|
| 791 |
+
animation: kxIntroRise 0.6s cubic-bezier(0.2, 0.7, 0.2, 1) both;
|
| 792 |
+
}
|
| 793 |
+
|
| 794 |
+
/* rainbow-shimmer icon — a slowly rotating conic ring + halo in the app's accent palette */
|
| 795 |
+
.kx-spark { position: relative; width: 60px; height: 60px; margin: 0 auto 24px; }
|
| 796 |
+
.kx-spark-ring {
|
| 797 |
+
position: absolute; inset: 0; border-radius: 50%;
|
| 798 |
+
background: conic-gradient(from 0deg, #ff7a6b, #ffcd6b, #64ffa0, #6fb3ff, #c792ea, #ff7a6b);
|
| 799 |
+
animation: kxSpin 6s linear infinite;
|
| 800 |
+
}
|
| 801 |
+
.kx-spark-ring::after { /* blurred halo that rotates with the ring → soft shimmer */
|
| 802 |
+
content: ""; position: absolute; inset: -7px; border-radius: 50%;
|
| 803 |
+
background: inherit; filter: blur(13px); opacity: 0.5;
|
| 804 |
+
}
|
| 805 |
+
.kx-spark-core { position: absolute; inset: 2px; border-radius: 50%; background: #0a0a0c; }
|
| 806 |
+
.kx-spark-icon { position: absolute; inset: 0; margin: auto; width: 32px; height: 32px; color: #fff; }
|
| 807 |
+
|
| 808 |
+
.kx-intro-title {
|
| 809 |
+
font-family: var(--display);
|
| 810 |
+
font-weight: 400;
|
| 811 |
+
font-size: clamp(26px, 3vw, 34px);
|
| 812 |
+
line-height: 1.12;
|
| 813 |
+
color: #fff;
|
| 814 |
+
margin-bottom: 16px;
|
| 815 |
+
}
|
| 816 |
+
.kx-intro-lead {
|
| 817 |
+
font-size: 14.5px;
|
| 818 |
+
font-weight: 300;
|
| 819 |
+
line-height: 1.7;
|
| 820 |
+
color: var(--t2);
|
| 821 |
+
margin: 0 auto 26px;
|
| 822 |
+
max-width: 48ch;
|
| 823 |
+
}
|
| 824 |
+
.kx-points {
|
| 825 |
+
list-style: none;
|
| 826 |
+
display: flex;
|
| 827 |
+
flex-direction: column;
|
| 828 |
+
gap: 13px;
|
| 829 |
+
text-align: left;
|
| 830 |
+
margin-bottom: 28px;
|
| 831 |
+
}
|
| 832 |
+
.kx-points li {
|
| 833 |
+
position: relative;
|
| 834 |
+
padding-left: 22px;
|
| 835 |
+
font-size: 13.5px;
|
| 836 |
+
line-height: 1.62;
|
| 837 |
+
color: var(--t2);
|
| 838 |
+
}
|
| 839 |
+
.kx-points li::before {
|
| 840 |
+
content: "";
|
| 841 |
+
position: absolute; left: 2px; top: 0.6em;
|
| 842 |
+
width: 6px; height: 6px; border-radius: 50%;
|
| 843 |
+
}
|
| 844 |
+
.kx-points li:nth-child(1)::before { background: #ff7a6b; box-shadow: 0 0 8px rgba(255, 122, 107, 0.7); }
|
| 845 |
+
.kx-points li:nth-child(2)::before { background: #6fb3ff; box-shadow: 0 0 8px rgba(111, 179, 255, 0.7); }
|
| 846 |
+
.kx-points li:nth-child(3)::before { background: #64ffa0; box-shadow: 0 0 8px rgba(100, 255, 160, 0.7); }
|
| 847 |
+
.kx-points b { color: var(--t1); font-weight: 600; }
|
| 848 |
+
.kx-intro-hint {
|
| 849 |
+
font-family: var(--mono);
|
| 850 |
+
font-size: 11px;
|
| 851 |
+
letter-spacing: 0.08em;
|
| 852 |
+
text-transform: uppercase;
|
| 853 |
+
color: var(--t3);
|
| 854 |
+
}
|
| 855 |
+
|
| 856 |
.kx-code::-webkit-scrollbar, .kx-list::-webkit-scrollbar { width: 10px; height: 10px; }
|
| 857 |
.kx-code::-webkit-scrollbar-thumb, .kx-list::-webkit-scrollbar-thumb { background: var(--line); border: 3px solid #0a0a0c; border-radius: 10px; }
|
| 858 |
/* while the overlay is open, lock the page behind it so only the overlay's panes scroll */
|
| 859 |
body.kx-locked { overflow: hidden; }
|
| 860 |
@keyframes kxFade { from { opacity: 0; } to { opacity: 1; } }
|
| 861 |
@keyframes kxRise { from { opacity: 0; transform: translateY(12px) scale(0.99); } to { opacity: 1; transform: none; } }
|
| 862 |
+
@keyframes kxSpin { to { transform: rotate(360deg); } }
|
| 863 |
+
@keyframes kxIntroRise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
|
| 864 |
|
| 865 |
@media (max-width: 760px) {
|
| 866 |
.kx { padding: 0; }
|
|
|
|
| 944 |
<div class="hero-row anim">
|
| 945 |
<div class="hero-main">
|
| 946 |
<p class="hero-sub">
|
| 947 |
+
<b>Gemma 4 E2B (QAT Mobile)</b> — a powerful open-source model — runs
|
| 948 |
fully on-device with WebGPU. Weights cache locally after the first load, and nothing you
|
| 949 |
type ever leaves your machine.
|
| 950 |
</p>
|
|
|
|
| 1048 |
<div class="kx-body">
|
| 1049 |
<div class="kx-side"><div class="kx-list" id="kxList"></div></div>
|
| 1050 |
<div class="kx-view">
|
| 1051 |
+
<div class="kx-intro" id="kxIntro">
|
| 1052 |
+
<div class="kx-intro-inner">
|
| 1053 |
+
<div class="kx-spark" aria-hidden="true">
|
| 1054 |
+
<span class="kx-spark-ring"></span>
|
| 1055 |
+
<span class="kx-spark-core"></span>
|
| 1056 |
+
<svg class="kx-spark-icon" viewBox="0 0 20 20" fill="currentColor"><path d="M11.7858 1.66699C11.9437 1.66699 12.0957 1.72951 12.2074 1.84115C12.3189 1.95276 12.3815 2.10483 12.3815 2.2627V3.45247H15.3568C15.6725 3.45247 15.9767 3.57757 16.1999 3.80078C16.4231 4.02403 16.5482 4.32813 16.5482 4.64388V7.61914H17.738C17.8957 7.61914 18.0479 7.68181 18.1595 7.79329C18.2712 7.90491 18.3337 8.05698 18.3337 8.21484C18.3336 8.37247 18.2709 8.52323 18.1595 8.63477C18.0478 8.7464 17.8958 8.81055 17.738 8.81055H16.5482V11.1901H17.738C17.8958 11.1901 18.0478 11.2543 18.1595 11.3659C18.2709 11.4774 18.3336 11.6282 18.3337 11.7858C18.3337 11.9437 18.2712 12.0957 18.1595 12.2074C18.0479 12.3188 17.8957 12.3815 17.738 12.3815H16.5482V15.3568C16.5482 15.6725 16.4231 15.9767 16.1999 16.1999C15.9767 16.4231 15.6725 16.5482 15.3568 16.5482H12.3815V17.738C12.3815 17.8959 12.3188 18.0479 12.2074 18.1595C12.0957 18.271 11.9437 18.3337 11.7858 18.3337C11.6282 18.3336 11.4774 18.2707 11.3659 18.1595C11.2543 18.0478 11.1901 17.896 11.1901 17.738V16.5482H8.81055V17.738C8.81055 17.896 8.7464 18.0478 8.63477 18.1595C8.52323 18.2707 8.37247 18.3336 8.21484 18.3337C8.05698 18.3337 7.90491 18.271 7.79329 18.1595C7.68181 18.0479 7.61914 17.8958 7.61914 17.738V16.5482H4.64388C4.32813 16.5482 4.02403 16.4231 3.80078 16.1999C3.57756 15.9767 3.45247 15.6725 3.45247 15.3568V12.3815H2.2627C2.10485 12.3815 1.95276 12.3189 1.84115 12.2074C1.72951 12.0957 1.66699 11.9437 1.66699 11.7858C1.66708 11.6283 1.72987 11.4774 1.84115 11.3659C1.95276 11.2543 2.10483 11.1901 2.2627 11.1901H3.45247V8.81055H2.2627C2.10483 8.81055 1.95276 8.7464 1.84115 8.63477C1.72987 8.52324 1.66704 8.37243 1.66699 8.21484C1.66699 8.05698 1.72951 7.90491 1.84115 7.79329C1.95275 7.68175 2.1049 7.61914 2.2627 7.61914H3.45247V4.64388C3.45247 4.32813 3.57751 4.02403 3.80078 3.80078C4.02403 3.57753 4.32813 3.45247 4.64388 3.45247H7.61914V2.2627C7.61914 2.10488 7.68175 1.95275 7.79329 1.84115C7.90491 1.72951 8.05698 1.66699 8.21484 1.66699C8.37243 1.66704 8.52324 1.72987 8.63477 1.84115C8.7464 1.95276 8.81055 2.10481 8.81055 2.2627V3.45247H11.1901V2.2627C11.1901 2.10481 11.2543 1.95276 11.3659 1.84115C11.4774 1.72987 11.6283 1.66708 11.7858 1.66699ZM6.14616 5.31445C5.6863 5.31489 5.31445 5.68782 5.31445 6.14779V13.8529C5.31445 14.3131 5.68755 14.6862 6.14779 14.6862H13.8529C14.3131 14.6862 14.6862 14.3131 14.6862 13.8529V6.14779C14.6862 5.68755 14.3131 5.31445 13.8529 5.31445H6.14616Z" fill-opacity="0.4"></path><rect x="5.31348" y="5.31445" width="9.37256" height="9.37256" rx="0.833333" fill-opacity="0.15"></rect><path d="M8.19238 7.91225V12.254C8.19238 12.585 8.55699 12.7862 8.83777 12.606L12.2491 10.4351C12.3088 10.3973 12.358 10.3451 12.3921 10.2831C12.4262 10.2212 12.4441 10.1517 12.4441 10.081C12.4441 10.0103 12.4262 9.9408 12.3921 9.87889C12.358 9.81697 12.3088 9.76468 12.2491 9.72688L8.83777 7.56022C8.77456 7.51934 8.70149 7.49627 8.62626 7.49346C8.55103 7.49064 8.47644 7.50819 8.41035 7.54423C8.34426 7.58028 8.28913 7.6335 8.25077 7.69827C8.2124 7.76304 8.19223 7.83697 8.19238 7.91225Z" fill-opacity="0.8"></path></svg>
|
| 1057 |
+
</div>
|
| 1058 |
+
<h2 class="kx-intro-title">What are Kernels?</h2>
|
| 1059 |
+
<p class="kx-intro-lead">Kernels are the low-level GPU programs that do the model's actual math — the matrix multiplications, attention, and normalization behind every token. And how well they're optimized can dramatically speed up inference.</p>
|
| 1060 |
+
<ul class="kx-points">
|
| 1061 |
+
<li><b>WebGPU & WGSL.</b> Each kernel is a WebGPU compute shader, written in WGSL — the language that runs general-purpose math on the GPU — entirely locally in your browser.</li>
|
| 1062 |
+
<li><b>Agentic Kernel Optimization.</b> Every kernel was generated by AI (in this case, Fable 5, before it was shut down), benchmarked on an Apple M4 Max, and refined through an evolutionary, genetic-style search toward the fastest version.</li>
|
| 1063 |
+
<li><b>Blazingly Fast.</b> This means we are able to run Gemma 4 E2B at ~250 tokens/sec on an M4 Max, pushing your device to its limits.</li>
|
| 1064 |
+
</ul>
|
| 1065 |
+
<div class="kx-intro-hint">Select a kernel to read its real source</div>
|
| 1066 |
+
</div>
|
| 1067 |
+
</div>
|
| 1068 |
+
<div class="kx-source" id="kxSource" hidden>
|
| 1069 |
+
<div class="kx-view-head">
|
| 1070 |
+
<span class="kx-name" id="kxName"></span>
|
| 1071 |
+
<div class="kx-view-actions">
|
| 1072 |
+
<span class="kx-lines" id="kxLines"></span>
|
| 1073 |
+
<button class="kx-copy" id="kxCopy" type="button">Copy</button>
|
| 1074 |
+
</div>
|
| 1075 |
</div>
|
| 1076 |
+
<pre class="kx-code"><code id="kxCode"></code></pre>
|
| 1077 |
</div>
|
|
|
|
| 1078 |
</div>
|
| 1079 |
</div>
|
| 1080 |
</div>
|
|
|
|
| 1325 |
item.addEventListener("click", () => selectKernel(i));
|
| 1326 |
list.appendChild(item);
|
| 1327 |
});
|
| 1328 |
+
// Open on the explanation, with no kernel selected — the source shows only once one is clicked.
|
| 1329 |
+
[...list.children].forEach((el) => el.classList.remove("active"));
|
| 1330 |
+
$("kxSource").hidden = true;
|
| 1331 |
+
$("kxIntro").hidden = false;
|
| 1332 |
+
kxCopySource = "";
|
| 1333 |
kernelsOverlay.hidden = false;
|
| 1334 |
document.body.classList.add("kx-locked");
|
| 1335 |
+
list.scrollTop = 0;
|
| 1336 |
requestAnimationFrame(updateListFade);
|
| 1337 |
}
|
| 1338 |
|
|
|
|
| 1347 |
function selectKernel(i) {
|
| 1348 |
const k = kernels[i];
|
| 1349 |
if (!k) return;
|
| 1350 |
+
$("kxIntro").hidden = true; // swap the explanation out for the source
|
| 1351 |
+
$("kxSource").hidden = false;
|
| 1352 |
[...$("kxList").children].forEach((el, j) => el.classList.toggle("active", j === i));
|
| 1353 |
$("kxName").textContent = k.name;
|
| 1354 |
$("kxLines").textContent = `${k.source.split("\n").length} lines`;
|