Spaces:
Sleeping
Sleeping
Commit Β·
cf92bd1
1
Parent(s): ec942b9
Add landing page at / (CTA enters app at /index.html)
Browse files- forge/api.py +10 -1
- frontend/landing.css +777 -0
- frontend/landing.html +629 -0
forge/api.py
CHANGED
|
@@ -15,7 +15,7 @@ from pathlib import Path
|
|
| 15 |
|
| 16 |
from fastapi import Body, FastAPI, HTTPException, Query
|
| 17 |
from fastapi.middleware.cors import CORSMiddleware
|
| 18 |
-
from fastapi.responses import StreamingResponse
|
| 19 |
from fastapi.staticfiles import StaticFiles
|
| 20 |
|
| 21 |
from . import db, engine, scraper
|
|
@@ -37,6 +37,15 @@ def health():
|
|
| 37 |
return {"ok": True, "llm_up": scraper._llm_up()}
|
| 38 |
|
| 39 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
@app.get("/graph")
|
| 41 |
def graph():
|
| 42 |
"""All nodes + edges for the initial force-graph render."""
|
|
|
|
| 15 |
|
| 16 |
from fastapi import Body, FastAPI, HTTPException, Query
|
| 17 |
from fastapi.middleware.cors import CORSMiddleware
|
| 18 |
+
from fastapi.responses import FileResponse, StreamingResponse
|
| 19 |
from fastapi.staticfiles import StaticFiles
|
| 20 |
|
| 21 |
from . import db, engine, scraper
|
|
|
|
| 37 |
return {"ok": True, "llm_up": scraper._llm_up()}
|
| 38 |
|
| 39 |
|
| 40 |
+
@app.get("/")
|
| 41 |
+
def landing():
|
| 42 |
+
"""Marketing landing page is the homepage; its CTA enters the app at /index.html."""
|
| 43 |
+
page = FRONTEND_DIR / "landing.html"
|
| 44 |
+
if page.is_file():
|
| 45 |
+
return FileResponse(str(page))
|
| 46 |
+
return FileResponse(str(FRONTEND_DIR / "index.html"))
|
| 47 |
+
|
| 48 |
+
|
| 49 |
@app.get("/graph")
|
| 50 |
def graph():
|
| 51 |
"""All nodes + edges for the initial force-graph render."""
|
frontend/landing.css
ADDED
|
@@ -0,0 +1,777 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* ============================================================================
|
| 2 |
+
FORGE β landing page specific styles. Layered on top of styles.css
|
| 3 |
+
============================================================================ */
|
| 4 |
+
|
| 5 |
+
.lp {
|
| 6 |
+
min-height: 100vh;
|
| 7 |
+
position: relative;
|
| 8 |
+
z-index: 1;
|
| 9 |
+
}
|
| 10 |
+
.lp-shell {
|
| 11 |
+
max-width: 1180px;
|
| 12 |
+
margin: 0 auto;
|
| 13 |
+
padding: 0 32px;
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
/* ββ Sticky top nav βββββββββββββββββββββββββββββββββββββββββββββββββββββ */
|
| 17 |
+
.lp-nav {
|
| 18 |
+
position: sticky; top: 0;
|
| 19 |
+
z-index: 20;
|
| 20 |
+
background: linear-gradient(180deg, rgba(15,10,5,0.92) 0%, rgba(15,10,5,0.75) 100%);
|
| 21 |
+
backdrop-filter: blur(10px);
|
| 22 |
+
border-bottom: 1px solid rgba(212, 164, 68, 0.18);
|
| 23 |
+
box-shadow: 0 4px 16px rgba(0,0,0,0.5);
|
| 24 |
+
}
|
| 25 |
+
.lp-nav-inner {
|
| 26 |
+
max-width: 1180px;
|
| 27 |
+
margin: 0 auto;
|
| 28 |
+
padding: 14px 32px;
|
| 29 |
+
display: flex; align-items: center; gap: 24px;
|
| 30 |
+
}
|
| 31 |
+
.lp-nav .brand {
|
| 32 |
+
display: flex; align-items: center; gap: 12px;
|
| 33 |
+
}
|
| 34 |
+
.lp-nav .brand .mark {
|
| 35 |
+
width: 32px; height: 32px;
|
| 36 |
+
display: grid; place-items: center;
|
| 37 |
+
background: radial-gradient(circle at 50% 65%, #4a1c0a 0%, #0f0805 70%);
|
| 38 |
+
border: 1px solid #5a3010;
|
| 39 |
+
box-shadow: inset 0 0 12px rgba(255, 106, 31, 0.55), 0 0 10px rgba(255,106,31,0.20);
|
| 40 |
+
}
|
| 41 |
+
.lp-nav .brand .name {
|
| 42 |
+
font-family: var(--f-display);
|
| 43 |
+
font-size: 22px;
|
| 44 |
+
font-weight: 600;
|
| 45 |
+
letter-spacing: 0.18em;
|
| 46 |
+
color: #f6e4c8;
|
| 47 |
+
text-shadow: 0 1px 0 #000, 0 0 8px rgba(255, 138, 61, 0.25);
|
| 48 |
+
}
|
| 49 |
+
.lp-nav .links {
|
| 50 |
+
margin-left: auto;
|
| 51 |
+
display: flex; align-items: center; gap: 24px;
|
| 52 |
+
font-family: var(--f-display);
|
| 53 |
+
font-size: 11px;
|
| 54 |
+
letter-spacing: 0.22em;
|
| 55 |
+
text-transform: uppercase;
|
| 56 |
+
}
|
| 57 |
+
.lp-nav .links a {
|
| 58 |
+
color: var(--bone-3);
|
| 59 |
+
text-decoration: none;
|
| 60 |
+
padding: 6px 0;
|
| 61 |
+
border-bottom: 1px solid transparent;
|
| 62 |
+
transition: color 160ms ease, border 160ms ease;
|
| 63 |
+
}
|
| 64 |
+
.lp-nav .links a:hover { color: var(--brass-1); border-bottom-color: var(--brass-1); }
|
| 65 |
+
.lp-nav .cta-mini {
|
| 66 |
+
font-family: var(--f-display);
|
| 67 |
+
font-size: 11px;
|
| 68 |
+
letter-spacing: 0.22em;
|
| 69 |
+
text-transform: uppercase;
|
| 70 |
+
padding: 8px 16px;
|
| 71 |
+
color: #fff5e8;
|
| 72 |
+
background: linear-gradient(180deg, #ff8a3d 0%, #c46822 100%);
|
| 73 |
+
border: 1px solid #6a2a08;
|
| 74 |
+
text-decoration: none;
|
| 75 |
+
box-shadow: inset 0 1px 0 rgba(255,255,255,0.25), 0 2px 6px rgba(0,0,0,0.5), 0 0 8px var(--ember-glow);
|
| 76 |
+
}
|
| 77 |
+
.lp-nav .cta-mini:hover {
|
| 78 |
+
background: linear-gradient(180deg, #ffba5e 0%, #ff8a3d 100%);
|
| 79 |
+
box-shadow: inset 0 1px 0 rgba(255,255,255,0.35), 0 2px 8px rgba(0,0,0,0.6), 0 0 16px var(--ember-1);
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
/* ββ Hero βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
|
| 83 |
+
.lp-hero {
|
| 84 |
+
padding: 90px 0 100px;
|
| 85 |
+
position: relative;
|
| 86 |
+
display: grid;
|
| 87 |
+
grid-template-columns: 1.15fr 1fr;
|
| 88 |
+
gap: 60px;
|
| 89 |
+
align-items: center;
|
| 90 |
+
}
|
| 91 |
+
.lp-hero::before {
|
| 92 |
+
/* ember bloom under the hero */
|
| 93 |
+
content: "";
|
| 94 |
+
position: absolute; left: 50%; bottom: -40px;
|
| 95 |
+
width: 80%; height: 220px;
|
| 96 |
+
transform: translateX(-50%);
|
| 97 |
+
background: radial-gradient(ellipse at 50% 100%, rgba(255, 106, 31, 0.18), transparent 60%);
|
| 98 |
+
pointer-events: none;
|
| 99 |
+
}
|
| 100 |
+
.lp-eyebrow {
|
| 101 |
+
font-family: var(--f-mono);
|
| 102 |
+
font-size: 11px;
|
| 103 |
+
letter-spacing: 0.30em;
|
| 104 |
+
text-transform: uppercase;
|
| 105 |
+
color: var(--brass-2);
|
| 106 |
+
margin-bottom: 22px;
|
| 107 |
+
display: inline-flex; align-items: center; gap: 12px;
|
| 108 |
+
}
|
| 109 |
+
.lp-eyebrow::before, .lp-eyebrow::after {
|
| 110 |
+
content: "";
|
| 111 |
+
display: inline-block;
|
| 112 |
+
width: 28px; height: 1px;
|
| 113 |
+
background: linear-gradient(90deg, transparent, var(--brass-2));
|
| 114 |
+
}
|
| 115 |
+
.lp-eyebrow::after { background: linear-gradient(90deg, var(--brass-2), transparent); }
|
| 116 |
+
|
| 117 |
+
.lp-title {
|
| 118 |
+
font-family: var(--f-display);
|
| 119 |
+
font-size: 92px;
|
| 120 |
+
font-weight: 600;
|
| 121 |
+
line-height: 0.92;
|
| 122 |
+
letter-spacing: 0.04em;
|
| 123 |
+
color: #f6e4c8;
|
| 124 |
+
margin: 0 0 28px;
|
| 125 |
+
text-shadow:
|
| 126 |
+
0 1px 0 #000,
|
| 127 |
+
0 2px 0 #000,
|
| 128 |
+
0 0 24px rgba(255, 138, 61, 0.25);
|
| 129 |
+
}
|
| 130 |
+
.lp-title em {
|
| 131 |
+
font-style: normal;
|
| 132 |
+
background: linear-gradient(180deg, #ffba5e 0%, #ff6a1f 70%, #8a3010 100%);
|
| 133 |
+
-webkit-background-clip: text;
|
| 134 |
+
background-clip: text;
|
| 135 |
+
-webkit-text-fill-color: transparent;
|
| 136 |
+
display: inline-block;
|
| 137 |
+
}
|
| 138 |
+
.lp-subtitle {
|
| 139 |
+
font-family: var(--f-serif);
|
| 140 |
+
font-style: italic;
|
| 141 |
+
font-size: 22px;
|
| 142 |
+
line-height: 1.45;
|
| 143 |
+
color: var(--bone-2);
|
| 144 |
+
margin: 0 0 38px;
|
| 145 |
+
max-width: 540px;
|
| 146 |
+
letter-spacing: 0.005em;
|
| 147 |
+
}
|
| 148 |
+
.lp-subtitle strong {
|
| 149 |
+
color: var(--brass-1);
|
| 150 |
+
font-style: normal;
|
| 151 |
+
font-weight: 500;
|
| 152 |
+
letter-spacing: 0.02em;
|
| 153 |
+
}
|
| 154 |
+
.lp-cta-row {
|
| 155 |
+
display: flex; align-items: center; gap: 18px;
|
| 156 |
+
margin-top: 8px;
|
| 157 |
+
}
|
| 158 |
+
.lp-cta-primary {
|
| 159 |
+
font-family: var(--f-display);
|
| 160 |
+
font-size: 13px;
|
| 161 |
+
letter-spacing: 0.26em;
|
| 162 |
+
text-transform: uppercase;
|
| 163 |
+
padding: 16px 28px;
|
| 164 |
+
color: #fff5e8;
|
| 165 |
+
background: linear-gradient(180deg, #ff8a3d 0%, #c46822 100%);
|
| 166 |
+
border: 1px solid #2a1a08;
|
| 167 |
+
text-decoration: none;
|
| 168 |
+
box-shadow:
|
| 169 |
+
inset 0 1px 0 rgba(255,255,255,0.30),
|
| 170 |
+
inset 0 -2px 0 rgba(0,0,0,0.30),
|
| 171 |
+
0 4px 14px rgba(0,0,0,0.5),
|
| 172 |
+
0 0 16px var(--ember-glow);
|
| 173 |
+
position: relative;
|
| 174 |
+
transition: transform 120ms ease, box-shadow 200ms ease;
|
| 175 |
+
cursor: pointer;
|
| 176 |
+
display: inline-flex; align-items: center; gap: 12px;
|
| 177 |
+
}
|
| 178 |
+
.lp-cta-primary::before, .lp-cta-primary::after {
|
| 179 |
+
content: "";
|
| 180 |
+
position: absolute; top: 50%; transform: translateY(-50%);
|
| 181 |
+
width: 6px; height: 6px;
|
| 182 |
+
background: #ffba5e;
|
| 183 |
+
box-shadow: 0 0 6px #ffba5e;
|
| 184 |
+
}
|
| 185 |
+
.lp-cta-primary::before { left: -3px; }
|
| 186 |
+
.lp-cta-primary::after { right: -3px; }
|
| 187 |
+
.lp-cta-primary:hover {
|
| 188 |
+
transform: translateY(-1px);
|
| 189 |
+
box-shadow:
|
| 190 |
+
inset 0 1px 0 rgba(255,255,255,0.40),
|
| 191 |
+
inset 0 -2px 0 rgba(0,0,0,0.30),
|
| 192 |
+
0 6px 18px rgba(0,0,0,0.55),
|
| 193 |
+
0 0 28px var(--ember-1);
|
| 194 |
+
}
|
| 195 |
+
.lp-cta-secondary {
|
| 196 |
+
font-family: var(--f-display);
|
| 197 |
+
font-size: 12px;
|
| 198 |
+
letter-spacing: 0.22em;
|
| 199 |
+
text-transform: uppercase;
|
| 200 |
+
padding: 16px 22px;
|
| 201 |
+
color: var(--bone-2);
|
| 202 |
+
background: transparent;
|
| 203 |
+
border: 1px solid var(--steel-2);
|
| 204 |
+
text-decoration: none;
|
| 205 |
+
}
|
| 206 |
+
.lp-cta-secondary:hover { color: var(--bone-1); border-color: var(--brass-2); }
|
| 207 |
+
|
| 208 |
+
/* ββ Hero right: floating anvil + mini graph demo ββββββββββββββββββββββ */
|
| 209 |
+
.lp-hero-art {
|
| 210 |
+
position: relative;
|
| 211 |
+
min-height: 480px;
|
| 212 |
+
display: grid;
|
| 213 |
+
place-items: center;
|
| 214 |
+
}
|
| 215 |
+
.lp-hero-art::before {
|
| 216 |
+
/* glowing forge ring behind the demo */
|
| 217 |
+
content: "";
|
| 218 |
+
position: absolute;
|
| 219 |
+
width: 480px; height: 480px;
|
| 220 |
+
border-radius: 50%;
|
| 221 |
+
background:
|
| 222 |
+
radial-gradient(circle at 50% 60%, rgba(255, 106, 31, 0.18) 0%, transparent 60%);
|
| 223 |
+
pointer-events: none;
|
| 224 |
+
}
|
| 225 |
+
.lp-hero-art::after {
|
| 226 |
+
content: "";
|
| 227 |
+
position: absolute;
|
| 228 |
+
width: 360px; height: 360px;
|
| 229 |
+
border-radius: 50%;
|
| 230 |
+
border: 1px dashed rgba(212, 164, 68, 0.18);
|
| 231 |
+
animation: gentle-rotate 60s linear infinite;
|
| 232 |
+
}
|
| 233 |
+
.demo-svg {
|
| 234 |
+
position: relative;
|
| 235 |
+
width: 460px; height: 460px;
|
| 236 |
+
display: block;
|
| 237 |
+
}
|
| 238 |
+
|
| 239 |
+
/* ββ Sections βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
|
| 240 |
+
section.lp-section { padding: 80px 0; position: relative; scroll-margin-top: 80px; }
|
| 241 |
+
.lp-section + .lp-section { border-top: 1px solid rgba(212, 164, 68, 0.08); }
|
| 242 |
+
.lp-section-head {
|
| 243 |
+
text-align: center;
|
| 244 |
+
margin-bottom: 56px;
|
| 245 |
+
}
|
| 246 |
+
.lp-section-eyebrow {
|
| 247 |
+
font-family: var(--f-mono);
|
| 248 |
+
font-size: 11px;
|
| 249 |
+
letter-spacing: 0.30em;
|
| 250 |
+
text-transform: uppercase;
|
| 251 |
+
color: var(--brass-1);
|
| 252 |
+
margin-bottom: 14px;
|
| 253 |
+
}
|
| 254 |
+
.lp-section-title {
|
| 255 |
+
font-family: var(--f-display);
|
| 256 |
+
font-size: 44px;
|
| 257 |
+
font-weight: 500;
|
| 258 |
+
letter-spacing: 0.03em;
|
| 259 |
+
color: #f6e4c8;
|
| 260 |
+
margin: 0 0 14px;
|
| 261 |
+
text-shadow: 0 1px 0 #000;
|
| 262 |
+
}
|
| 263 |
+
.lp-section-sub {
|
| 264 |
+
font-family: var(--f-serif);
|
| 265 |
+
font-style: italic;
|
| 266 |
+
font-size: 17px;
|
| 267 |
+
line-height: 1.5;
|
| 268 |
+
color: var(--bone-3);
|
| 269 |
+
max-width: 620px;
|
| 270 |
+
margin: 0 auto;
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
+
/* What it does β three carved tablets */
|
| 274 |
+
.lp-tablets {
|
| 275 |
+
display: grid;
|
| 276 |
+
grid-template-columns: repeat(3, 1fr);
|
| 277 |
+
gap: 24px;
|
| 278 |
+
}
|
| 279 |
+
.lp-tablet {
|
| 280 |
+
position: relative;
|
| 281 |
+
padding: 38px 28px 32px;
|
| 282 |
+
background:
|
| 283 |
+
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='p'><feTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='2' stitchTiles='stitch' seed='5'/><feColorMatrix values='0 0 0 0 0.30 0 0 0 0 0.22 0 0 0 0 0.12 0 0 0 0.14 0'/></filter><rect width='100%25' height='100%25' filter='url(%23p)'/></svg>"),
|
| 284 |
+
linear-gradient(180deg, rgba(40,30,18,0.45) 0%, rgba(15,12,8,0.85) 100%);
|
| 285 |
+
background-blend-mode: overlay, normal;
|
| 286 |
+
border: 1px solid rgba(70, 50, 28, 0.7);
|
| 287 |
+
border-top: 2px solid var(--brass-2);
|
| 288 |
+
box-shadow:
|
| 289 |
+
inset 0 1px 0 rgba(255,255,255,0.04),
|
| 290 |
+
0 8px 24px rgba(0,0,0,0.5);
|
| 291 |
+
}
|
| 292 |
+
.lp-tablet::before, .lp-tablet::after {
|
| 293 |
+
/* brass corner ornaments top-left + top-right */
|
| 294 |
+
content: "";
|
| 295 |
+
position: absolute; top: -1px;
|
| 296 |
+
width: 8px; height: 8px;
|
| 297 |
+
border: 2px solid var(--brass-2);
|
| 298 |
+
}
|
| 299 |
+
.lp-tablet::before { left: -1px; border-right: none; border-bottom: none; }
|
| 300 |
+
.lp-tablet::after { right: -1px; border-left: none; border-bottom: none; }
|
| 301 |
+
.lp-tablet-icon {
|
| 302 |
+
width: 56px; height: 56px;
|
| 303 |
+
margin-bottom: 22px;
|
| 304 |
+
display: grid; place-items: center;
|
| 305 |
+
border: 1px solid rgba(212, 164, 68, 0.30);
|
| 306 |
+
background:
|
| 307 |
+
radial-gradient(circle at 50% 35%, rgba(255, 138, 61, 0.18) 0%, rgba(0,0,0,0) 70%),
|
| 308 |
+
#0a0805;
|
| 309 |
+
color: var(--brass-1);
|
| 310 |
+
position: relative;
|
| 311 |
+
}
|
| 312 |
+
.lp-tablet-icon::before, .lp-tablet-icon::after {
|
| 313 |
+
/* corner ornaments */
|
| 314 |
+
content: "";
|
| 315 |
+
position: absolute;
|
| 316 |
+
width: 4px; height: 4px;
|
| 317 |
+
border: 1px solid var(--brass-2);
|
| 318 |
+
}
|
| 319 |
+
.lp-tablet-icon::before { top: -1px; left: -1px; border-right: none; border-bottom: none; }
|
| 320 |
+
.lp-tablet-icon::after { bottom: -1px; right: -1px; border-left: none; border-top: none; }
|
| 321 |
+
|
| 322 |
+
.lp-tablet-num {
|
| 323 |
+
position: absolute; top: 18px; right: 22px;
|
| 324 |
+
font-family: var(--f-display);
|
| 325 |
+
font-size: 38px;
|
| 326 |
+
font-weight: 600;
|
| 327 |
+
color: rgba(212, 164, 68, 0.20);
|
| 328 |
+
letter-spacing: 0.02em;
|
| 329 |
+
line-height: 1;
|
| 330 |
+
}
|
| 331 |
+
.lp-tablet h3 {
|
| 332 |
+
font-family: var(--f-display);
|
| 333 |
+
font-size: 22px;
|
| 334 |
+
font-weight: 500;
|
| 335 |
+
letter-spacing: 0.02em;
|
| 336 |
+
margin: 0 0 12px;
|
| 337 |
+
color: #fff5e8;
|
| 338 |
+
}
|
| 339 |
+
.lp-tablet p {
|
| 340 |
+
font-family: var(--f-serif);
|
| 341 |
+
font-size: 15px;
|
| 342 |
+
line-height: 1.55;
|
| 343 |
+
color: var(--bone-2);
|
| 344 |
+
margin: 0;
|
| 345 |
+
}
|
| 346 |
+
.lp-tablet p em {
|
| 347 |
+
color: var(--brass-1);
|
| 348 |
+
font-style: italic;
|
| 349 |
+
}
|
| 350 |
+
|
| 351 |
+
/* How to use β alternating numbered rows */
|
| 352 |
+
.lp-steps { display: flex; flex-direction: column; gap: 60px; }
|
| 353 |
+
.lp-step {
|
| 354 |
+
display: grid;
|
| 355 |
+
grid-template-columns: 1fr 1fr;
|
| 356 |
+
gap: 60px;
|
| 357 |
+
align-items: center;
|
| 358 |
+
}
|
| 359 |
+
.lp-step:nth-child(even) .lp-step-text { order: 2; }
|
| 360 |
+
.lp-step:nth-child(even) .lp-step-art { order: 1; }
|
| 361 |
+
.lp-step-num {
|
| 362 |
+
display: inline-block;
|
| 363 |
+
font-family: var(--f-display);
|
| 364 |
+
font-size: 13px;
|
| 365 |
+
letter-spacing: 0.30em;
|
| 366 |
+
text-transform: uppercase;
|
| 367 |
+
color: var(--brass-1);
|
| 368 |
+
padding-bottom: 8px;
|
| 369 |
+
margin-bottom: 14px;
|
| 370 |
+
border-bottom: 1px solid var(--brass-2);
|
| 371 |
+
}
|
| 372 |
+
.lp-step h3 {
|
| 373 |
+
font-family: var(--f-display);
|
| 374 |
+
font-size: 36px;
|
| 375 |
+
font-weight: 500;
|
| 376 |
+
letter-spacing: 0.02em;
|
| 377 |
+
margin: 0 0 18px;
|
| 378 |
+
color: #fff5e8;
|
| 379 |
+
line-height: 1.05;
|
| 380 |
+
}
|
| 381 |
+
.lp-step p {
|
| 382 |
+
font-family: var(--f-serif);
|
| 383 |
+
font-size: 16.5px;
|
| 384 |
+
line-height: 1.6;
|
| 385 |
+
color: var(--bone-2);
|
| 386 |
+
margin: 0 0 14px;
|
| 387 |
+
max-width: 460px;
|
| 388 |
+
}
|
| 389 |
+
.lp-step .quote {
|
| 390 |
+
font-family: var(--f-serif);
|
| 391 |
+
font-style: italic;
|
| 392 |
+
font-size: 13px;
|
| 393 |
+
color: var(--bone-3);
|
| 394 |
+
border-left: 2px solid var(--brass-2);
|
| 395 |
+
padding-left: 14px;
|
| 396 |
+
margin: 18px 0 0;
|
| 397 |
+
max-width: 460px;
|
| 398 |
+
}
|
| 399 |
+
.lp-step-art {
|
| 400 |
+
position: relative;
|
| 401 |
+
min-height: 320px;
|
| 402 |
+
display: grid; place-items: center;
|
| 403 |
+
background:
|
| 404 |
+
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='p'><feTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='2' stitchTiles='stitch' seed='9'/><feColorMatrix values='0 0 0 0 0.25 0 0 0 0 0.20 0 0 0 0 0.10 0 0 0 0.10 0'/></filter><rect width='100%25' height='100%25' filter='url(%23p)'/></svg>"),
|
| 405 |
+
linear-gradient(180deg, rgba(20,14,10,0.6) 0%, rgba(8,6,4,0.85) 100%);
|
| 406 |
+
background-blend-mode: overlay, normal;
|
| 407 |
+
border: 1px solid rgba(60, 42, 22, 0.6);
|
| 408 |
+
padding: 32px;
|
| 409 |
+
}
|
| 410 |
+
|
| 411 |
+
/* Tier system explainer */
|
| 412 |
+
.lp-tiers {
|
| 413 |
+
display: grid;
|
| 414 |
+
grid-template-columns: repeat(3, 1fr);
|
| 415 |
+
gap: 22px;
|
| 416 |
+
}
|
| 417 |
+
.lp-tier {
|
| 418 |
+
padding: 30px 26px;
|
| 419 |
+
background: linear-gradient(180deg, rgba(20,14,10,0.5) 0%, rgba(8,6,4,0.8) 100%);
|
| 420 |
+
border: 1px solid rgba(60, 42, 22, 0.7);
|
| 421 |
+
border-left: 3px solid var(--lp-tier-color, var(--brass-2));
|
| 422 |
+
position: relative;
|
| 423 |
+
}
|
| 424 |
+
.lp-tier-1 { --lp-tier-color: var(--brass-1); }
|
| 425 |
+
.lp-tier-2 { --lp-tier-color: var(--brass-2); }
|
| 426 |
+
.lp-tier-3 { --lp-tier-color: var(--brass-3); }
|
| 427 |
+
|
| 428 |
+
.lp-tier-coin {
|
| 429 |
+
width: 48px; height: 48px;
|
| 430 |
+
border-radius: 50%;
|
| 431 |
+
margin-bottom: 18px;
|
| 432 |
+
border: 1px solid rgba(0,0,0,0.5);
|
| 433 |
+
box-shadow: inset 0 1px 0 rgba(255,255,255,0.18), 0 1px 3px rgba(0,0,0,0.6);
|
| 434 |
+
display: grid; place-items: center;
|
| 435 |
+
font-family: var(--f-display);
|
| 436 |
+
font-size: 17px;
|
| 437 |
+
font-weight: 700;
|
| 438 |
+
color: var(--coal-0);
|
| 439 |
+
letter-spacing: 0.02em;
|
| 440 |
+
}
|
| 441 |
+
.lp-tier-1 .lp-tier-coin { background: radial-gradient(circle at 35% 30%, #ffd09a, #ff8a3d 50%, #6a2a08); box-shadow: 0 0 14px var(--tier1-glow), inset 0 1px 0 rgba(255,255,255,0.25); }
|
| 442 |
+
.lp-tier-2 .lp-tier-coin { background: radial-gradient(circle at 35% 30%, #b8d4f0, #5b9bd8 50%, #1c3a5a); box-shadow: 0 0 8px var(--tier2-glow), inset 0 1px 0 rgba(255,255,255,0.22); }
|
| 443 |
+
.lp-tier-3 .lp-tier-coin { background: radial-gradient(circle at 35% 30%, #cac4b6, #9a9285 50%, #3a3528); box-shadow: 0 0 4px var(--tier3-glow), inset 0 1px 0 rgba(255,255,255,0.18); }
|
| 444 |
+
|
| 445 |
+
.lp-tier-label {
|
| 446 |
+
font-family: var(--f-display);
|
| 447 |
+
font-size: 13px;
|
| 448 |
+
letter-spacing: 0.24em;
|
| 449 |
+
text-transform: uppercase;
|
| 450 |
+
color: var(--lp-tier-color);
|
| 451 |
+
margin-bottom: 6px;
|
| 452 |
+
}
|
| 453 |
+
.lp-tier h4 {
|
| 454 |
+
font-family: var(--f-display);
|
| 455 |
+
font-size: 22px;
|
| 456 |
+
font-weight: 500;
|
| 457 |
+
margin: 0 0 14px;
|
| 458 |
+
color: #fff5e8;
|
| 459 |
+
letter-spacing: 0.01em;
|
| 460 |
+
}
|
| 461 |
+
.lp-tier p {
|
| 462 |
+
font-family: var(--f-serif);
|
| 463 |
+
font-size: 14.5px;
|
| 464 |
+
line-height: 1.55;
|
| 465 |
+
color: var(--bone-2);
|
| 466 |
+
margin: 0 0 14px;
|
| 467 |
+
}
|
| 468 |
+
.lp-tier .example {
|
| 469 |
+
font-family: var(--f-mono);
|
| 470 |
+
font-size: 10.5px;
|
| 471 |
+
letter-spacing: 0.02em;
|
| 472 |
+
color: var(--bone-4);
|
| 473 |
+
padding: 8px 10px;
|
| 474 |
+
background: var(--coal-0);
|
| 475 |
+
border-left: 2px solid var(--lp-tier-color);
|
| 476 |
+
}
|
| 477 |
+
|
| 478 |
+
/* Scraper / live data section */
|
| 479 |
+
.lp-scraper {
|
| 480 |
+
display: grid;
|
| 481 |
+
grid-template-columns: 1.1fr 1fr;
|
| 482 |
+
gap: 60px;
|
| 483 |
+
align-items: center;
|
| 484 |
+
}
|
| 485 |
+
.lp-scraper p { font-family: var(--f-serif); font-size: 16px; line-height: 1.6; color: var(--bone-2); max-width: 520px; }
|
| 486 |
+
.lp-scraper p em { font-style: italic; color: var(--brass-2); }
|
| 487 |
+
.lp-pipeline {
|
| 488 |
+
display: flex; flex-direction: column; gap: 10px;
|
| 489 |
+
padding: 24px;
|
| 490 |
+
background: var(--coal-0);
|
| 491 |
+
border: 1px solid rgba(60, 42, 22, 0.6);
|
| 492 |
+
font-family: var(--f-mono);
|
| 493 |
+
font-size: 11.5px;
|
| 494 |
+
position: relative;
|
| 495 |
+
}
|
| 496 |
+
.lp-pipeline::before {
|
| 497 |
+
content: "scraper.log";
|
| 498 |
+
position: absolute; top: -10px; left: 16px;
|
| 499 |
+
background: var(--coal-0);
|
| 500 |
+
padding: 0 8px;
|
| 501 |
+
font-family: var(--f-display);
|
| 502 |
+
font-size: 10px;
|
| 503 |
+
letter-spacing: 0.20em;
|
| 504 |
+
text-transform: uppercase;
|
| 505 |
+
color: var(--brass-2);
|
| 506 |
+
}
|
| 507 |
+
.lp-pipeline-step {
|
| 508 |
+
display: grid;
|
| 509 |
+
grid-template-columns: auto 1fr auto;
|
| 510 |
+
gap: 12px;
|
| 511 |
+
padding: 8px 0;
|
| 512 |
+
border-bottom: 1px solid rgba(60,42,22,0.4);
|
| 513 |
+
color: var(--bone-2);
|
| 514 |
+
}
|
| 515 |
+
.lp-pipeline-step:last-child { border-bottom: none; }
|
| 516 |
+
.lp-pipeline-step .arrow { color: var(--ember-2); }
|
| 517 |
+
.lp-pipeline-step .src { color: var(--brass-2); }
|
| 518 |
+
.lp-pipeline-step .tier {
|
| 519 |
+
font-family: var(--f-display);
|
| 520 |
+
font-size: 9px;
|
| 521 |
+
padding: 1px 5px;
|
| 522 |
+
letter-spacing: 0.12em;
|
| 523 |
+
color: var(--coal-0);
|
| 524 |
+
text-transform: uppercase;
|
| 525 |
+
font-weight: 600;
|
| 526 |
+
}
|
| 527 |
+
.lp-pipeline-step .tier.t1 { background: var(--brass-1); }
|
| 528 |
+
.lp-pipeline-step .tier.t2 { background: var(--brass-2); color: #fff; }
|
| 529 |
+
.lp-pipeline-step .tier.t3 { background: var(--brass-3); }
|
| 530 |
+
|
| 531 |
+
/* Final CTA strip */
|
| 532 |
+
.lp-finale {
|
| 533 |
+
padding: 120px 0;
|
| 534 |
+
text-align: center;
|
| 535 |
+
position: relative;
|
| 536 |
+
}
|
| 537 |
+
.lp-finale::before {
|
| 538 |
+
content: "";
|
| 539 |
+
position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
|
| 540 |
+
width: 700px; height: 200px;
|
| 541 |
+
background: radial-gradient(ellipse, rgba(255, 106, 31, 0.18) 0%, transparent 70%);
|
| 542 |
+
pointer-events: none;
|
| 543 |
+
}
|
| 544 |
+
.lp-finale-title {
|
| 545 |
+
font-family: var(--f-display);
|
| 546 |
+
font-size: 64px;
|
| 547 |
+
font-weight: 500;
|
| 548 |
+
letter-spacing: 0.04em;
|
| 549 |
+
margin: 0 0 14px;
|
| 550 |
+
color: #f6e4c8;
|
| 551 |
+
position: relative;
|
| 552 |
+
text-shadow: 0 2px 0 #000, 0 0 22px rgba(255, 138, 61, 0.30);
|
| 553 |
+
}
|
| 554 |
+
.lp-finale-sub {
|
| 555 |
+
font-family: var(--f-serif);
|
| 556 |
+
font-style: italic;
|
| 557 |
+
font-size: 18px;
|
| 558 |
+
color: var(--bone-3);
|
| 559 |
+
margin: 0 0 38px;
|
| 560 |
+
position: relative;
|
| 561 |
+
}
|
| 562 |
+
.lp-finale .lp-cta-primary { font-size: 14px; padding: 18px 36px; }
|
| 563 |
+
|
| 564 |
+
.lp-foot {
|
| 565 |
+
border-top: 1px solid rgba(212, 164, 68, 0.10);
|
| 566 |
+
padding: 28px 0 40px;
|
| 567 |
+
text-align: center;
|
| 568 |
+
font-family: var(--f-mono);
|
| 569 |
+
font-size: 10.5px;
|
| 570 |
+
letter-spacing: 0.12em;
|
| 571 |
+
color: var(--bone-4);
|
| 572 |
+
}
|
| 573 |
+
.lp-foot a { color: var(--bone-3); text-decoration: none; border-bottom: 1px dotted var(--bone-4); }
|
| 574 |
+
|
| 575 |
+
/* ββ Hero mini demo: 5 nodes, cyclic state animation βββββββββββββββββββ */
|
| 576 |
+
.demo-svg .lp-node { cursor: default; }
|
| 577 |
+
.demo-svg .lp-aura { fill: none; stroke: none; opacity: 0; }
|
| 578 |
+
.demo-svg .lp-frame-outer { fill: none; stroke: #2a2017; stroke-width: 2.2; }
|
| 579 |
+
.demo-svg .lp-plate { fill: var(--coal-2); stroke: rgba(0,0,0,0.5); stroke-width: 1.5; }
|
| 580 |
+
.demo-svg .lp-gem { fill: var(--type-color, #5fb3d4); opacity: 0.18; }
|
| 581 |
+
.demo-svg .lp-frame { fill: none; stroke: #6b5026; stroke-width: 1.2; }
|
| 582 |
+
.demo-svg .lp-stud { fill: #8a6a32; stroke: #2a2017; stroke-width: 0.6; }
|
| 583 |
+
.demo-svg .lp-icon { transition: stroke 240ms ease, opacity 240ms ease; opacity: 0.9; }
|
| 584 |
+
.demo-svg .lp-ribbon { fill: rgba(11,14,19,0.85); stroke: rgba(107, 80, 38, 0.7); stroke-width: 0.7; }
|
| 585 |
+
.demo-svg .lp-name {
|
| 586 |
+
fill: var(--bone-1);
|
| 587 |
+
font-family: var(--f-display);
|
| 588 |
+
font-size: 11.5px;
|
| 589 |
+
font-weight: 500;
|
| 590 |
+
letter-spacing: 0.04em;
|
| 591 |
+
}
|
| 592 |
+
.demo-svg .lp-lock { opacity: 0; transition: opacity 320ms ease; }
|
| 593 |
+
.demo-svg .lp-chip { opacity: 0; transition: opacity 320ms ease; }
|
| 594 |
+
|
| 595 |
+
/* type-color slots per node */
|
| 596 |
+
.demo-svg .lp-center { --type-color: var(--t-technique); }
|
| 597 |
+
.demo-svg .lp-outer-1 { --type-color: var(--t-technique); }
|
| 598 |
+
.demo-svg .lp-outer-2 { --type-color: var(--t-quantization); }
|
| 599 |
+
.demo-svg .lp-outer-3 { --type-color: var(--t-technique); }
|
| 600 |
+
.demo-svg .lp-outer-4 { --type-color: var(--t-architecture); }
|
| 601 |
+
.demo-svg .lp-outer-5 { --type-color: var(--t-technique); }
|
| 602 |
+
|
| 603 |
+
/* edges: base curves */
|
| 604 |
+
.demo-svg .lp-edge { fill: none; stroke-linecap: round; }
|
| 605 |
+
.demo-svg .lp-edge-breaks { stroke: rgba(200,64,60,0.4); stroke-width: 1.4; }
|
| 606 |
+
.demo-svg .lp-edge-requires,
|
| 607 |
+
.demo-svg .lp-edge-requires-2 { stroke: rgba(255,160,60,0.35); stroke-width: 1.4; }
|
| 608 |
+
.demo-svg .lp-edge-compatible,
|
| 609 |
+
.demo-svg .lp-edge-compatible-2 { stroke: rgba(212,164,68,0.20); stroke-width: 1.0; }
|
| 610 |
+
|
| 611 |
+
/* center β selected (red-hot) */
|
| 612 |
+
.demo-svg .lp-center .lp-plate { animation: lp-plate-select 8s ease-in-out infinite; }
|
| 613 |
+
.demo-svg .lp-center .lp-frame { animation: lp-frame-select 8s ease-in-out infinite; }
|
| 614 |
+
.demo-svg .lp-center .lp-frame-outer { animation: lp-frame-outer-select 8s ease-in-out infinite; }
|
| 615 |
+
.demo-svg .lp-center .lp-aura { animation: lp-aura-select 8s ease-in-out infinite; }
|
| 616 |
+
.demo-svg .lp-center .lp-stud { animation: lp-stud-select 8s ease-in-out infinite; }
|
| 617 |
+
.demo-svg .lp-center .lp-gem { animation: lp-gem-select 8s ease-in-out infinite; }
|
| 618 |
+
.demo-svg .lp-center .lp-icon { animation: lp-icon-select 8s ease-in-out infinite; }
|
| 619 |
+
.demo-svg .lp-center .lp-name { animation: lp-name-select 8s ease-in-out infinite; }
|
| 620 |
+
.demo-svg .lp-center .lp-ribbon { animation: lp-ribbon-select 8s ease-in-out infinite; }
|
| 621 |
+
|
| 622 |
+
@keyframes lp-plate-select {
|
| 623 |
+
0%, 12%, 92%, 100% { fill: var(--coal-2); filter: none; }
|
| 624 |
+
18%, 86% { fill: url(#lp-molten); filter: url(#lp-ember); }
|
| 625 |
+
}
|
| 626 |
+
@keyframes lp-frame-select {
|
| 627 |
+
0%, 12%, 92%, 100% { stroke: #6b5026; stroke-width: 1.2; }
|
| 628 |
+
18%, 86% { stroke: #d4a049; stroke-width: 1.5; }
|
| 629 |
+
}
|
| 630 |
+
@keyframes lp-frame-outer-select {
|
| 631 |
+
0%, 12%, 92%, 100% { stroke: #2a2017; }
|
| 632 |
+
18%, 86% { stroke: #3a1a08; }
|
| 633 |
+
}
|
| 634 |
+
@keyframes lp-aura-select {
|
| 635 |
+
0%, 12%, 92%, 100% { opacity: 0; stroke: var(--ember-1); stroke-width: 1.5; fill: none; }
|
| 636 |
+
18% { opacity: 1; stroke: var(--ember-1); stroke-width: 2; fill: none; }
|
| 637 |
+
50% { opacity: 0.4; stroke: var(--ember-1); stroke-width: 4; fill: none; }
|
| 638 |
+
86% { opacity: 1; stroke: var(--ember-1); stroke-width: 2; fill: none; }
|
| 639 |
+
}
|
| 640 |
+
@keyframes lp-stud-select {
|
| 641 |
+
0%, 12%, 92%, 100% { fill: #8a6a32; stroke: #2a2017; }
|
| 642 |
+
18%, 86% { fill: #d4a049; stroke: #3a1a08; }
|
| 643 |
+
}
|
| 644 |
+
@keyframes lp-gem-select {
|
| 645 |
+
0%, 12%, 92%, 100% { fill: var(--type-color); opacity: 0.18; }
|
| 646 |
+
18%, 86% { fill: var(--ember-1); opacity: 0.55; }
|
| 647 |
+
}
|
| 648 |
+
@keyframes lp-icon-select {
|
| 649 |
+
0%, 12%, 92%, 100% { stroke: var(--type-color); opacity: 0.9; }
|
| 650 |
+
18%, 86% { stroke: #fff5e8; opacity: 1; }
|
| 651 |
+
}
|
| 652 |
+
@keyframes lp-name-select {
|
| 653 |
+
0%, 12%, 92%, 100% { fill: var(--bone-1); }
|
| 654 |
+
18%, 86% { fill: #fff5e8; }
|
| 655 |
+
}
|
| 656 |
+
@keyframes lp-ribbon-select {
|
| 657 |
+
0%, 12%, 92%, 100% { fill: rgba(11,14,19,0.85); stroke: rgba(107, 80, 38, 0.7); }
|
| 658 |
+
18%, 86% { fill: rgba(40,15,5,0.92); stroke: #d4a049; }
|
| 659 |
+
}
|
| 660 |
+
|
| 661 |
+
/* outer-1: BLOCKED */
|
| 662 |
+
.demo-svg .lp-outer-1 .lp-plate { animation: lp-plate-block 8s ease-in-out infinite; }
|
| 663 |
+
.demo-svg .lp-outer-1 .lp-frame { animation: lp-frame-block 8s ease-in-out infinite; }
|
| 664 |
+
.demo-svg .lp-outer-1 .lp-icon { animation: lp-icon-block 8s ease-in-out infinite; }
|
| 665 |
+
.demo-svg .lp-outer-1 .lp-aura { animation: lp-aura-block 8s ease-in-out infinite; }
|
| 666 |
+
.demo-svg .lp-outer-1 .lp-stud { animation: lp-stud-block 8s ease-in-out infinite; }
|
| 667 |
+
.demo-svg .lp-outer-1 .lp-gem { animation: lp-gem-fade 8s ease-in-out infinite; }
|
| 668 |
+
.demo-svg .lp-outer-1 .lp-name { animation: lp-name-block 8s ease-in-out infinite; }
|
| 669 |
+
.demo-svg .lp-outer-1 .lp-lock { animation: lp-lock-show 8s ease-in-out infinite; }
|
| 670 |
+
|
| 671 |
+
@keyframes lp-plate-block {
|
| 672 |
+
0%, 12%, 92%, 100% { fill: var(--coal-2); filter: none; opacity: 1; }
|
| 673 |
+
18%, 86% { fill: var(--coal-1); filter: grayscale(100%) brightness(0.55); opacity: 0.55; }
|
| 674 |
+
}
|
| 675 |
+
@keyframes lp-frame-block {
|
| 676 |
+
0%, 12%, 92%, 100% { stroke: #6b5026; }
|
| 677 |
+
18%, 86% { stroke: var(--rust-2); }
|
| 678 |
+
}
|
| 679 |
+
@keyframes lp-icon-block {
|
| 680 |
+
0%, 12%, 92%, 100% { stroke: var(--type-color); opacity: 0.9; }
|
| 681 |
+
18%, 86% { stroke: var(--rust); opacity: 0.45; }
|
| 682 |
+
}
|
| 683 |
+
@keyframes lp-aura-block {
|
| 684 |
+
0%, 12%, 92%, 100% { opacity: 0; }
|
| 685 |
+
18%, 86% { opacity: 0.85; stroke: var(--rust); stroke-width: 1.2; fill: none; }
|
| 686 |
+
}
|
| 687 |
+
@keyframes lp-stud-block {
|
| 688 |
+
0%, 12%, 92%, 100% { fill: #8a6a32; }
|
| 689 |
+
18%, 86% { fill: var(--rust-2); }
|
| 690 |
+
}
|
| 691 |
+
@keyframes lp-gem-fade {
|
| 692 |
+
0%, 12%, 92%, 100% { opacity: 0.18; }
|
| 693 |
+
18%, 86% { opacity: 0; }
|
| 694 |
+
}
|
| 695 |
+
@keyframes lp-name-block {
|
| 696 |
+
0%, 12%, 92%, 100% { fill: var(--bone-1); }
|
| 697 |
+
18%, 86% { fill: var(--rust); opacity: 0.7; }
|
| 698 |
+
}
|
| 699 |
+
@keyframes lp-lock-show {
|
| 700 |
+
0%, 14%, 92%, 100% { opacity: 0; }
|
| 701 |
+
20%, 86% { opacity: 1; }
|
| 702 |
+
}
|
| 703 |
+
|
| 704 |
+
/* outer-2: CONDITIONAL ("needs Β· add") */
|
| 705 |
+
.demo-svg .lp-outer-2 .lp-plate { animation: lp-plate-cond 8s ease-in-out infinite; }
|
| 706 |
+
.demo-svg .lp-outer-2 .lp-frame { animation: lp-frame-cond 8s ease-in-out infinite; }
|
| 707 |
+
.demo-svg .lp-outer-2 .lp-icon { animation: lp-icon-cond 8s ease-in-out infinite; }
|
| 708 |
+
.demo-svg .lp-outer-2 .lp-aura { animation: lp-aura-cond 8s ease-in-out infinite; }
|
| 709 |
+
.demo-svg .lp-outer-2 .lp-stud { animation: lp-stud-cond 8s ease-in-out infinite; }
|
| 710 |
+
.demo-svg .lp-outer-2 .lp-gem { animation: lp-gem-fade 8s ease-in-out infinite; }
|
| 711 |
+
.demo-svg .lp-outer-2 .lp-name { animation: lp-name-cond 8s ease-in-out infinite; }
|
| 712 |
+
.demo-svg .lp-outer-2 .lp-chip { animation: lp-chip-show 8s ease-in-out infinite; }
|
| 713 |
+
|
| 714 |
+
@keyframes lp-plate-cond {
|
| 715 |
+
0%, 12%, 92%, 100% { fill: var(--coal-2); filter: none; opacity: 1; }
|
| 716 |
+
18%, 86% { fill: var(--coal-1); filter: grayscale(85%) brightness(0.7); opacity: 0.55; }
|
| 717 |
+
}
|
| 718 |
+
@keyframes lp-frame-cond {
|
| 719 |
+
0%, 12%, 92%, 100% { stroke: #6b5026; }
|
| 720 |
+
18%, 86% { stroke: #3a2f1c; }
|
| 721 |
+
}
|
| 722 |
+
@keyframes lp-icon-cond {
|
| 723 |
+
0%, 12%, 92%, 100% { stroke: var(--type-color); opacity: 0.9; }
|
| 724 |
+
18%, 86% { stroke: var(--bone-4); opacity: 0.5; }
|
| 725 |
+
}
|
| 726 |
+
@keyframes lp-aura-cond {
|
| 727 |
+
0%, 12%, 92%, 100% { opacity: 0; }
|
| 728 |
+
18%, 86% { opacity: 0.7; stroke: var(--amber); stroke-width: 1; fill: none; stroke-dasharray: 3 4; }
|
| 729 |
+
}
|
| 730 |
+
@keyframes lp-stud-cond {
|
| 731 |
+
0%, 12%, 92%, 100% { fill: #8a6a32; }
|
| 732 |
+
18%, 86% { fill: #3a2f1c; }
|
| 733 |
+
}
|
| 734 |
+
@keyframes lp-name-cond {
|
| 735 |
+
0%, 12%, 92%, 100% { fill: var(--bone-1); }
|
| 736 |
+
18%, 86% { fill: var(--bone-3); }
|
| 737 |
+
}
|
| 738 |
+
@keyframes lp-chip-show {
|
| 739 |
+
0%, 14%, 92%, 100% { opacity: 0; }
|
| 740 |
+
22%, 86% { opacity: 1; }
|
| 741 |
+
}
|
| 742 |
+
|
| 743 |
+
/* Edges: glow during the selected window */
|
| 744 |
+
.demo-svg .lp-edge-breaks { animation: lp-edge-breaks-anim 8s ease-in-out infinite; }
|
| 745 |
+
.demo-svg .lp-edge-requires { animation: lp-edge-requires-anim 8s ease-in-out infinite; }
|
| 746 |
+
.demo-svg .lp-edge-requires-2 { animation: lp-edge-requires-anim 8s ease-in-out infinite; }
|
| 747 |
+
.demo-svg .lp-edge-compatible,
|
| 748 |
+
.demo-svg .lp-edge-compatible-2 { animation: lp-edge-compat-anim 8s ease-in-out infinite; }
|
| 749 |
+
|
| 750 |
+
@keyframes lp-edge-breaks-anim {
|
| 751 |
+
0%, 12%, 92%, 100% { stroke: rgba(200,64,60,0.4); stroke-width: 1.4; filter: none; }
|
| 752 |
+
18%, 86% { stroke: var(--rust); stroke-width: 2.4; filter: drop-shadow(0 0 7px rgba(200,64,60,1)); }
|
| 753 |
+
}
|
| 754 |
+
@keyframes lp-edge-requires-anim {
|
| 755 |
+
0%, 12%, 92%, 100% { stroke: rgba(255,160,60,0.35); stroke-width: 1.4; filter: none; }
|
| 756 |
+
18%, 86% { stroke: var(--ember-2); stroke-width: 2.2; filter: drop-shadow(0 0 6px var(--ember-glow)); }
|
| 757 |
+
}
|
| 758 |
+
@keyframes lp-edge-compat-anim {
|
| 759 |
+
0%, 12%, 92%, 100% { stroke: rgba(212,164,68,0.20); stroke-width: 1.0; }
|
| 760 |
+
18%, 86% { stroke: rgba(255,191,90,0.65); stroke-width: 1.6; filter: drop-shadow(0 0 4px rgba(255,138,61,0.4)); }
|
| 761 |
+
}
|
| 762 |
+
|
| 763 |
+
/* ββ Responsive ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
|
| 764 |
+
@media (max-width: 920px) {
|
| 765 |
+
.lp-shell { padding: 0 22px; }
|
| 766 |
+
.lp-hero { grid-template-columns: 1fr; gap: 30px; padding: 60px 0 70px; }
|
| 767 |
+
.lp-hero-art { min-height: 320px; }
|
| 768 |
+
.lp-title { font-size: 60px; }
|
| 769 |
+
.lp-section-title { font-size: 32px; }
|
| 770 |
+
.lp-tablets { grid-template-columns: 1fr; }
|
| 771 |
+
.lp-step { grid-template-columns: 1fr; gap: 20px; }
|
| 772 |
+
.lp-step:nth-child(even) .lp-step-text { order: 1; }
|
| 773 |
+
.lp-step:nth-child(even) .lp-step-art { order: 2; }
|
| 774 |
+
.lp-tiers { grid-template-columns: 1fr; }
|
| 775 |
+
.lp-scraper { grid-template-columns: 1fr; }
|
| 776 |
+
.lp-finale-title { font-size: 42px; }
|
| 777 |
+
}
|
frontend/landing.html
ADDED
|
@@ -0,0 +1,629 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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">
|
| 6 |
+
<title>Forge β compatibility graph for ML training</title>
|
| 7 |
+
<meta name="description" content="Assemble a training recipe from real practitioner evidence. Watch incompatible tools dim. Forge what works.">
|
| 8 |
+
|
| 9 |
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
| 10 |
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
| 11 |
+
<link href="https://fonts.googleapis.com/css2?family=Cinzel:wght@400;500;600;700&family=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;1,400;1,500&family=Geist:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
| 12 |
+
|
| 13 |
+
<link rel="stylesheet" href="styles.css">
|
| 14 |
+
<link rel="stylesheet" href="landing.css">
|
| 15 |
+
|
| 16 |
+
<style>
|
| 17 |
+
/* Override styles.css app-shell lock so the landing scrolls naturally */
|
| 18 |
+
html, body { height: auto !important; overflow: auto !important; }
|
| 19 |
+
html { scroll-behavior: smooth; }
|
| 20 |
+
|
| 21 |
+
/* More intense ember rain β bigger sparks, more of them, brighter trails */
|
| 22 |
+
.sparks { z-index: 0; }
|
| 23 |
+
.sparks span {
|
| 24 |
+
width: 3px; height: 3px;
|
| 25 |
+
background: var(--ember-2);
|
| 26 |
+
box-shadow:
|
| 27 |
+
0 0 8px var(--ember-1),
|
| 28 |
+
0 0 18px rgba(255, 106, 31, 0.55),
|
| 29 |
+
0 0 2px #fff5e8;
|
| 30 |
+
opacity: 0;
|
| 31 |
+
}
|
| 32 |
+
.sparks span.big {
|
| 33 |
+
width: 4px; height: 4px;
|
| 34 |
+
box-shadow:
|
| 35 |
+
0 0 12px var(--ember-1),
|
| 36 |
+
0 0 28px var(--ember-2),
|
| 37 |
+
0 0 3px #fff5e8;
|
| 38 |
+
}
|
| 39 |
+
.sparks span.trail {
|
| 40 |
+
width: 2px; height: 14px;
|
| 41 |
+
border-radius: 2px;
|
| 42 |
+
background: linear-gradient(180deg, transparent 0%, var(--ember-2) 60%, var(--ember-1) 100%);
|
| 43 |
+
box-shadow: 0 0 6px var(--ember-1);
|
| 44 |
+
}
|
| 45 |
+
@keyframes spark-fall {
|
| 46 |
+
0% { transform: translateY(-8vh) translateX(0); opacity: 0; }
|
| 47 |
+
8% { opacity: 0.9; }
|
| 48 |
+
50% { transform: translateY(50vh) translateX(var(--drift, 0px)); opacity: 0.9; }
|
| 49 |
+
100% { transform: translateY(110vh) translateX(calc(var(--drift, 0px) * 2)); opacity: 0; }
|
| 50 |
+
}
|
| 51 |
+
</style>
|
| 52 |
+
</head>
|
| 53 |
+
<body>
|
| 54 |
+
<div class="sparks">
|
| 55 |
+
<span style="left: 4%; animation-duration: 14s; animation-delay: -2s; --drift: -18px;"></span>
|
| 56 |
+
<span class="big" style="left: 9%; animation-duration: 18s; animation-delay: -10s; --drift: 8px;"></span>
|
| 57 |
+
<span style="left: 14%; animation-duration: 11s; animation-delay: -6s; --drift: -12px;"></span>
|
| 58 |
+
<span class="trail" style="left: 18%; animation-duration: 9s; animation-delay: -3s; --drift: 4px;"></span>
|
| 59 |
+
<span style="left: 23%; animation-duration: 16s; animation-delay: -14s; --drift: -20px;"></span>
|
| 60 |
+
<span class="big" style="left: 28%; animation-duration: 13s; animation-delay: -7s; --drift: 14px;"></span>
|
| 61 |
+
<span style="left: 33%; animation-duration: 19s; animation-delay: -1s; --drift: -8px;"></span>
|
| 62 |
+
<span class="trail" style="left: 38%; animation-duration: 8s; animation-delay: -5s; --drift: -10px;"></span>
|
| 63 |
+
<span style="left: 42%; animation-duration: 15s; animation-delay: -11s; --drift: 22px;"></span>
|
| 64 |
+
<span class="big" style="left: 47%; animation-duration: 12s; animation-delay: -8s; --drift: -6px;"></span>
|
| 65 |
+
<span style="left: 52%; animation-duration: 17s; animation-delay: -13s; --drift: 12px;"></span>
|
| 66 |
+
<span class="trail" style="left: 56%; animation-duration: 10s; animation-delay: -4s; --drift: -18px;"></span>
|
| 67 |
+
<span style="left: 60%; animation-duration: 14s; animation-delay: -9s; --drift: 6px;"></span>
|
| 68 |
+
<span class="big" style="left: 65%; animation-duration: 16s; animation-delay: -2s; --drift: -14px;"></span>
|
| 69 |
+
<span style="left: 70%; animation-duration: 11s; animation-delay: -12s; --drift: 18px;"></span>
|
| 70 |
+
<span class="trail" style="left: 75%; animation-duration: 9s; animation-delay: -6s; --drift: -10px;"></span>
|
| 71 |
+
<span style="left: 79%; animation-duration: 18s; animation-delay: -15s; --drift: 8px;"></span>
|
| 72 |
+
<span class="big" style="left: 83%; animation-duration: 13s; animation-delay: -3s; --drift: -22px;"></span>
|
| 73 |
+
<span style="left: 87%; animation-duration: 15s; animation-delay: -8s; --drift: 14px;"></span>
|
| 74 |
+
<span class="trail" style="left: 91%; animation-duration: 10s; animation-delay: -1s; --drift: -4px;"></span>
|
| 75 |
+
<span style="left: 95%; animation-duration: 17s; animation-delay: -11s; --drift: 16px;"></span>
|
| 76 |
+
<span class="big" style="left: 98%; animation-duration: 12s; animation-delay: -7s; --drift: -12px;"></span>
|
| 77 |
+
</div>
|
| 78 |
+
|
| 79 |
+
<div class="lp">
|
| 80 |
+
|
| 81 |
+
<!-- ββ Sticky nav ββββββββββββββββββββββββββββββββββββββββββββββββββββ -->
|
| 82 |
+
<nav class="lp-nav">
|
| 83 |
+
<div class="lp-nav-inner">
|
| 84 |
+
<div class="brand">
|
| 85 |
+
<div class="mark">
|
| 86 |
+
<svg width="20" height="20" viewBox="0 0 32 32" fill="none">
|
| 87 |
+
<path d="M5 14 h17 l3 -3 h4 v4 h-3 l-2 2 h-3 v4 h2 v3 h-13 v-3 h2 v-4 h-7 z" fill="#c4934e" stroke="#2a1a08" stroke-width="0.7" stroke-linejoin="round"/>
|
| 88 |
+
<rect x="10" y="25" width="13" height="2" fill="#2a1a08"/>
|
| 89 |
+
<circle cx="17" cy="15" r="1.2" fill="#ffba5e"/>
|
| 90 |
+
</svg>
|
| 91 |
+
</div>
|
| 92 |
+
<div class="name">FORGE</div>
|
| 93 |
+
</div>
|
| 94 |
+
<div class="links">
|
| 95 |
+
<a href="#what">What</a>
|
| 96 |
+
<a href="#how">How</a>
|
| 97 |
+
<a href="#tiers">Tiers</a>
|
| 98 |
+
<a href="#scraper">Scraper</a>
|
| 99 |
+
</div>
|
| 100 |
+
<a class="cta-mini" href="index.html">Enter the Forge β</a>
|
| 101 |
+
</div>
|
| 102 |
+
</nav>
|
| 103 |
+
|
| 104 |
+
<!-- ββ Hero ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ -->
|
| 105 |
+
<section class="lp-hero lp-shell">
|
| 106 |
+
<div class="lp-hero-text">
|
| 107 |
+
<div class="lp-eyebrow">a bright data hackathon submission Β· 2026</div>
|
| 108 |
+
<h1 class="lp-title">Forge a<br/><em>training recipe</em><br/>that actually runs.</h1>
|
| 109 |
+
<p class="lp-subtitle">
|
| 110 |
+
A live <strong>compatibility graph</strong> for ML training components.
|
| 111 |
+
Pick your optimizer, scheduler, quantization, technique. Incompatible tools
|
| 112 |
+
<strong>grey out instantly</strong> with cited evidence from real practitioner runs.
|
| 113 |
+
Greyed means <em>not yet satisfied</em>, not forbidden β add the missing
|
| 114 |
+
ingredient and watch it re-light.
|
| 115 |
+
</p>
|
| 116 |
+
<div class="lp-cta-row">
|
| 117 |
+
<a href="index.html" class="lp-cta-primary">
|
| 118 |
+
Enter the Forge
|
| 119 |
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round">
|
| 120 |
+
<path d="M5 12h14M13 6l6 6-6 6"/>
|
| 121 |
+
</svg>
|
| 122 |
+
</a>
|
| 123 |
+
<a href="#what" class="lp-cta-secondary">Read first</a>
|
| 124 |
+
</div>
|
| 125 |
+
</div>
|
| 126 |
+
|
| 127 |
+
<!-- Mini demo: 5 nodes, looped state animation -->
|
| 128 |
+
<div class="lp-hero-art">
|
| 129 |
+
<svg class="demo-svg" viewBox="0 0 460 460">
|
| 130 |
+
<defs>
|
| 131 |
+
<radialGradient id="lp-molten" cx="50%" cy="55%" r="65%">
|
| 132 |
+
<stop offset="0%" stop-color="#5a1f0a"/>
|
| 133 |
+
<stop offset="35%" stop-color="#3a1408"/>
|
| 134 |
+
<stop offset="70%" stop-color="#1a0807"/>
|
| 135 |
+
<stop offset="100%" stop-color="#0a0303"/>
|
| 136 |
+
</radialGradient>
|
| 137 |
+
<filter id="lp-ember" x="-50%" y="-50%" width="200%" height="200%">
|
| 138 |
+
<feGaussianBlur stdDeviation="2.4" result="b"/>
|
| 139 |
+
<feFlood flood-color="#ff6a1f" flood-opacity="0.55"/>
|
| 140 |
+
<feComposite in2="b" operator="in"/>
|
| 141 |
+
<feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>
|
| 142 |
+
</filter>
|
| 143 |
+
<radialGradient id="lp-brass-t1" cx="40%" cy="35%" r="75%">
|
| 144 |
+
<stop offset="0%" stop-color="#ffd09a"/>
|
| 145 |
+
<stop offset="45%" stop-color="#ff8a3d"/>
|
| 146 |
+
<stop offset="100%" stop-color="#6a2a08"/>
|
| 147 |
+
</radialGradient>
|
| 148 |
+
<radialGradient id="lp-brass-t2" cx="40%" cy="35%" r="75%">
|
| 149 |
+
<stop offset="0%" stop-color="#b8d4f0"/>
|
| 150 |
+
<stop offset="45%" stop-color="#5b9bd8"/>
|
| 151 |
+
<stop offset="100%" stop-color="#1c3a5a"/>
|
| 152 |
+
</radialGradient>
|
| 153 |
+
<radialGradient id="lp-brass-t3" cx="40%" cy="35%" r="75%">
|
| 154 |
+
<stop offset="0%" stop-color="#cac4b6"/>
|
| 155 |
+
<stop offset="45%" stop-color="#9a9285"/>
|
| 156 |
+
<stop offset="100%" stop-color="#3a3528"/>
|
| 157 |
+
</radialGradient>
|
| 158 |
+
</defs>
|
| 159 |
+
|
| 160 |
+
<!-- Curved edges (drawn first, behind nodes) -->
|
| 161 |
+
<g class="lp-edges">
|
| 162 |
+
<path class="lp-edge lp-edge-breaks" d="M 230 230 Q 270 100 320 90"/>
|
| 163 |
+
<path class="lp-edge lp-edge-requires" d="M 230 230 Q 350 220 380 250"/>
|
| 164 |
+
<path class="lp-edge lp-edge-compatible" d="M 230 230 Q 260 360 320 380"/>
|
| 165 |
+
<path class="lp-edge lp-edge-requires-2" d="M 230 230 Q 120 280 80 270"/>
|
| 166 |
+
<path class="lp-edge lp-edge-compatible-2" d="M 230 230 Q 110 130 130 90"/>
|
| 167 |
+
</g>
|
| 168 |
+
|
| 169 |
+
<!-- Center node β the "ingredient on the anvil" / selected -->
|
| 170 |
+
<g class="lp-node lp-center" transform="translate(230, 230)">
|
| 171 |
+
<polygon class="lp-aura" points="-13.3,-32 13.3,-32 32,-13.3 32,13.3 13.3,32 -13.3,32 -32,13.3 -32,-13.3" transform="scale(1.3)"/>
|
| 172 |
+
<polygon class="lp-frame-outer" points="-13.3,-32 13.3,-32 32,-13.3 32,13.3 13.3,32 -13.3,32 -32,13.3 -32,-13.3"/>
|
| 173 |
+
<polygon class="lp-plate" points="-11.2,-27 11.2,-27 27,-11.2 27,11.2 11.2,27 -11.2,27 -27,11.2 -27,-11.2"/>
|
| 174 |
+
<ellipse class="lp-gem" cx="0" cy="-2" rx="14" ry="11"/>
|
| 175 |
+
<polygon class="lp-frame" points="-11.2,-27 11.2,-27 27,-11.2 27,11.2 11.2,27 -11.2,27 -27,11.2 -27,-11.2"/>
|
| 176 |
+
<g class="lp-icon" stroke="#fff5e8" fill="none" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" transform="translate(-12,-14)">
|
| 177 |
+
<path d="M12 3l9 16H3z"/><path d="M12 9l4 7H8z"/>
|
| 178 |
+
</g>
|
| 179 |
+
<circle class="lp-stud" cx="-22.6" cy="-22.6" r="1.8"/>
|
| 180 |
+
<circle class="lp-stud" cx="22.6" cy="-22.6" r="1.8"/>
|
| 181 |
+
<circle class="lp-stud" cx="22.6" cy="22.6" r="1.8"/>
|
| 182 |
+
<circle class="lp-stud" cx="-22.6" cy="22.6" r="1.8"/>
|
| 183 |
+
<g class="lp-seal" transform="translate(22, -22)">
|
| 184 |
+
<circle r="8.5" fill="url(#lp-brass-t1)" stroke="#1a1208"/>
|
| 185 |
+
<text y="2.5" text-anchor="middle" font-family="Cinzel" font-size="8" font-weight="700" fill="#1a1208">T1</text>
|
| 186 |
+
</g>
|
| 187 |
+
<path class="lp-ribbon" d="M -33 33 L -38 47 L -28 44 L -22 48 L -16 44 L -10 48 L -4 44 L 2 48 L 8 44 L 14 48 L 20 44 L 26 48 L 34 47 L 33 33 Z"/>
|
| 188 |
+
<text class="lp-name" y="44.5" text-anchor="middle">QLoRA</text>
|
| 189 |
+
</g>
|
| 190 |
+
|
| 191 |
+
<!-- Outer nodes -->
|
| 192 |
+
<g class="lp-node lp-outer-1" transform="translate(345, 90)"> <!-- BLOCKED (Full Fine-Tune) -->
|
| 193 |
+
<polygon class="lp-aura" points="-13.3,-32 13.3,-32 32,-13.3 32,13.3 13.3,32 -13.3,32 -32,13.3 -32,-13.3" transform="scale(1.3)"/>
|
| 194 |
+
<polygon class="lp-frame-outer" points="-13.3,-32 13.3,-32 32,-13.3 32,13.3 13.3,32 -13.3,32 -32,13.3 -32,-13.3"/>
|
| 195 |
+
<polygon class="lp-plate" points="-11.2,-27 11.2,-27 27,-11.2 27,11.2 11.2,27 -11.2,27 -27,11.2 -27,-11.2"/>
|
| 196 |
+
<ellipse class="lp-gem" cx="0" cy="-2" rx="14" ry="11"/>
|
| 197 |
+
<polygon class="lp-frame" points="-11.2,-27 11.2,-27 27,-11.2 27,11.2 11.2,27 -11.2,27 -27,11.2 -27,-11.2"/>
|
| 198 |
+
<g class="lp-icon" stroke="#fff5e8" fill="none" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" transform="translate(-12,-14)">
|
| 199 |
+
<path d="M12 3l9 16H3z"/><path d="M12 9l4 7H8z"/>
|
| 200 |
+
</g>
|
| 201 |
+
<circle class="lp-stud" cx="-22.6" cy="-22.6" r="1.8"/>
|
| 202 |
+
<circle class="lp-stud" cx="22.6" cy="-22.6" r="1.8"/>
|
| 203 |
+
<circle class="lp-stud" cx="22.6" cy="22.6" r="1.8"/>
|
| 204 |
+
<circle class="lp-stud" cx="-22.6" cy="22.6" r="1.8"/>
|
| 205 |
+
<g class="lp-seal" transform="translate(22, -22)">
|
| 206 |
+
<circle r="8.5" fill="url(#lp-brass-t1)" stroke="#1a1208"/>
|
| 207 |
+
<text y="2.5" text-anchor="middle" font-family="Cinzel" font-size="8" font-weight="700" fill="#1a1208">T1</text>
|
| 208 |
+
</g>
|
| 209 |
+
<g class="lp-lock">
|
| 210 |
+
<path d="M -5 -2 v -4 a 5 5 0 0 1 10 0 v 4" fill="none" stroke="#cfc8b8" stroke-width="1.1" stroke-linecap="round"/>
|
| 211 |
+
<rect x="-7" y="-2" width="14" height="11" rx="1.5" fill="#8a2520" stroke="#cfc8b8" stroke-width="0.6"/>
|
| 212 |
+
<circle cx="0" cy="2" r="1.4" fill="#07090c"/>
|
| 213 |
+
</g>
|
| 214 |
+
<text class="lp-name" y="48" text-anchor="middle">Full FT</text>
|
| 215 |
+
</g>
|
| 216 |
+
|
| 217 |
+
<g class="lp-node lp-outer-2" transform="translate(385, 270)"> <!-- NEEDED β conditional (bnb 4-bit) -->
|
| 218 |
+
<polygon class="lp-aura" points="-13.3,-32 13.3,-32 32,-13.3 32,13.3 13.3,32 -13.3,32 -32,13.3 -32,-13.3" transform="scale(1.3)"/>
|
| 219 |
+
<polygon class="lp-frame-outer" points="-13.3,-32 13.3,-32 32,-13.3 32,13.3 13.3,32 -13.3,32 -32,13.3 -32,-13.3"/>
|
| 220 |
+
<polygon class="lp-plate" points="-11.2,-27 11.2,-27 27,-11.2 27,11.2 11.2,27 -11.2,27 -27,11.2 -27,-11.2"/>
|
| 221 |
+
<ellipse class="lp-gem" cx="0" cy="-2" rx="14" ry="11"/>
|
| 222 |
+
<polygon class="lp-frame" points="-11.2,-27 11.2,-27 27,-11.2 27,11.2 11.2,27 -11.2,27 -27,11.2 -27,-11.2"/>
|
| 223 |
+
<g class="lp-icon" stroke="#fff5e8" fill="none" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" transform="translate(-12,-14)">
|
| 224 |
+
<rect x="4" y="13" width="3" height="7" rx="0.5"/><rect x="10.5" y="9" width="3" height="11" rx="0.5"/><rect x="17" y="5" width="3" height="15" rx="0.5"/>
|
| 225 |
+
</g>
|
| 226 |
+
<circle class="lp-stud" cx="-22.6" cy="-22.6" r="1.8"/>
|
| 227 |
+
<circle class="lp-stud" cx="22.6" cy="-22.6" r="1.8"/>
|
| 228 |
+
<circle class="lp-stud" cx="22.6" cy="22.6" r="1.8"/>
|
| 229 |
+
<circle class="lp-stud" cx="-22.6" cy="22.6" r="1.8"/>
|
| 230 |
+
<g class="lp-seal" transform="translate(22, -22)">
|
| 231 |
+
<circle r="8.5" fill="url(#lp-brass-t1)" stroke="#1a1208"/>
|
| 232 |
+
<text y="2.5" text-anchor="middle" font-family="Cinzel" font-size="8" font-weight="700" fill="#1a1208">T1</text>
|
| 233 |
+
</g>
|
| 234 |
+
<text class="lp-name" y="48" text-anchor="middle">bnb 4-bit</text>
|
| 235 |
+
<g class="lp-chip" transform="translate(0, 58)">
|
| 236 |
+
<rect x="-32" y="-7" width="64" height="14" fill="rgba(40,26,8,0.95)" stroke="#e0a13c" stroke-width="0.7"/>
|
| 237 |
+
<text y="2.5" text-anchor="middle" font-family="JetBrains Mono" font-size="7" fill="#e0a13c" letter-spacing="0.12em">needs Β· add</text>
|
| 238 |
+
</g>
|
| 239 |
+
</g>
|
| 240 |
+
|
| 241 |
+
<g class="lp-node lp-outer-3" transform="translate(330, 380)"> <!-- AVAILABLE β LoRA -->
|
| 242 |
+
<polygon class="lp-aura" points="-13.3,-32 13.3,-32 32,-13.3 32,13.3 13.3,32 -13.3,32 -32,13.3 -32,-13.3" transform="scale(1.3)"/>
|
| 243 |
+
<polygon class="lp-frame-outer" points="-13.3,-32 13.3,-32 32,-13.3 32,13.3 13.3,32 -13.3,32 -32,13.3 -32,-13.3"/>
|
| 244 |
+
<polygon class="lp-plate" points="-11.2,-27 11.2,-27 27,-11.2 27,11.2 11.2,27 -11.2,27 -27,11.2 -27,-11.2"/>
|
| 245 |
+
<ellipse class="lp-gem" cx="0" cy="-2" rx="14" ry="11"/>
|
| 246 |
+
<polygon class="lp-frame" points="-11.2,-27 11.2,-27 27,-11.2 27,11.2 11.2,27 -11.2,27 -27,11.2 -27,-11.2"/>
|
| 247 |
+
<g class="lp-icon" stroke="#fff5e8" fill="none" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" transform="translate(-12,-14)">
|
| 248 |
+
<path d="M12 3l9 16H3z"/><path d="M12 9l4 7H8z"/>
|
| 249 |
+
</g>
|
| 250 |
+
<circle class="lp-stud" cx="-22.6" cy="-22.6" r="1.8"/>
|
| 251 |
+
<circle class="lp-stud" cx="22.6" cy="-22.6" r="1.8"/>
|
| 252 |
+
<circle class="lp-stud" cx="22.6" cy="22.6" r="1.8"/>
|
| 253 |
+
<circle class="lp-stud" cx="-22.6" cy="22.6" r="1.8"/>
|
| 254 |
+
<g class="lp-seal" transform="translate(22, -22)">
|
| 255 |
+
<circle r="8.5" fill="url(#lp-brass-t1)" stroke="#1a1208"/>
|
| 256 |
+
<text y="2.5" text-anchor="middle" font-family="Cinzel" font-size="8" font-weight="700" fill="#1a1208">T1</text>
|
| 257 |
+
</g>
|
| 258 |
+
<text class="lp-name" y="48" text-anchor="middle">LoRA</text>
|
| 259 |
+
</g>
|
| 260 |
+
|
| 261 |
+
<g class="lp-node lp-outer-4" transform="translate(70, 270)"> <!-- AVAILABLE β Llama-3 -->
|
| 262 |
+
<polygon class="lp-aura" points="-13.3,-32 13.3,-32 32,-13.3 32,13.3 13.3,32 -13.3,32 -32,13.3 -32,-13.3" transform="scale(1.3)"/>
|
| 263 |
+
<polygon class="lp-frame-outer" points="-13.3,-32 13.3,-32 32,-13.3 32,13.3 13.3,32 -13.3,32 -32,13.3 -32,-13.3"/>
|
| 264 |
+
<polygon class="lp-plate" points="-11.2,-27 11.2,-27 27,-11.2 27,11.2 11.2,27 -11.2,27 -27,11.2 -27,-11.2"/>
|
| 265 |
+
<ellipse class="lp-gem" cx="0" cy="-2" rx="14" ry="11"/>
|
| 266 |
+
<polygon class="lp-frame" points="-11.2,-27 11.2,-27 27,-11.2 27,11.2 11.2,27 -11.2,27 -27,11.2 -27,-11.2"/>
|
| 267 |
+
<g class="lp-icon" stroke="#fff5e8" fill="none" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" transform="translate(-12,-14)">
|
| 268 |
+
<path d="M3 7l9-4 9 4"/><path d="M5 7v12M19 7v12M12 7v12"/><path d="M3 21h18"/>
|
| 269 |
+
</g>
|
| 270 |
+
<circle class="lp-stud" cx="-22.6" cy="-22.6" r="1.8"/>
|
| 271 |
+
<circle class="lp-stud" cx="22.6" cy="-22.6" r="1.8"/>
|
| 272 |
+
<circle class="lp-stud" cx="22.6" cy="22.6" r="1.8"/>
|
| 273 |
+
<circle class="lp-stud" cx="-22.6" cy="22.6" r="1.8"/>
|
| 274 |
+
<g class="lp-seal" transform="translate(22, -22)">
|
| 275 |
+
<circle r="8.5" fill="url(#lp-brass-t1)" stroke="#1a1208"/>
|
| 276 |
+
<text y="2.5" text-anchor="middle" font-family="Cinzel" font-size="8" font-weight="700" fill="#1a1208">T1</text>
|
| 277 |
+
</g>
|
| 278 |
+
<text class="lp-name" y="48" text-anchor="middle">Llama-3</text>
|
| 279 |
+
</g>
|
| 280 |
+
|
| 281 |
+
<g class="lp-node lp-outer-5" transform="translate(110, 90)"> <!-- AVAILABLE β Grad Ckpt -->
|
| 282 |
+
<polygon class="lp-aura" points="-13.3,-32 13.3,-32 32,-13.3 32,13.3 13.3,32 -13.3,32 -32,13.3 -32,-13.3" transform="scale(1.3)"/>
|
| 283 |
+
<polygon class="lp-frame-outer" points="-13.3,-32 13.3,-32 32,-13.3 32,13.3 13.3,32 -13.3,32 -32,13.3 -32,-13.3"/>
|
| 284 |
+
<polygon class="lp-plate" points="-11.2,-27 11.2,-27 27,-11.2 27,11.2 11.2,27 -11.2,27 -27,11.2 -27,-11.2"/>
|
| 285 |
+
<ellipse class="lp-gem" cx="0" cy="-2" rx="14" ry="11"/>
|
| 286 |
+
<polygon class="lp-frame" points="-11.2,-27 11.2,-27 27,-11.2 27,11.2 11.2,27 -11.2,27 -27,11.2 -27,-11.2"/>
|
| 287 |
+
<g class="lp-icon" stroke="#fff5e8" fill="none" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" transform="translate(-12,-14)">
|
| 288 |
+
<path d="M12 3l9 16H3z"/><path d="M12 9l4 7H8z"/>
|
| 289 |
+
</g>
|
| 290 |
+
<circle class="lp-stud" cx="-22.6" cy="-22.6" r="1.8"/>
|
| 291 |
+
<circle class="lp-stud" cx="22.6" cy="-22.6" r="1.8"/>
|
| 292 |
+
<circle class="lp-stud" cx="22.6" cy="22.6" r="1.8"/>
|
| 293 |
+
<circle class="lp-stud" cx="-22.6" cy="22.6" r="1.8"/>
|
| 294 |
+
<g class="lp-seal" transform="translate(22, -22)">
|
| 295 |
+
<circle r="8.5" fill="url(#lp-brass-t2)" stroke="#1a1208"/>
|
| 296 |
+
<text y="2.5" text-anchor="middle" font-family="Cinzel" font-size="8" font-weight="700" fill="#fff">T2</text>
|
| 297 |
+
</g>
|
| 298 |
+
<text class="lp-name" y="48" text-anchor="middle">Grad Ckpt</text>
|
| 299 |
+
</g>
|
| 300 |
+
</svg>
|
| 301 |
+
</div>
|
| 302 |
+
</section>
|
| 303 |
+
|
| 304 |
+
<!-- ββ What βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ -->
|
| 305 |
+
<section class="lp-section" id="what">
|
| 306 |
+
<div class="lp-shell">
|
| 307 |
+
<div class="lp-section-head">
|
| 308 |
+
<div class="lp-section-eyebrow">what it does</div>
|
| 309 |
+
<h2 class="lp-section-title">A loadout-builder for ML training.</h2>
|
| 310 |
+
<p class="lp-section-sub">
|
| 311 |
+
Pick optimizers, schedulers, quantization, techniques. The graph re-resolves
|
| 312 |
+
live and tells you what fits, what's missing, and what blows up β every fact
|
| 313 |
+
backed by a citation.
|
| 314 |
+
</p>
|
| 315 |
+
</div>
|
| 316 |
+
|
| 317 |
+
<div class="lp-tablets">
|
| 318 |
+
<div class="lp-tablet">
|
| 319 |
+
<div class="lp-tablet-num">I</div>
|
| 320 |
+
<div class="lp-tablet-icon">
|
| 321 |
+
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
| 322 |
+
<circle cx="12" cy="12" r="3"/>
|
| 323 |
+
<path d="M12 3v3M12 18v3M3 12h3M18 12h3M5.6 5.6l2.1 2.1M16.3 16.3l2.1 2.1M5.6 18.4l2.1-2.1M16.3 7.7l2.1-2.1"/>
|
| 324 |
+
</svg>
|
| 325 |
+
</div>
|
| 326 |
+
<h3>Compatibility-aware</h3>
|
| 327 |
+
<p>Pick a component and every other one re-styles by status: <em>available</em>, <em>conditional</em>, or <em>blocked</em>. Greyed means not yet satisfied β add the missing ingredient and it re-lights in real time.</p>
|
| 328 |
+
</div>
|
| 329 |
+
|
| 330 |
+
<div class="lp-tablet">
|
| 331 |
+
<div class="lp-tablet-num">II</div>
|
| 332 |
+
<div class="lp-tablet-icon">
|
| 333 |
+
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
| 334 |
+
<path d="M4 19V5a2 2 0 0 1 2-2h11l3 3v13a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2z"/>
|
| 335 |
+
<path d="M8 8h7M8 12h7M8 16h5"/>
|
| 336 |
+
</svg>
|
| 337 |
+
</div>
|
| 338 |
+
<h3>Evidence-backed</h3>
|
| 339 |
+
<p>Every grey-out, every fix, every conflict carries its <em>cited source</em> β verbatim quote, URL, and tier badge. Hover anything to see where the claim comes from.</p>
|
| 340 |
+
</div>
|
| 341 |
+
|
| 342 |
+
<div class="lp-tablet">
|
| 343 |
+
<div class="lp-tablet-num">III</div>
|
| 344 |
+
<div class="lp-tablet-icon">
|
| 345 |
+
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
| 346 |
+
<path d="M3 12h4l3 8 4-16 3 8h4"/>
|
| 347 |
+
</svg>
|
| 348 |
+
</div>
|
| 349 |
+
<h3>Benchmark-backed</h3>
|
| 350 |
+
<p>Scheduler picks aren't picked from a paper β they're picked from <em>real measured val_loss / val_acc</em> on distilbert / sst2, three seeds each. DLRS leads. OneCycle is flagged above cohort cutoff.</p>
|
| 351 |
+
</div>
|
| 352 |
+
</div>
|
| 353 |
+
</div>
|
| 354 |
+
</section>
|
| 355 |
+
|
| 356 |
+
<!-- ββ How to use βββββββββββββββββββββββββββββββββββββββββββββββββββ -->
|
| 357 |
+
<section class="lp-section" id="how">
|
| 358 |
+
<div class="lp-shell">
|
| 359 |
+
<div class="lp-section-head">
|
| 360 |
+
<div class="lp-section-eyebrow">how to use it</div>
|
| 361 |
+
<h2 class="lp-section-title">Three strikes on the anvil.</h2>
|
| 362 |
+
<p class="lp-section-sub">
|
| 363 |
+
Sixty seconds, three motions. The demo path the team built it around.
|
| 364 |
+
</p>
|
| 365 |
+
</div>
|
| 366 |
+
|
| 367 |
+
<div class="lp-steps">
|
| 368 |
+
|
| 369 |
+
<div class="lp-step">
|
| 370 |
+
<div class="lp-step-text">
|
| 371 |
+
<span class="lp-step-num">Step One</span>
|
| 372 |
+
<h3>Pick from the inventory.</h3>
|
| 373 |
+
<p>
|
| 374 |
+
The left rail is your loadout. Tap any optimizer, scheduler, technique,
|
| 375 |
+
quantization, architecture, or inference engine. The instant you equip one,
|
| 376 |
+
the graph re-runs <code style="font-family: var(--f-mono); font-size: 0.92em; color: var(--brass-1);">POST /resolve</code> and re-styles every other node by status.
|
| 377 |
+
</p>
|
| 378 |
+
<div class="quote">
|
| 379 |
+
"Pick <strong style="color: var(--brass-1);">QLoRA</strong>. Full Fine-Tune slams to <strong style="color: var(--rust);">blocked</strong>.
|
| 380 |
+
bnb 4-bit shimmers <strong style="color: var(--amber);">conditional</strong> β ‘needed by QLoRA’."
|
| 381 |
+
</div>
|
| 382 |
+
</div>
|
| 383 |
+
<div class="lp-step-art">
|
| 384 |
+
<!-- Illustration: inventory card sample -->
|
| 385 |
+
<div style="width: 100%; max-width: 320px;">
|
| 386 |
+
<div class="inv-row tier-1 selected" style="--type-color: var(--t-technique);">
|
| 387 |
+
<div class="type-ic">
|
| 388 |
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
|
| 389 |
+
<path d="M12 3l9 16H3z"/><path d="M12 9l4 7H8z"/>
|
| 390 |
+
</svg>
|
| 391 |
+
</div>
|
| 392 |
+
<div>
|
| 393 |
+
<div class="inv-name">QLoRA</div>
|
| 394 |
+
<div class="inv-meta"><span style="color: var(--ember-2);">equipped</span></div>
|
| 395 |
+
</div>
|
| 396 |
+
<div class="tier-pip t1">T1</div>
|
| 397 |
+
</div>
|
| 398 |
+
<div class="inv-row tier-1 blocked" style="margin-top: 6px; --type-color: var(--t-technique);">
|
| 399 |
+
<div class="type-ic">
|
| 400 |
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
|
| 401 |
+
<path d="M12 3l9 16H3z"/><path d="M12 9l4 7H8z"/>
|
| 402 |
+
</svg>
|
| 403 |
+
</div>
|
| 404 |
+
<div>
|
| 405 |
+
<div class="inv-name">Full Fine-Tune</div>
|
| 406 |
+
<div class="inv-meta"><span style="color: var(--rust);">blocked Β· breaks with QLoRA</span></div>
|
| 407 |
+
</div>
|
| 408 |
+
<div class="tier-pip t1">T1</div>
|
| 409 |
+
</div>
|
| 410 |
+
<div class="inv-row tier-1 dim" style="margin-top: 6px; --type-color: var(--t-quantization);">
|
| 411 |
+
<div class="type-ic">
|
| 412 |
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
|
| 413 |
+
<rect x="4" y="13" width="3" height="7" rx="0.5"/>
|
| 414 |
+
<rect x="10.5" y="9" width="3" height="11" rx="0.5"/>
|
| 415 |
+
<rect x="17" y="5" width="3" height="15" rx="0.5"/>
|
| 416 |
+
</svg>
|
| 417 |
+
</div>
|
| 418 |
+
<div>
|
| 419 |
+
<div class="inv-name">bnb 4-bit</div>
|
| 420 |
+
<div class="inv-meta"><span style="color: var(--amber);">needed by QLoRA</span></div>
|
| 421 |
+
</div>
|
| 422 |
+
<div class="tier-pip t1">T1</div>
|
| 423 |
+
</div>
|
| 424 |
+
</div>
|
| 425 |
+
</div>
|
| 426 |
+
</div>
|
| 427 |
+
|
| 428 |
+
<div class="lp-step">
|
| 429 |
+
<div class="lp-step-text">
|
| 430 |
+
<span class="lp-step-num">Step Two</span>
|
| 431 |
+
<h3>Read the recipe.</h3>
|
| 432 |
+
<p>
|
| 433 |
+
The right rail is your crafting window. Conflicts are scored in
|
| 434 |
+
<strong style="color: var(--rust);">rust</strong>. Unmet requirements glow
|
| 435 |
+
<strong style="color: var(--amber);">amber</strong> with a one-tap
|
| 436 |
+
<em>+ add bnb 4-bit</em> button. Benchmark-backed scheduler picks list themselves
|
| 437 |
+
by measured val_loss with the leader marked with a star.
|
| 438 |
+
</p>
|
| 439 |
+
<div class="quote">
|
| 440 |
+
Every entry shows the <strong style="color: var(--brass-1);">tier badge</strong>
|
| 441 |
+
and a source link β so the credibility chain stays visible all the way through.
|
| 442 |
+
</div>
|
| 443 |
+
</div>
|
| 444 |
+
<div class="lp-step-art">
|
| 445 |
+
<div style="width: 100%; max-width: 360px;">
|
| 446 |
+
<div class="entry conflict" style="margin-bottom: 8px;">
|
| 447 |
+
<div class="title conflict">QLoRA <span style="color: var(--bone-4);">β</span> Full Fine-Tune</div>
|
| 448 |
+
<div class="fix">QLoRA freezes the base model; Full Fine-Tune updates it. Pick one.</div>
|
| 449 |
+
<div class="meta">
|
| 450 |
+
<span class="tier-badge t1">T1</span>
|
| 451 |
+
<span style="color: var(--bone-4);">arxiv.org/abs/2305.14314</span>
|
| 452 |
+
</div>
|
| 453 |
+
</div>
|
| 454 |
+
<div class="entry unmet">
|
| 455 |
+
<div class="title unmet">QLoRA needs <strong style="color: #fff5e8;">bnb 4-bit</strong></div>
|
| 456 |
+
<div class="fix">QLoRA is defined as 4-bit NF4 base + LoRA adapters β load the base in bnb 4-bit.</div>
|
| 457 |
+
<button class="add-btn" type="button">
|
| 458 |
+
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M12 5v14M5 12h14"/></svg>
|
| 459 |
+
add bnb 4-bit
|
| 460 |
+
</button>
|
| 461 |
+
</div>
|
| 462 |
+
</div>
|
| 463 |
+
</div>
|
| 464 |
+
</div>
|
| 465 |
+
|
| 466 |
+
<div class="lp-step">
|
| 467 |
+
<div class="lp-step-text">
|
| 468 |
+
<span class="lp-step-num">Step Three</span>
|
| 469 |
+
<h3>Inspect the evidence.</h3>
|
| 470 |
+
<p>
|
| 471 |
+
Hover any node, edge, or recipe entry to surface the <em>verbatim quote</em> from
|
| 472 |
+
its source and the tier badge it earned. T1 is Rick's own verified runs
|
| 473 |
+
(immutable). T2 is community-corroborated. T3 is single-source β lives in
|
| 474 |
+
the review queue until something else agrees.
|
| 475 |
+
</p>
|
| 476 |
+
<div class="quote">
|
| 477 |
+
The point of the tooltip is the source URL. The point of the graph is the
|
| 478 |
+
decision. The point of the tier is so you know how much to trust both.
|
| 479 |
+
</div>
|
| 480 |
+
</div>
|
| 481 |
+
<div class="lp-step-art">
|
| 482 |
+
<div style="width: 100%; max-width: 320px;">
|
| 483 |
+
<div class="evidence-tip" style="position: static; box-shadow: 0 14px 30px rgba(0,0,0,0.6);">
|
| 484 |
+
<div class="tip-head">
|
| 485 |
+
<span class="tip-name">AdamW 8-bit</span>
|
| 486 |
+
<span class="tip-status blocked">blocked</span>
|
| 487 |
+
</div>
|
| 488 |
+
<div class="tip-reason">
|
| 489 |
+
<div class="tip-reason-label" style="color: var(--rust);">breaks with Per-Layer LR Rotation</div>
|
| 490 |
+
<div class="tip-reason-fix">Pass custom <code style="font-family: var(--f-mono);">optimizer_grouped_parameters</code> β adamw_8bit's default decay/no-decay split silently no-ops per-layer LR.</div>
|
| 491 |
+
<div class="quote">"adamw_8bit produces decay/no-decay param groups by default; per-layer LR rotation silently no-ops unless you pass them yourself."</div>
|
| 492 |
+
<div class="tip-foot">
|
| 493 |
+
<span class="src-link">mempalace Β· rick</span>
|
| 494 |
+
<span class="tier-badge t1">T1</span>
|
| 495 |
+
</div>
|
| 496 |
+
</div>
|
| 497 |
+
</div>
|
| 498 |
+
</div>
|
| 499 |
+
</div>
|
| 500 |
+
</div>
|
| 501 |
+
|
| 502 |
+
</div>
|
| 503 |
+
</div>
|
| 504 |
+
</section>
|
| 505 |
+
|
| 506 |
+
<!-- ββ Tiers ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ -->
|
| 507 |
+
<section class="lp-section" id="tiers">
|
| 508 |
+
<div class="lp-shell">
|
| 509 |
+
<div class="lp-section-head">
|
| 510 |
+
<div class="lp-section-eyebrow">trust model</div>
|
| 511 |
+
<h2 class="lp-section-title">Every claim earns its tier.</h2>
|
| 512 |
+
<p class="lp-section-sub">
|
| 513 |
+
We don't assert nonsense as fact. Three tiers, three colors, three weights.
|
| 514 |
+
The scraper feeds the bottom; corroboration promotes upward.
|
| 515 |
+
</p>
|
| 516 |
+
</div>
|
| 517 |
+
|
| 518 |
+
<div class="lp-tiers">
|
| 519 |
+
<div class="lp-tier lp-tier-1">
|
| 520 |
+
<div class="lp-tier-coin">T1</div>
|
| 521 |
+
<div class="lp-tier-label">Legendary Β· 1.0</div>
|
| 522 |
+
<h4>Verified runs</h4>
|
| 523 |
+
<p>Rick's own research notes and reproduced runs. <em>Immutable</em> β the scraper can never overwrite these, only add corroboration.</p>
|
| 524 |
+
<div class="example">e.g. <span style="color: var(--bone-2);">Per-Layer LR Rotation Γ AdamW 8-bit</span> Β· mempalace://chaos-injection-trainer-notes</div>
|
| 525 |
+
</div>
|
| 526 |
+
|
| 527 |
+
<div class="lp-tier lp-tier-2">
|
| 528 |
+
<div class="lp-tier-coin">T2</div>
|
| 529 |
+
<div class="lp-tier-label">Rare Β· 0.8</div>
|
| 530 |
+
<h4>Community-confirmed</h4>
|
| 531 |
+
<p>Official docs, or two-plus independent sources agree. The bulk of the workable graph.</p>
|
| 532 |
+
<div class="example">e.g. <span style="color: var(--bone-2);">Muon β AdamW 8-bit</span> Β· kellerjordan.github.io/posts/muon</div>
|
| 533 |
+
</div>
|
| 534 |
+
|
| 535 |
+
<div class="lp-tier lp-tier-3">
|
| 536 |
+
<div class="lp-tier-coin">T3</div>
|
| 537 |
+
<div class="lp-tier-label">Common Β· 0.5</div>
|
| 538 |
+
<h4>Single-source</h4>
|
| 539 |
+
<p>One scraped report, no corroboration yet. Lives in the review queue. Promotes when something else agrees, or when Rick signs off.</p>
|
| 540 |
+
<div class="example">e.g. <span style="color: var(--bone-2);">Lion Γ bnb 8-bit divergence</span> Β· github.com/bitsandbytes issue</div>
|
| 541 |
+
</div>
|
| 542 |
+
</div>
|
| 543 |
+
</div>
|
| 544 |
+
</section>
|
| 545 |
+
|
| 546 |
+
<!-- ββ Scraper βββββββββββββββββββββββββββββββββββββββββββββββββββββββ -->
|
| 547 |
+
<section class="lp-section" id="scraper">
|
| 548 |
+
<div class="lp-shell">
|
| 549 |
+
<div class="lp-section-head">
|
| 550 |
+
<div class="lp-section-eyebrow">the live data layer</div>
|
| 551 |
+
<h2 class="lp-section-title">The graph grows itself.</h2>
|
| 552 |
+
<p class="lp-section-sub">
|
| 553 |
+
A Bright Data scraper hunts SERP results in English <em>and</em> Chinese,
|
| 554 |
+
extracts (A, relation, B, conditions, fix, quote) tuples with Haiku, resolves
|
| 555 |
+
them against canonical node aliases, and proposes them to the review queue.
|
| 556 |
+
</p>
|
| 557 |
+
</div>
|
| 558 |
+
|
| 559 |
+
<div class="lp-scraper">
|
| 560 |
+
<div>
|
| 561 |
+
<p>
|
| 562 |
+
Watch the <strong style="color: var(--brass-1); font-style: normal;">Live Discoveries</strong>
|
| 563 |
+
hearth at the bottom of the Forge while you work β new edges literally rise
|
| 564 |
+
out of it as the scraper corroborates them. The graph is alive.
|
| 565 |
+
</p>
|
| 566 |
+
<p>
|
| 567 |
+
English-only sources miss large chunks of the Chinese ML ecosystem. We
|
| 568 |
+
cover both. The scraper writes nothing to T1 β that's Rick's territory.
|
| 569 |
+
Single-source claims sit at T3 in the queue and only ascend with evidence.
|
| 570 |
+
</p>
|
| 571 |
+
</div>
|
| 572 |
+
|
| 573 |
+
<div class="lp-pipeline">
|
| 574 |
+
<div class="lp-pipeline-step">
|
| 575 |
+
<span>SERPΒ·en/zh</span>
|
| 576 |
+
<span class="arrow">β</span>
|
| 577 |
+
<span class="src">arxiv Β· github</span>
|
| 578 |
+
</div>
|
| 579 |
+
<div class="lp-pipeline-step">
|
| 580 |
+
<span>scrape_as_markdown</span>
|
| 581 |
+
<span class="arrow">β</span>
|
| 582 |
+
<span class="src">bright data</span>
|
| 583 |
+
</div>
|
| 584 |
+
<div class="lp-pipeline-step">
|
| 585 |
+
<span>extract tuple</span>
|
| 586 |
+
<span class="arrow">β</span>
|
| 587 |
+
<span class="src">haiku</span>
|
| 588 |
+
</div>
|
| 589 |
+
<div class="lp-pipeline-step">
|
| 590 |
+
<span>entity-resolve</span>
|
| 591 |
+
<span class="arrow">β</span>
|
| 592 |
+
<span class="src">canonical aliases</span>
|
| 593 |
+
</div>
|
| 594 |
+
<div class="lp-pipeline-step">
|
| 595 |
+
<span>review_queue</span>
|
| 596 |
+
<span class="arrow">β</span>
|
| 597 |
+
<span class="tier t3">T3</span>
|
| 598 |
+
</div>
|
| 599 |
+
<div class="lp-pipeline-step">
|
| 600 |
+
<span>corroborate</span>
|
| 601 |
+
<span class="arrow">β</span>
|
| 602 |
+
<span class="tier t2">T2</span>
|
| 603 |
+
</div>
|
| 604 |
+
</div>
|
| 605 |
+
</div>
|
| 606 |
+
</div>
|
| 607 |
+
</section>
|
| 608 |
+
|
| 609 |
+
<!-- ββ Finale CTA ββββββββββββββββββββββββββββββββββββββββββββββββββββ -->
|
| 610 |
+
<section class="lp-finale">
|
| 611 |
+
<h2 class="lp-finale-title">Light the forge.</h2>
|
| 612 |
+
<p class="lp-finale-sub">Ninety seconds. Ten components. One recipe that actually compiles.</p>
|
| 613 |
+
<a href="index.html" class="lp-cta-primary">
|
| 614 |
+
Enter the Forge
|
| 615 |
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round">
|
| 616 |
+
<path d="M5 12h14M13 6l6 6-6 6"/>
|
| 617 |
+
</svg>
|
| 618 |
+
</a>
|
| 619 |
+
</section>
|
| 620 |
+
|
| 621 |
+
<footer class="lp-foot lp-shell">
|
| 622 |
+
bright data Β· "web data unlocked" Β· 2026
|
| 623 |
+
Β·
|
| 624 |
+
<a href="index.html">launch app</a>
|
| 625 |
+
</footer>
|
| 626 |
+
|
| 627 |
+
</div>
|
| 628 |
+
</body>
|
| 629 |
+
</html>
|