Spaces:
Running
v0.7.7: UX restructure — task tiles + 'Why static?' README FAQ
Browse filesUX RESTRUCTURE — addresses the 14-tabs-overflow problem before forum-post traffic arrives.
NEW <section id='task-tiles'>: 5 tiles grouping the 14 modes by user intent (not feature):
- 🔬 Diagnose a model (Profile, Unmask, NIAH→Reason, Quant, Inspector)
- ✓ Trust a benchmark score (Contamination, Drift, Arena CI)
- ⚙️ Set up an eval correctly (Chat-template, Diagnose CLI)
- 🆚 Compare models (Compare, Phase diagram)
- 📋 Manual / free-form (Recipe, Ask)
Tile buttons emit [data-mode-link='X'] clicks → delegated handler triggers the corresponding mode-btn (no duplicate state, fully reuses the existing mode switcher) and smooth-scrolls to the section so the user immediately sees the form they expected.
Mode-tabs strip stays as a power-user backup below the tiles (still wrapped foldable by wrapMainSectionsAsFoldable). Subtitle on tiles points users there if they want full access.
Cognitive load drops from 14 buttons → 5 categorical tiles. Adding more modes in v0.8 won't require new top-level UI — just new tile entries.
README FAQ — preempts 'why not Gradio?' criticism before forum post traffic arrives. Cites three USPs (privacy + $0 + Lean formal verification) that are only viable with browser-only architecture.
i18n: 12 new keys × EN/ES/FR/ZH (693 total, 0 missing / 0 extra).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- README.md +14 -0
- index.html +52 -0
- js/i18n.js +56 -0
- js/main.js +25 -0
- style.css +50 -0
|
@@ -132,6 +132,20 @@ nothing is hallucinated.
|
|
| 132 |
|
| 133 |
If 1 user or 1 million users hit it, our cost stays the same: $0.
|
| 134 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
## Architecture coverage
|
| 136 |
|
| 137 |
Supports any model whose `config.json` is parseable:
|
|
|
|
| 132 |
|
| 133 |
If 1 user or 1 million users hit it, our cost stays the same: $0.
|
| 134 |
|
| 135 |
+
## Why static HTML+JS+Pyodide instead of Gradio/Streamlit?
|
| 136 |
+
|
| 137 |
+
A reasonable question. Three TAF Agent USPs are **only possible** with browser-only architecture:
|
| 138 |
+
|
| 139 |
+
1. **Your inputs never leave the tab.** No server = no privacy compromise. The "anti-bullshit" framing depends on this.
|
| 140 |
+
2. **$0 forever, even at infinite scale.** Static Spaces have unlimited HF bandwidth; there is no cold-start, no queue, no rate limit. Going viral can't bankrupt the project.
|
| 141 |
+
3. **Lean+Mathlib formal verification** ships as a static manifest. The 37 theorem badges link to source lines that anyone can `lake build` themselves — no hidden server logic.
|
| 142 |
+
|
| 143 |
+
Bonus: in-browser LLM (WebLLM running Qwen2.5-0.5B in your GPU/CPU) for the 💬 Ask mode is only viable in static. Pyodide running deterministic Python in your browser means you can audit every number — no opaque server.
|
| 144 |
+
|
| 145 |
+
The cost: HuggingFace's "Trending Spaces" algorithm favours Gradio/Streamlit Spaces. We compensate with detailed tags + forum presence + this README. If you'd prefer a Python-API client, that's a planned `gradio_client` companion (v0.9).
|
| 146 |
+
|
| 147 |
+
---
|
| 148 |
+
|
| 149 |
## Architecture coverage
|
| 150 |
|
| 151 |
Supports any model whose `config.json` is parseable:
|
|
@@ -349,6 +349,58 @@
|
|
| 349 |
</div>
|
| 350 |
</section>
|
| 351 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 352 |
<!-- Mode toggle -->
|
| 353 |
<section id="mode-section">
|
| 354 |
<h2><span data-i18n="modes.title">🎯 Mode</span>
|
|
|
|
| 349 |
</div>
|
| 350 |
</section>
|
| 351 |
|
| 352 |
+
<!-- v0.7.7 — Task tiles: friendlier entry point, groups 14 modes by user intent. -->
|
| 353 |
+
<section id="task-tiles" aria-labelledby="tiles-title">
|
| 354 |
+
<h2 id="tiles-title" data-i18n="tiles.title">🎯 What do you want to do?</h2>
|
| 355 |
+
<p class="recipe-desc" data-i18n="tiles.subtitle">Pick a task. Each one opens the right tool below. Or scroll down for the full list of 14 modes.</p>
|
| 356 |
+
<div class="tiles-grid">
|
| 357 |
+
<div class="task-tile">
|
| 358 |
+
<h3 data-i18n="tile.diagnose.title">🔬 Diagnose a model</h3>
|
| 359 |
+
<p class="tile-desc" data-i18n="tile.diagnose.desc">Will this specific model work for my use case?</p>
|
| 360 |
+
<div class="tile-modes">
|
| 361 |
+
<button data-mode-link="profile" data-i18n="modes.profile">📇 Profile a model</button>
|
| 362 |
+
<button data-mode-link="unmask" data-i18n="modes.unmask">🪟 Unmask</button>
|
| 363 |
+
<button data-mode-link="niah" data-i18n="modes.niah">🔍 NIAH→Reason</button>
|
| 364 |
+
<button data-mode-link="quant" data-i18n="modes.quant">⚖️ Quant</button>
|
| 365 |
+
<button data-mode-link="inspector" data-i18n="modes.inspector">🔍 Inspect config</button>
|
| 366 |
+
</div>
|
| 367 |
+
</div>
|
| 368 |
+
<div class="task-tile">
|
| 369 |
+
<h3 data-i18n="tile.trust.title">✓ Trust a benchmark score</h3>
|
| 370 |
+
<p class="tile-desc" data-i18n="tile.trust.desc">Should I believe this number? Bug or noise?</p>
|
| 371 |
+
<div class="tile-modes">
|
| 372 |
+
<button data-mode-link="contam" data-i18n="modes.contam">🧪 Contamination</button>
|
| 373 |
+
<button data-mode-link="drift" data-i18n="modes.drift">🔀 Drift</button>
|
| 374 |
+
<button data-mode-link="arena" data-i18n="modes.arena">🎯 Arena CI</button>
|
| 375 |
+
</div>
|
| 376 |
+
</div>
|
| 377 |
+
<div class="task-tile">
|
| 378 |
+
<h3 data-i18n="tile.eval.title">⚙️ Set up an eval correctly</h3>
|
| 379 |
+
<p class="tile-desc" data-i18n="tile.eval.desc">Get the exact CLI flag for lm-eval / vLLM / transformers.</p>
|
| 380 |
+
<div class="tile-modes">
|
| 381 |
+
<button data-mode-link="template" data-i18n="modes.template">📜 Chat-template</button>
|
| 382 |
+
<button data-mode-link="diagnose" data-i18n="modes.diagnose">🩺 Diagnose CLI</button>
|
| 383 |
+
</div>
|
| 384 |
+
</div>
|
| 385 |
+
<div class="task-tile">
|
| 386 |
+
<h3 data-i18n="tile.compare.title">🆚 Compare models</h3>
|
| 387 |
+
<p class="tile-desc" data-i18n="tile.compare.desc">Side-by-side, or browse the empirical model landscape.</p>
|
| 388 |
+
<div class="tile-modes">
|
| 389 |
+
<button data-mode-link="compare" data-i18n="modes.compare">🆚 Compare models</button>
|
| 390 |
+
<button data-mode-link="phase" data-i18n="modes.phase">📊 Phase diagram</button>
|
| 391 |
+
</div>
|
| 392 |
+
</div>
|
| 393 |
+
<div class="task-tile">
|
| 394 |
+
<h3 data-i18n="tile.manual.title">📋 Manual / free-form</h3>
|
| 395 |
+
<p class="tile-desc" data-i18n="tile.manual.desc">Pick a specific recipe by hand, or ask in plain English.</p>
|
| 396 |
+
<div class="tile-modes">
|
| 397 |
+
<button data-mode-link="recipe" data-i18n="modes.recipe">📋 Pick recipe</button>
|
| 398 |
+
<button data-mode-link="ask" data-i18n="modes.ask">💬 Ask plain English</button>
|
| 399 |
+
</div>
|
| 400 |
+
</div>
|
| 401 |
+
</div>
|
| 402 |
+
</section>
|
| 403 |
+
|
| 404 |
<!-- Mode toggle -->
|
| 405 |
<section id="mode-section">
|
| 406 |
<h2><span data-i18n="modes.title">🎯 Mode</span>
|
|
@@ -465,6 +465,20 @@ export const TRANSLATIONS = {
|
|
| 465 |
"niah.status.fetched": "✅ Config fetched for {modelId}. Set T_eval and click Predict (or Sweep contexts).",
|
| 466 |
"niah.status.done": "✅ {verdict} — NIAH {niah}% · reasoning {reasoning}%",
|
| 467 |
"niah.status.sweep_done": "✅ Swept {n} context lengths.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 468 |
"share.import_desc": "Got a JSON file from someone else's TAF analysis? Load it here to see the verdict + chain locally. Same view as if you'd run it yourself.",
|
| 469 |
"share.import_btn": "📂 Load shared JSON",
|
| 470 |
"synthesis.system": "You are a precise transformer LLM diagnostic assistant. Given pre-computed TAF formula results, write a clear plain-English summary in 4-6 sentences. Cite the section number (§X.Y) for each number you mention. Always give a concrete recommendation. Do NOT invent numbers.",
|
|
@@ -1354,6 +1368,20 @@ export const TRANSLATIONS = {
|
|
| 1354 |
"niah.status.fetched": "✅ Config obtenido para {modelId}. Pon T_eval y click Predecir (o Barrer contextos).",
|
| 1355 |
"niah.status.done": "✅ {verdict} — NIAH {niah}% · reasoning {reasoning}%",
|
| 1356 |
"niah.status.sweep_done": "✅ Barridos {n} largos de contexto.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1357 |
"share.import_desc": "¿Tienes un fichero JSON del análisis TAF de alguien? Cárgalo aquí para ver el veredicto + cadena localmente. La misma vista que si lo hubieras ejecutado tú.",
|
| 1358 |
"share.import_btn": "📂 Cargar JSON compartido",
|
| 1359 |
"synthesis.system": "Eres un asistente de diagnóstico preciso para LLMs transformer. Dados resultados de fórmulas TAF pre-calculados, escribe un resumen claro en español de 4-6 frases. Cita el número de sección (§X.Y) para cada número que menciones. Da siempre una recomendación concreta. NO inventes números.",
|
|
@@ -2107,6 +2135,20 @@ export const TRANSLATIONS = {
|
|
| 2107 |
"niah.status.fetched": "✅ Config récupéré pour {modelId}. Réglez T_eval et cliquez Prédire (ou Balayer les contextes).",
|
| 2108 |
"niah.status.done": "✅ {verdict} — NIAH {niah}% · reasoning {reasoning}%",
|
| 2109 |
"niah.status.sweep_done": "✅ Balayé {n} longueurs de contexte.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2110 |
"share.import_desc": "Vous avez un fichier JSON de l'analyse TAF de quelqu'un ? Chargez-le ici pour voir le verdict + la chaîne localement. La même vue que si vous l'aviez exécuté vous-même.",
|
| 2111 |
"share.import_btn": "📂 Charger JSON partagé",
|
| 2112 |
"synthesis.system": "Vous êtes un assistant de diagnostic précis pour LLMs transformer. Étant donné des résultats de formules TAF pré-calculés, écrivez un résumé clair en français de 4-6 phrases. Citez le numéro de section (§X.Y) pour chaque nombre mentionné. Donnez toujours une recommandation concrète. N'INVENTEZ PAS de nombres.",
|
|
@@ -2860,6 +2902,20 @@ export const TRANSLATIONS = {
|
|
| 2860 |
"niah.status.fetched": "✅ 已获取 {modelId} 的 config。设置 T_eval 并点击预测(或扫描上下文)。",
|
| 2861 |
"niah.status.done": "✅ {verdict} — NIAH {niah}% · reasoning {reasoning}%",
|
| 2862 |
"niah.status.sweep_done": "✅ 已扫描 {n} 个上下文长度。",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2863 |
"share.import_desc": "有他人 TAF 分析的 JSON 文件? 在这里加载以本地查看判定 + 链。与您自己运行的视图相同。",
|
| 2864 |
"share.import_btn": "📂 加载共享的 JSON",
|
| 2865 |
"synthesis.system": "您是 transformer LLM 的精确诊断助手。给定预先计算的 TAF 公式结果,用 4-6 句中文写出清晰的摘要。为每个提到的数字引用章节号 (§X.Y)。始终给出具体建议。不要编造数字。",
|
|
|
|
| 465 |
"niah.status.fetched": "✅ Config fetched for {modelId}. Set T_eval and click Predict (or Sweep contexts).",
|
| 466 |
"niah.status.done": "✅ {verdict} — NIAH {niah}% · reasoning {reasoning}%",
|
| 467 |
"niah.status.sweep_done": "✅ Swept {n} context lengths.",
|
| 468 |
+
|
| 469 |
+
// v0.7.7 — Task tiles (UX restructure: 14 modes grouped by user intent)
|
| 470 |
+
"tiles.title": "🎯 What do you want to do?",
|
| 471 |
+
"tiles.subtitle": "Pick a task. Each one opens the right tool below. Or scroll down for the full list of 14 modes.",
|
| 472 |
+
"tile.diagnose.title": "🔬 Diagnose a model",
|
| 473 |
+
"tile.diagnose.desc": "Will this specific model work for my use case?",
|
| 474 |
+
"tile.trust.title": "✓ Trust a benchmark score",
|
| 475 |
+
"tile.trust.desc": "Should I believe this number? Bug or noise?",
|
| 476 |
+
"tile.eval.title": "⚙️ Set up an eval correctly",
|
| 477 |
+
"tile.eval.desc": "Get the exact CLI flag for lm-eval / vLLM / transformers.",
|
| 478 |
+
"tile.compare.title": "🆚 Compare models",
|
| 479 |
+
"tile.compare.desc": "Side-by-side, or browse the empirical model landscape.",
|
| 480 |
+
"tile.manual.title": "📋 Manual / free-form",
|
| 481 |
+
"tile.manual.desc": "Pick a specific recipe by hand, or ask in plain English.",
|
| 482 |
"share.import_desc": "Got a JSON file from someone else's TAF analysis? Load it here to see the verdict + chain locally. Same view as if you'd run it yourself.",
|
| 483 |
"share.import_btn": "📂 Load shared JSON",
|
| 484 |
"synthesis.system": "You are a precise transformer LLM diagnostic assistant. Given pre-computed TAF formula results, write a clear plain-English summary in 4-6 sentences. Cite the section number (§X.Y) for each number you mention. Always give a concrete recommendation. Do NOT invent numbers.",
|
|
|
|
| 1368 |
"niah.status.fetched": "✅ Config obtenido para {modelId}. Pon T_eval y click Predecir (o Barrer contextos).",
|
| 1369 |
"niah.status.done": "✅ {verdict} — NIAH {niah}% · reasoning {reasoning}%",
|
| 1370 |
"niah.status.sweep_done": "✅ Barridos {n} largos de contexto.",
|
| 1371 |
+
|
| 1372 |
+
// v0.7.7 — Tiles de tareas (UX restructure: 14 modos agrupados por intención)
|
| 1373 |
+
"tiles.title": "🎯 ¿Qué quieres hacer?",
|
| 1374 |
+
"tiles.subtitle": "Elige una tarea. Cada una abre la herramienta adecuada debajo. O baja para la lista completa de 14 modos.",
|
| 1375 |
+
"tile.diagnose.title": "🔬 Diagnosticar un modelo",
|
| 1376 |
+
"tile.diagnose.desc": "¿Servirá este modelo concreto para mi caso de uso?",
|
| 1377 |
+
"tile.trust.title": "✓ Confiar en un score de benchmark",
|
| 1378 |
+
"tile.trust.desc": "¿Me creo este número? ¿Es bug o ruido?",
|
| 1379 |
+
"tile.eval.title": "⚙️ Configurar bien una eval",
|
| 1380 |
+
"tile.eval.desc": "Obtén el flag CLI exacto para lm-eval / vLLM / transformers.",
|
| 1381 |
+
"tile.compare.title": "🆚 Comparar modelos",
|
| 1382 |
+
"tile.compare.desc": "Lado a lado, o explora el panel empírico de modelos.",
|
| 1383 |
+
"tile.manual.title": "📋 Manual / libre",
|
| 1384 |
+
"tile.manual.desc": "Elige una receta concreta a mano, o pregunta en inglés llano.",
|
| 1385 |
"share.import_desc": "¿Tienes un fichero JSON del análisis TAF de alguien? Cárgalo aquí para ver el veredicto + cadena localmente. La misma vista que si lo hubieras ejecutado tú.",
|
| 1386 |
"share.import_btn": "📂 Cargar JSON compartido",
|
| 1387 |
"synthesis.system": "Eres un asistente de diagnóstico preciso para LLMs transformer. Dados resultados de fórmulas TAF pre-calculados, escribe un resumen claro en español de 4-6 frases. Cita el número de sección (§X.Y) para cada número que menciones. Da siempre una recomendación concreta. NO inventes números.",
|
|
|
|
| 2135 |
"niah.status.fetched": "✅ Config récupéré pour {modelId}. Réglez T_eval et cliquez Prédire (ou Balayer les contextes).",
|
| 2136 |
"niah.status.done": "✅ {verdict} — NIAH {niah}% · reasoning {reasoning}%",
|
| 2137 |
"niah.status.sweep_done": "✅ Balayé {n} longueurs de contexte.",
|
| 2138 |
+
|
| 2139 |
+
// v0.7.7 — Tuiles de tâches (refonte UX : 14 modes regroupés par intention)
|
| 2140 |
+
"tiles.title": "🎯 Que voulez-vous faire ?",
|
| 2141 |
+
"tiles.subtitle": "Choisissez une tâche. Chacune ouvre l'outil adéquat ci-dessous. Ou faites défiler pour la liste complète des 14 modes.",
|
| 2142 |
+
"tile.diagnose.title": "🔬 Diagnostiquer un modèle",
|
| 2143 |
+
"tile.diagnose.desc": "Ce modèle conviendra-t-il à mon cas d'usage ?",
|
| 2144 |
+
"tile.trust.title": "✓ Faire confiance à un score",
|
| 2145 |
+
"tile.trust.desc": "Dois-je croire ce nombre ? Bug ou bruit ?",
|
| 2146 |
+
"tile.eval.title": "⚙️ Configurer une éval correctement",
|
| 2147 |
+
"tile.eval.desc": "Obtenez le flag CLI exact pour lm-eval / vLLM / transformers.",
|
| 2148 |
+
"tile.compare.title": "🆚 Comparer des modèles",
|
| 2149 |
+
"tile.compare.desc": "Côte à côte, ou explorez le panel empirique de modèles.",
|
| 2150 |
+
"tile.manual.title": "📋 Manuel / libre",
|
| 2151 |
+
"tile.manual.desc": "Choisissez une recette à la main, ou demandez en langage naturel.",
|
| 2152 |
"share.import_desc": "Vous avez un fichier JSON de l'analyse TAF de quelqu'un ? Chargez-le ici pour voir le verdict + la chaîne localement. La même vue que si vous l'aviez exécuté vous-même.",
|
| 2153 |
"share.import_btn": "📂 Charger JSON partagé",
|
| 2154 |
"synthesis.system": "Vous êtes un assistant de diagnostic précis pour LLMs transformer. Étant donné des résultats de formules TAF pré-calculés, écrivez un résumé clair en français de 4-6 phrases. Citez le numéro de section (§X.Y) pour chaque nombre mentionné. Donnez toujours une recommandation concrète. N'INVENTEZ PAS de nombres.",
|
|
|
|
| 2902 |
"niah.status.fetched": "✅ 已获取 {modelId} 的 config。设置 T_eval 并点击预测(或扫描上下文)。",
|
| 2903 |
"niah.status.done": "✅ {verdict} — NIAH {niah}% · reasoning {reasoning}%",
|
| 2904 |
"niah.status.sweep_done": "✅ 已扫描 {n} 个上下文长度。",
|
| 2905 |
+
|
| 2906 |
+
// v0.7.7 — 任务卡片(UX 重构:按用户意图分组的 14 个模式)
|
| 2907 |
+
"tiles.title": "🎯 你想做什么?",
|
| 2908 |
+
"tiles.subtitle": "选择一项任务。每一项会打开下方对应的工具。或往下滚动查看完整的 14 个模式列表。",
|
| 2909 |
+
"tile.diagnose.title": "🔬 诊断一个模型",
|
| 2910 |
+
"tile.diagnose.desc": "这个具体模型符合我的用例吗?",
|
| 2911 |
+
"tile.trust.title": "✓ 相信 benchmark 分数",
|
| 2912 |
+
"tile.trust.desc": "我该相信这个数字吗?是 bug 还是噪声?",
|
| 2913 |
+
"tile.eval.title": "⚙️ 正确设置 eval",
|
| 2914 |
+
"tile.eval.desc": "获取 lm-eval / vLLM / transformers 的精确 CLI flag。",
|
| 2915 |
+
"tile.compare.title": "🆚 比较模型",
|
| 2916 |
+
"tile.compare.desc": "并排,或浏览经验模型面板。",
|
| 2917 |
+
"tile.manual.title": "📋 手动 / 自由",
|
| 2918 |
+
"tile.manual.desc": "手动挑一个具体 recipe,或用自然语言提问。",
|
| 2919 |
"share.import_desc": "有他人 TAF 分析的 JSON 文件? 在这里加载以本地查看判定 + 链。与您自己运行的视图相同。",
|
| 2920 |
"share.import_btn": "📂 加载共享的 JSON",
|
| 2921 |
"synthesis.system": "您是 transformer LLM 的精确诊断助手。给定预先计算的 TAF 公式结果,用 4-6 句中文写出清晰的摘要。为每个提到的数字引用章节号 (§X.Y)。始终给出具体建议。不要编造数字。",
|
|
@@ -184,6 +184,31 @@ wrapMainSectionsAsFoldable();
|
|
| 184 |
// ════════════════════════════════════════════════════════════════════
|
| 185 |
// Mode toggle
|
| 186 |
// ════════════════════════════════════════════════════════════════════
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 187 |
document.querySelectorAll(".mode-btn").forEach(btn => {
|
| 188 |
btn.addEventListener("click", () => {
|
| 189 |
document.querySelectorAll(".mode-btn").forEach(b => {
|
|
|
|
| 184 |
// ════════════════════════════════════════════════════════════════════
|
| 185 |
// Mode toggle
|
| 186 |
// ════════════════════════════════════════════════════════════════════
|
| 187 |
+
// v0.7.7 — task tiles: clicking a tile-mode-link button triggers the equivalent mode-btn.
|
| 188 |
+
// Reuses the mode switcher entirely (no duplicate state). Smoothly scrolls to the
|
| 189 |
+
// activated section so the user immediately sees the form they expected.
|
| 190 |
+
document.addEventListener("click", (e) => {
|
| 191 |
+
const linkBtn = e.target.closest("[data-mode-link]");
|
| 192 |
+
if (!linkBtn) return;
|
| 193 |
+
const targetMode = linkBtn.dataset.modeLink;
|
| 194 |
+
const targetTab = document.querySelector(`.mode-btn[data-mode="${targetMode}"]`);
|
| 195 |
+
if (targetTab) {
|
| 196 |
+
targetTab.click();
|
| 197 |
+
// Scroll the activated section into view so the tile click feels responsive.
|
| 198 |
+
const sectionId = {
|
| 199 |
+
ask: "ask-section", recipe: "recipe-section", profile: "profile-section",
|
| 200 |
+
compare: "compare-section", inspector: "inspector-section",
|
| 201 |
+
diagnose: "diagnose-section", phase: "phase-section", unmask: "unmask-section",
|
| 202 |
+
template: "template-section", arena: "arena-section", contam: "contam-section",
|
| 203 |
+
quant: "quant-section", drift: "drift-section", niah: "niah-section",
|
| 204 |
+
}[targetMode];
|
| 205 |
+
if (sectionId) {
|
| 206 |
+
const sec = document.getElementById(sectionId);
|
| 207 |
+
if (sec) sec.scrollIntoView({ behavior: "smooth", block: "start" });
|
| 208 |
+
}
|
| 209 |
+
}
|
| 210 |
+
});
|
| 211 |
+
|
| 212 |
document.querySelectorAll(".mode-btn").forEach(btn => {
|
| 213 |
btn.addEventListener("click", () => {
|
| 214 |
document.querySelectorAll(".mode-btn").forEach(b => {
|
|
@@ -33,6 +33,56 @@
|
|
| 33 |
flex: 1;
|
| 34 |
}
|
| 35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
/* v0.7.5 — Cross-framework drift bound */
|
| 37 |
/* Drift section overrides the default 980px main width so the two-column form
|
| 38 |
has room without overlapping. Mobile (<800px) collapses to single column. */
|
|
|
|
| 33 |
flex: 1;
|
| 34 |
}
|
| 35 |
|
| 36 |
+
/* v0.7.7 — Task tiles: groups 14 modes by user intent, primary entry point */
|
| 37 |
+
#task-tiles { margin-bottom: 1em; }
|
| 38 |
+
#task-tiles h2 { margin-bottom: 0.3em; }
|
| 39 |
+
#task-tiles .recipe-desc { margin-bottom: 0.8em; opacity: 0.85; }
|
| 40 |
+
.tiles-grid {
|
| 41 |
+
display: grid;
|
| 42 |
+
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
| 43 |
+
gap: 0.8em;
|
| 44 |
+
}
|
| 45 |
+
.task-tile {
|
| 46 |
+
padding: 0.9em 1em;
|
| 47 |
+
background: #12181f;
|
| 48 |
+
border: 1px solid rgba(88, 166, 255, 0.2);
|
| 49 |
+
border-radius: 10px;
|
| 50 |
+
transition: border-color 0.15s, transform 0.15s;
|
| 51 |
+
}
|
| 52 |
+
.task-tile:hover {
|
| 53 |
+
border-color: rgba(88, 166, 255, 0.5);
|
| 54 |
+
}
|
| 55 |
+
.task-tile h3 {
|
| 56 |
+
margin: 0 0 0.3em;
|
| 57 |
+
font-size: 1.05em;
|
| 58 |
+
color: #58a6ff;
|
| 59 |
+
}
|
| 60 |
+
.task-tile .tile-desc {
|
| 61 |
+
font-size: 0.88em;
|
| 62 |
+
opacity: 0.8;
|
| 63 |
+
margin: 0 0 0.6em;
|
| 64 |
+
line-height: 1.4;
|
| 65 |
+
}
|
| 66 |
+
.task-tile .tile-modes {
|
| 67 |
+
display: flex;
|
| 68 |
+
flex-wrap: wrap;
|
| 69 |
+
gap: 0.35em;
|
| 70 |
+
}
|
| 71 |
+
.task-tile .tile-modes button {
|
| 72 |
+
font-size: 0.85em;
|
| 73 |
+
padding: 0.35em 0.7em;
|
| 74 |
+
background: rgba(88, 166, 255, 0.10);
|
| 75 |
+
border: 1px solid rgba(88, 166, 255, 0.25);
|
| 76 |
+
color: #c9d1d9;
|
| 77 |
+
border-radius: 5px;
|
| 78 |
+
cursor: pointer;
|
| 79 |
+
transition: background 0.12s, border-color 0.12s;
|
| 80 |
+
}
|
| 81 |
+
.task-tile .tile-modes button:hover {
|
| 82 |
+
background: rgba(88, 166, 255, 0.22);
|
| 83 |
+
border-color: rgba(88, 166, 255, 0.55);
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
/* v0.7.5 — Cross-framework drift bound */
|
| 87 |
/* Drift section overrides the default 980px main width so the two-column form
|
| 88 |
has room without overlapping. Mobile (<800px) collapses to single column. */
|