lm-playground-api / web /platform /platform.css
deploy
Deploy LM Playground API
f0a527a
Raw
History Blame Contribute Delete
12.5 kB
/* ============================================================================
LM Playground — shared platform shell (nav bar, hub, theme tokens)
Loaded by every page via <link rel="stylesheet" href="/platform/platform.css">
All selectors are scoped under .plat- to avoid colliding with chapter CSS.
========================================================================== */
:root{
--plat-bg:#0f1117; --plat-panel:#181b24; --plat-panel2:#1f2330;
--plat-border:#2a2f3d; --plat-text:#e6e8ee; --plat-muted:#9aa3b2;
--plat-accent:#7c8cff; --plat-accent2:#5be0c0;
--plat-good:#5be08a; --plat-warn:#ffc06b;
--plat-mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
--plat-sans:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
--plat-nav-h:54px; /* approximate nav height; used for scroll-padding */
}
/* Anchor links land below the sticky nav, not hidden under it */
html { scroll-padding-top:calc(var(--plat-nav-h) + 12px) }
/* ---------------------------------------------------------------- top nav -- */
.plat-nav{position:sticky;top:0;z-index:1000;
background:rgba(15,17,23,.86);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
border-bottom:1px solid var(--plat-border);font-family:var(--plat-sans);
/* Break out of any body padding a chapter page may set, so the bar always spans
full viewport width. Formula: margin-left = -(body-padding-left);
width = 100vw regardless of parent width. When body has no padding the
calc evaluates to 0 and the rule is a no-op. */
width:100vw;
margin-left:calc(-1 * ((100vw - 100%) / 2));}
.plat-nav__inner{max-width:1180px;margin:0 auto;display:flex;align-items:center;
gap:14px;padding:9px 20px}
.plat-brand{display:flex;align-items:center;gap:8px;color:var(--plat-text);
text-decoration:none;font-weight:700;font-size:14px;letter-spacing:-.2px;white-space:nowrap}
.plat-brand .dot{width:9px;height:9px;border-radius:50%;
background:linear-gradient(135deg,var(--plat-accent),var(--plat-accent2))}
.plat-ctx{color:var(--plat-muted);font-size:12.5px;white-space:nowrap;
border-left:1px solid var(--plat-border);padding-left:14px}
.plat-ctx b{color:var(--plat-text);font-weight:600}
.plat-spacer{margin-left:auto}
.plat-navlinks{display:flex;align-items:center;gap:6px}
.plat-btn{display:inline-flex;align-items:center;gap:6px;text-decoration:none;
color:var(--plat-muted);font-size:13px;font-weight:600;padding:6px 12px;border-radius:8px;
border:1px solid transparent;background:transparent;cursor:pointer;font-family:inherit;
transition:.12s;white-space:nowrap}
.plat-btn:hover{color:var(--plat-text);background:rgba(124,140,255,.10)}
.plat-btn[aria-disabled="true"]{opacity:.32;pointer-events:none}
.plat-btn--primary{color:#fff;background:rgba(124,140,255,.16);border-color:rgba(124,140,255,.4)}
/* ------------------------------------------------------- curriculum overlay -- */
.plat-overlay{position:fixed;inset:0;z-index:1001;display:none;
background:rgba(8,9,13,.6);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}
.plat-overlay.open{display:block}
.plat-drawer{position:absolute;top:0;right:0;height:100%;width:min(460px,92vw);
background:var(--plat-panel);border-left:1px solid var(--plat-border);
box-shadow:-20px 0 50px rgba(0,0,0,.4);overflow-y:auto;padding:18px 18px 60px;
font-family:var(--plat-sans)}
.plat-drawer h2{font-size:15px;margin:4px 0 2px;color:var(--plat-text)}
.plat-drawer .sub{font-size:12.5px;color:var(--plat-muted);margin:0 0 16px}
.plat-drawer .close{position:absolute;top:14px;right:14px}
.plat-part{font-size:11px;text-transform:uppercase;letter-spacing:.08em;
color:var(--plat-accent2);font-weight:700;margin:18px 0 6px}
.plat-link{display:flex;align-items:center;gap:10px;text-decoration:none;
color:var(--plat-text);padding:7px 9px;border-radius:8px;border:1px solid transparent}
.plat-link:hover{background:var(--plat-panel2);border-color:var(--plat-border)}
.plat-link.active{background:rgba(124,140,255,.14);border-color:rgba(124,140,255,.4)}
.plat-link .n{font:700 11px/1 var(--plat-mono);color:var(--plat-muted);
background:var(--plat-panel2);border-radius:6px;padding:3px 6px;min-width:26px;text-align:center}
.plat-link.active .n{background:linear-gradient(135deg,var(--plat-accent),var(--plat-accent2));color:#0f1117}
.plat-link .t{font-size:13.5px;font-weight:600;flex:1}
.plat-link .st{font-size:14px}
/* ---------------------------------------------------------- hub / home grid -- */
.plat-hub{max-width:1100px;margin:0 auto;padding:40px 20px 80px;
font-family:var(--plat-sans);color:var(--plat-text)}
.plat-hub__head{display:flex;align-items:flex-start;gap:16px;flex-wrap:wrap;
border-bottom:1px solid var(--plat-border);padding-bottom:22px;margin-bottom:8px}
.plat-hub__eyebrow{font-size:12px;text-transform:uppercase;letter-spacing:.12em;
color:var(--plat-accent2);font-weight:700;margin:0 0 10px}
.plat-hub__head h1{font-size:32px;margin:0 0 10px;letter-spacing:-.6px;line-height:1.1}
.plat-hub__head .lede{color:var(--plat-muted);font-size:15.5px;max-width:660px;margin:0;line-height:1.6}
.plat-progress{margin-left:auto;min-width:200px;text-align:right}
.plat-progress .pct{font:700 13px/1 var(--plat-mono);color:var(--plat-text)}
.plat-progress .bar{height:8px;border-radius:99px;background:var(--plat-panel2);
border:1px solid var(--plat-border);margin-top:8px;overflow:hidden}
.plat-progress .fill{height:100%;background:linear-gradient(90deg,var(--plat-accent),var(--plat-accent2))}
/* --ph (part hue) is set per-section in platform.js and cascades to cards */
.plat-partsec{margin-top:38px;--ph:212}
.plat-partsec__head{display:flex;align-items:center;gap:12px;margin:0 0 16px}
.plat-partsec__num{font:700 11px/1 var(--plat-mono);color:#0f1117;letter-spacing:.04em;
background:linear-gradient(135deg,hsl(var(--ph) 75% 68%),hsl(var(--ph) 70% 58%));
border-radius:6px;padding:5px 9px}
.plat-partsec__title{font-size:18px;font-weight:700;margin:0;letter-spacing:-.2px}
.plat-partsec__rule{flex:1;height:1px;background:linear-gradient(90deg,
hsl(var(--ph) 60% 55% / .45),transparent)}
.plat-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(282px,1fr));gap:14px}
.plat-card{display:flex;flex-direction:column;gap:8px;text-decoration:none;
background:var(--plat-panel);border:1px solid var(--plat-border);border-radius:14px;
padding:17px 16px 15px;transition:transform .14s,border-color .14s,box-shadow .14s;
color:var(--plat-text);position:relative;overflow:hidden}
.plat-card::before{content:"";position:absolute;inset:0 0 auto 0;height:3px;
background:linear-gradient(90deg,hsl(var(--ph) 72% 62%),hsl(var(--ph) 60% 52% / .25));
opacity:.55;transition:opacity .14s}
.plat-card:hover{border-color:hsl(var(--ph) 65% 60%);transform:translateY(-3px);
box-shadow:0 10px 28px rgba(0,0,0,.32)}
.plat-card:hover::before{opacity:1}
.plat-card.stub{opacity:.9}
.plat-card.stub::before{opacity:.28}
.plat-card__top{display:flex;align-items:center;gap:10px;margin-top:2px}
.plat-card__num{font:700 12px/1 var(--plat-mono);color:#0f1117;border:0;border-radius:7px;padding:5px 8px;
background:linear-gradient(135deg,hsl(var(--ph) 75% 66%),hsl(var(--ph) 68% 56%))}
.plat-card.stub .plat-card__num{color:var(--plat-muted);
background:var(--plat-panel2);border:1px solid var(--plat-border)}
.plat-card__title{font-size:15.5px;font-weight:700;flex:1;line-height:1.25}
.plat-badge{font-size:10.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
padding:3px 7px;border-radius:99px;white-space:nowrap}
.plat-badge.ready{color:var(--plat-good);background:rgba(91,224,138,.12);border:1px solid rgba(91,224,138,.3)}
.plat-badge.soon{color:var(--plat-warn);background:rgba(255,192,107,.10);border:1px solid rgba(255,192,107,.3)}
.plat-card__blurb{font-size:13px;color:var(--plat-muted);line-height:1.5;margin:0}
.plat-card__obj{display:flex;flex-wrap:wrap;gap:5px;margin-top:2px}
.plat-card__obj span{font-size:11px;color:var(--plat-muted);
background:var(--plat-panel2);border:1px solid var(--plat-border);border-radius:99px;padding:2px 8px}
/* ------------------------------------------------------------ stub pages -- */
.plat-stub{max-width:820px;margin:0 auto;padding:48px 20px 80px;
font-family:var(--plat-sans);color:var(--plat-text);--ph:212}
/* hero: a faint part-hued glow behind the title */
.plat-stub__hero{position:relative;margin:0 0 32px;padding:32px 28px 28px;
background:var(--plat-panel);border:1px solid var(--plat-border);border-radius:18px;
overflow:hidden}
.plat-stub__hero::before{content:"";position:absolute;inset:0;pointer-events:none;
background:radial-gradient(ellipse 70% 120% at 100% 0%,
hsl(var(--ph) 72% 62% / .12),transparent 68%)}
.plat-stub__hero::after{content:"";position:absolute;top:0;left:0;right:0;height:3px;
background:linear-gradient(90deg,hsl(var(--ph) 72% 62%),hsl(var(--ph) 60% 52% / .2))}
.plat-stub__eyebrow{font-size:11.5px;text-transform:uppercase;letter-spacing:.12em;
color:hsl(var(--ph) 70% 68%);font-weight:700;margin:0 0 12px;display:flex;
align-items:center;gap:10px}
.plat-stub__eyebrow .part-pip{display:inline-block;width:7px;height:7px;border-radius:50%;
background:hsl(var(--ph) 72% 62%)}
.plat-stub__hero h1{font-size:34px;margin:0 0 14px;letter-spacing:-.6px;line-height:1.1}
.plat-stub__hero .lede{font-size:16.5px;color:var(--plat-muted);line-height:1.6;margin:0 0 20px;
max-width:620px}
/* objective pills */
.plat-pills{display:flex;flex-wrap:wrap;gap:7px}
.plat-pills span{font-size:12px;font-weight:600;padding:4px 11px;border-radius:99px;
color:hsl(var(--ph) 72% 72%);background:hsl(var(--ph) 72% 62% / .12);
border:1px solid hsl(var(--ph) 60% 55% / .3)}
/* panels */
.plat-panel{background:var(--plat-panel);border:1px solid var(--plat-border);
border-radius:14px;padding:20px 22px;margin:0 0 16px}
.plat-panel h3{font-size:11px;text-transform:uppercase;letter-spacing:.09em;
color:var(--plat-muted);font-weight:700;margin:0 0 14px}
/* "what you'll build" description */
.plat-panel .build-desc{margin:0;font-size:15px;color:var(--plat-text);
line-height:1.65;opacity:.88}
/* playground placeholder */
.plat-preview{border-radius:14px;overflow:hidden;border:1px solid var(--plat-border);
margin:0 0 16px;background:var(--plat-panel)}
.plat-preview__label{display:flex;align-items:center;gap:8px;padding:11px 18px;
border-bottom:1px solid var(--plat-border);background:var(--plat-panel2)}
.plat-preview__label span{font-size:11px;font-weight:700;text-transform:uppercase;
letter-spacing:.08em;color:var(--plat-muted)}
.plat-preview__label .dot-row{display:flex;gap:5px}
.plat-preview__label .dot-row i{display:block;width:8px;height:8px;border-radius:50%;
background:var(--plat-border)}
.plat-preview__canvas{display:flex;flex-direction:column;gap:10px;padding:22px 18px}
.plat-preview__bar{height:10px;border-radius:99px;background:var(--plat-panel2);
border:1px solid var(--plat-border)}
.plat-preview__bar.w60{width:60%}
.plat-preview__bar.w80{width:80%}
.plat-preview__bar.w45{width:45%}
.plat-preview__block{display:flex;gap:10px}
.plat-preview__block .col{flex:1;height:80px;border-radius:10px;
background:var(--plat-panel2);border:1px solid var(--plat-border)}
.plat-preview__block .col.accent{
background:hsl(var(--ph) 72% 62% / .08);border-color:hsl(var(--ph) 60% 55% / .25)}
.plat-preview__coming{display:flex;align-items:center;justify-content:center;gap:9px;
padding:10px 0 4px;font-size:13px;font-weight:600;color:var(--plat-warn)}
.plat-objlist{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:9px}
.plat-objlist li{display:flex;gap:10px;align-items:flex-start;font-size:15px}
.plat-objlist li::before{content:"▸";color:var(--plat-accent);font-weight:700;margin-top:1px}
.plat-stub__nav{display:flex;justify-content:space-between;gap:12px;margin-top:30px;
border-top:1px solid var(--plat-border);padding-top:20px}
/* back-to-hub link */
.plat-stub__back{display:inline-flex;align-items:center;gap:6px;font-size:13px;
font-weight:600;color:var(--plat-muted);text-decoration:none;margin-bottom:28px;
padding:6px 12px;border-radius:8px;border:1px solid var(--plat-border);
background:var(--plat-panel);transition:.12s}
.plat-stub__back:hover{color:var(--plat-text);border-color:hsl(var(--ph) 60% 55% / .5)}
@media (max-width:560px){
.plat-ctx{display:none}
.plat-hub__head h1{font-size:24px}
.plat-progress{margin-left:0;text-align:left;width:100%}
}