070959e133
landing-page-staging / Deploy landing page to staging (push) Has been skipped
landing-page-ci / Validate landing page (push) Failing after 4s
visual-baseline / Capture visual baselines (push) Has been cancelled
bake-plugin-previews / Bake plugin previews (push) Has been cancelled
604 lines
21 KiB
HTML
604 lines
21 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<title>Write an Architecture Review like a World-Class Staff Engineer - Product management</title>
|
||
<link href="https://fonts.googleapis.com/css2?family=Inter+Tight:wght@400;500;700;900&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
||
<style>
|
||
/* Sea Indigo - locked palette: bg #0a0e1a / ink #f5f5f7 / accent #5ac8fa */
|
||
:root{
|
||
--bg:#0a0e1a;
|
||
--ink:#f5f5f7;
|
||
--ink-dim:rgba(245,245,247,.68);
|
||
--ink-faint:rgba(245,245,247,.56);
|
||
--accent:#5ac8fa;
|
||
--line:rgba(245,245,247,.14);
|
||
--ease:cubic-bezier(.16,1,.3,1);
|
||
}
|
||
html,body{margin:0;padding:0}
|
||
body{
|
||
font-family:'Inter Tight',system-ui,sans-serif;
|
||
background:#020306;
|
||
height:100vh;
|
||
display:flex;align-items:center;justify-content:center;
|
||
overflow:hidden;
|
||
}
|
||
.stage{
|
||
width:1920px;height:1080px;
|
||
flex:none;
|
||
transform:scale(0.625);
|
||
transform-origin:center center;
|
||
position:relative;
|
||
background:var(--bg);
|
||
color:var(--ink);
|
||
/* single-accent ambient glow, cyan family only */
|
||
background-image:
|
||
radial-gradient(circle at 18% 82%, rgba(90,200,250,.10) 0%, transparent 50%),
|
||
radial-gradient(circle at 84% 22%, rgba(90,200,250,.045) 0%, transparent 55%);
|
||
}
|
||
/* ---- multi-slide canvas: stacked sections, one active ---- */
|
||
.slide{
|
||
position:absolute;inset:0;
|
||
padding:160px;
|
||
box-sizing:border-box;
|
||
display:flex;flex-direction:column;justify-content:space-between;
|
||
opacity:0;visibility:hidden;
|
||
transition:opacity .4s var(--ease), visibility .4s;
|
||
}
|
||
.slide.active{opacity:1;visibility:visible}
|
||
.mono{font-family:'JetBrains Mono',ui-monospace,monospace}
|
||
.accent{color:var(--accent)}
|
||
.meta{
|
||
display:flex;align-items:baseline;justify-content:space-between;
|
||
font-size:17px;text-transform:uppercase;
|
||
}
|
||
.meta-top{letter-spacing:.18em;color:var(--ink-dim);
|
||
border-bottom:1px solid var(--line);padding-bottom:28px}
|
||
.meta-bottom{letter-spacing:.18em;color:var(--ink-faint);
|
||
border-top:1px solid var(--line);padding-top:28px}
|
||
.meta-bottom .link{color:var(--accent)}
|
||
.kicker{
|
||
font-size:19px;letter-spacing:.22em;text-transform:uppercase;
|
||
color:var(--accent);
|
||
}
|
||
/* signature underline device */
|
||
.u{box-shadow:inset 0 -10px 0 0 rgba(90,200,250,.45)}
|
||
h1{
|
||
margin:36px 0 0;
|
||
font-size:160px;
|
||
font-weight:900;
|
||
line-height:.98;
|
||
letter-spacing:-.025em;
|
||
}
|
||
h1 .cloud{color:var(--accent)}
|
||
h1 .desk{
|
||
font-style:normal;
|
||
box-shadow:inset 0 -10px 0 0 rgba(90,200,250,.45);
|
||
}
|
||
.sub{
|
||
margin:56px 0 0;
|
||
font-size:36px;
|
||
font-weight:400;
|
||
color:var(--ink-dim);
|
||
max-width:1380px;
|
||
line-height:1.45;
|
||
}
|
||
/* staggered entrance: transform + opacity only */
|
||
.reveal{opacity:0;transform:translateY(24px)}
|
||
.slide.active .reveal{animation:reveal .8s var(--ease) forwards}
|
||
.slide.active .d1{animation-delay:.05s}
|
||
.slide.active .d2{animation-delay:.13s}
|
||
.slide.active .d3{animation-delay:.21s}
|
||
.slide.active .d4{animation-delay:.29s}
|
||
.slide.active .d5{animation-delay:.37s}
|
||
@keyframes reveal{to{opacity:1;transform:translateY(0)}}
|
||
@media (prefers-reduced-motion: reduce){
|
||
.slide{transition:none}
|
||
.reveal,.slide.active .reveal{animation:none;opacity:1;transform:none}
|
||
}
|
||
|
||
/* ---- 02 · asymmetric split ---- */
|
||
.split{display:flex;align-items:flex-end;gap:120px}
|
||
.split-main{flex:1 1 auto}
|
||
.split h2{
|
||
margin:36px 0 0;
|
||
font-size:120px;font-weight:900;line-height:1.0;letter-spacing:-.02em;
|
||
}
|
||
.split-aside{
|
||
flex:0 0 460px;
|
||
align-self:flex-start;
|
||
margin-top:96px;
|
||
border-left:1px solid var(--line);
|
||
padding-left:48px;
|
||
}
|
||
.split-aside p{
|
||
margin:0 0 36px;
|
||
font-size:28px;line-height:1.55;color:var(--ink-dim);font-weight:400;
|
||
}
|
||
.split-aside .tags{
|
||
font-size:18px;letter-spacing:.18em;color:var(--accent);margin:0;
|
||
}
|
||
|
||
/* ---- 03 · full-bleed section break ---- */
|
||
.break-wrap{align-self:flex-start}
|
||
.break-wrap h2{
|
||
margin:40px 0 0;
|
||
font-size:220px;font-weight:900;line-height:.95;letter-spacing:-.02em;
|
||
}
|
||
.break-sub{
|
||
margin:48px 0 0;
|
||
font-size:36px;color:var(--ink-dim);font-weight:400;
|
||
}
|
||
|
||
/* ---- 04 · oversized numeral stat ---- */
|
||
.stat-row{display:flex;align-items:baseline;gap:64px;margin-top:40px}
|
||
.stat-num{
|
||
font-size:220px;font-weight:900;letter-spacing:-.03em;line-height:1;
|
||
box-shadow:inset 0 -14px 0 0 rgba(90,200,250,.45);
|
||
}
|
||
.stat-label{
|
||
font-size:48px;font-weight:400;color:var(--ink-dim);
|
||
}
|
||
.stat-foot{
|
||
margin:72px 0 0;
|
||
font-size:22px;letter-spacing:.14em;color:var(--ink-faint);text-transform:uppercase;
|
||
}
|
||
.stat-foot b{color:var(--ink);font-weight:500}
|
||
|
||
/* ---- 05 · three-column evidence ---- */
|
||
.cols3{
|
||
display:grid;grid-template-columns:1fr 1fr 1fr;gap:80px;
|
||
margin-top:64px;
|
||
}
|
||
.col{border-top:1px solid var(--line);padding-top:44px}
|
||
.col-num{
|
||
font-size:88px;font-weight:900;letter-spacing:-.02em;line-height:1;
|
||
color:var(--accent);
|
||
}
|
||
.col-name{
|
||
margin-top:20px;
|
||
font-size:36px;font-weight:700;
|
||
}
|
||
.col-desc{
|
||
margin:24px 0 0;
|
||
font-size:24px;line-height:1.55;color:var(--ink-dim);font-weight:400;
|
||
}
|
||
|
||
/* ---- 06 · comparison spread ---- */
|
||
.cmp-row{display:flex;align-items:baseline;gap:96px;margin-top:56px}
|
||
.cmp-label{font-size:18px;letter-spacing:.18em;text-transform:uppercase;color:var(--ink-faint)}
|
||
.cmp-label.on{color:var(--accent)}
|
||
.cmp-old{
|
||
font-size:120px;font-weight:900;letter-spacing:-.02em;line-height:1;
|
||
color:var(--ink-faint);margin-top:28px;
|
||
text-decoration:line-through;
|
||
text-decoration-color:rgba(90,200,250,.55);
|
||
text-decoration-thickness:8px;
|
||
}
|
||
.cmp-new{
|
||
font-size:220px;font-weight:900;letter-spacing:-.03em;line-height:1;
|
||
margin-top:28px;
|
||
box-shadow:inset 0 -14px 0 0 rgba(90,200,250,.45);
|
||
}
|
||
.cmp-arrow{font-size:88px;color:var(--accent);font-weight:400;align-self:center}
|
||
.cmp-sub{margin-top:28px;font-size:24px;color:var(--ink-dim);font-weight:400}
|
||
.cmp-foot{
|
||
margin:64px 0 0;
|
||
font-size:22px;letter-spacing:.14em;color:var(--accent);
|
||
}
|
||
|
||
/* ---- 07 · flow built from positioned blocks ---- */
|
||
.flow{position:relative;height:560px;margin-top:48px}
|
||
.node{
|
||
position:absolute;box-sizing:border-box;
|
||
border:1px solid var(--line);
|
||
padding:36px 40px;
|
||
background:rgba(245,245,247,.03);
|
||
}
|
||
.node.on{border-color:rgba(90,200,250,.65)}
|
||
.node .n{font-size:18px;letter-spacing:.18em;color:var(--accent)}
|
||
.node h3{margin:18px 0 0;font-size:36px;font-weight:700;line-height:1.1}
|
||
.node p{margin:16px 0 0;font-size:22px;line-height:1.5;color:var(--ink-dim);font-weight:400}
|
||
.edge{
|
||
position:absolute;height:1px;background:rgba(90,200,250,.5);
|
||
transform-origin:0 0;
|
||
}
|
||
|
||
/* ---- 08 · editorial long-quote ---- */
|
||
.quote-wrap{padding-left:200px;position:relative;align-self:flex-start;max-width:1340px}
|
||
.qmark{
|
||
position:absolute;left:0;top:-40px;
|
||
font-size:220px;font-weight:900;color:var(--accent);line-height:1;
|
||
}
|
||
blockquote{
|
||
margin:0;
|
||
font-size:64px;font-weight:700;line-height:1.3;letter-spacing:-.01em;
|
||
}
|
||
.cite{
|
||
margin-top:56px;
|
||
font-size:19px;letter-spacing:.22em;text-transform:uppercase;color:var(--ink-faint);
|
||
}
|
||
|
||
/* ---- 09 · principles list ---- */
|
||
.list-head{
|
||
margin:36px 0 0;
|
||
font-size:88px;font-weight:900;letter-spacing:-.02em;line-height:1.02;
|
||
}
|
||
.plist{list-style:none;margin:72px 0 0;padding:0}
|
||
.plist li{
|
||
display:grid;grid-template-columns:120px 420px 1fr;align-items:baseline;
|
||
border-top:1px solid var(--line);
|
||
padding:30px 0;
|
||
}
|
||
.pnum{font-size:19px;letter-spacing:.18em;color:var(--accent)}
|
||
.pname{font-size:36px;font-weight:700}
|
||
.pdesc{font-size:24px;color:var(--ink-dim);font-weight:400}
|
||
|
||
/* ---- 10 · closing CTA ---- */
|
||
.cta-head{
|
||
margin:36px 0 0;
|
||
font-size:160px;font-weight:900;line-height:.98;letter-spacing:-.025em;
|
||
}
|
||
.cta-links{
|
||
display:flex;gap:80px;margin-top:88px;
|
||
}
|
||
.cta-link .ch{font-size:18px;letter-spacing:.18em;color:var(--ink-faint);text-transform:uppercase}
|
||
.cta-link .cv{margin-top:14px;font-size:26px;color:var(--accent)}
|
||
|
||
@media print{
|
||
body{display:block}
|
||
.stage{transform:none}
|
||
.slide{position:relative;opacity:1;visibility:visible}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="stage">
|
||
|
||
<!-- 01 · full-bleed question cover -->
|
||
<section class="slide active" data-slide-id="1">
|
||
<header class="meta meta-top mono">
|
||
<span>OPEN DESIGN · DECK · OPEN-SLIDE CANVAS</span>
|
||
<span>SEA INDIGO</span>
|
||
<span>№01 / 10</span>
|
||
</header>
|
||
|
||
<div>
|
||
<div class="kicker mono reveal d1">Decision Needed — RFC-014</div>
|
||
<h1 class="reveal d2">
|
||
Local daemon<br/>
|
||
architecture: lock it,<br/>
|
||
or keep it <span class="desk">open</span>?
|
||
</h1>
|
||
<p class="sub reveal d3">
|
||
This review recommends freezing the daemon + agent-runtime data boundary before v1.0 GA. Staff eng, tech leads, and security sign off below.
|
||
</p>
|
||
</div>
|
||
|
||
<footer class="meta meta-bottom mono">
|
||
<span>1920 × 1080 · CANVAS · KBD ← →</span>
|
||
<span class="link">github.com/nexu-io/open-design</span>
|
||
<span>00 : 00 : 00</span>
|
||
</footer>
|
||
</section>
|
||
|
||
<!-- 02 · asymmetric split: statement + narrow aside -->
|
||
<section class="slide" data-slide-id="2">
|
||
<header class="meta meta-top mono">
|
||
<span>OPEN DESIGN · DECK · OPEN-SLIDE CANVAS</span>
|
||
<span>SEA INDIGO</span>
|
||
<span>№02 / 10</span>
|
||
</header>
|
||
|
||
<div class="split">
|
||
<div class="split-main">
|
||
<div class="kicker mono reveal d1">The Problem</div>
|
||
<h2 class="reveal d2">
|
||
Three teams.<br/>
|
||
Three runtimes.<br/>
|
||
<span class="u">Zero agreement.</span>
|
||
</h2>
|
||
</div>
|
||
<aside class="split-aside reveal d3">
|
||
<p>
|
||
Desktop, web, and packaged builds each spawn the agent runtime
|
||
differently today. Namespace collisions and orphaned sidecars
|
||
account for 41% of this quarter's P1 tickets.
|
||
</p>
|
||
<p>Every new agent adapter re-derives its own data path instead of inheriting one resolved root.</p>
|
||
<p class="tags mono">OD_DATA_DIR · SIDECAR-PROTO · P1 × 41%</p>
|
||
</aside>
|
||
</div>
|
||
|
||
<footer class="meta meta-bottom mono">
|
||
<span>1920 × 1080 · CANVAS · KBD ← →</span>
|
||
<span class="link">github.com/nexu-io/open-design</span>
|
||
<span>00 : 02 : 40</span>
|
||
</footer>
|
||
</section>
|
||
|
||
<!-- 03 · full-bleed section break -->
|
||
<section class="slide" data-slide-id="3">
|
||
<header class="meta meta-top mono">
|
||
<span>OPEN DESIGN · DECK · OPEN-SLIDE CANVAS</span>
|
||
<span>SEA INDIGO</span>
|
||
<span>№03 / 10</span>
|
||
</header>
|
||
|
||
<div class="break-wrap">
|
||
<div class="kicker mono reveal d1">Part 01 — The Pain</div>
|
||
<h2 class="reveal d2">DRIFT<span class="accent">.</span></h2>
|
||
<p class="break-sub reveal d3">What happens when every surface guesses its own data root.</p>
|
||
</div>
|
||
|
||
<footer class="meta meta-bottom mono">
|
||
<span>1920 × 1080 · CANVAS · KBD ← →</span>
|
||
<span class="link">discord.gg/mHAjSMV6gz</span>
|
||
<span>00 : 05 : 05</span>
|
||
</footer>
|
||
</section>
|
||
|
||
<!-- 04 · oversized numeral stat -->
|
||
<section class="slide" data-slide-id="4">
|
||
<header class="meta meta-top mono">
|
||
<span>OPEN DESIGN · DECK · OPEN-SLIDE CANVAS</span>
|
||
<span>SEA INDIGO</span>
|
||
<span>№04 / 10</span>
|
||
</header>
|
||
|
||
<div>
|
||
<div class="kicker mono reveal d1">Incident History</div>
|
||
<div class="stat-row reveal d2">
|
||
<span class="stat-num">6</span>
|
||
<span class="stat-label">sidecar identity clashes this quarter</span>
|
||
</div>
|
||
<p class="stat-foot mono reveal d3">
|
||
<b>3 of 6</b> traced to a runtime writing outside RUNTIME_DATA_DIR — root cause, not symptom.
|
||
</p>
|
||
</div>
|
||
|
||
<footer class="meta meta-bottom mono">
|
||
<span>1920 × 1080 · CANVAS · KBD ← →</span>
|
||
<span class="link">github.com/nexu-io/open-design</span>
|
||
<span>00 : 07 : 30</span>
|
||
</footer>
|
||
</section>
|
||
|
||
<!-- 05 · three-column evidence grid -->
|
||
<section class="slide" data-slide-id="5">
|
||
<header class="meta meta-top mono">
|
||
<span>OPEN DESIGN · DECK · OPEN-SLIDE CANVAS</span>
|
||
<span>SEA INDIGO</span>
|
||
<span>№05 / 10</span>
|
||
</header>
|
||
|
||
<div>
|
||
<div class="kicker mono reveal d1">Options On The Table</div>
|
||
<div class="cols3">
|
||
<div class="col reveal d1">
|
||
<div class="col-num">A</div>
|
||
<div class="col-name">status quo</div>
|
||
<p class="col-desc">Each app resolves OD_DATA_DIR itself. Fast to ship, impossible to audit.</p>
|
||
</div>
|
||
<div class="col reveal d2">
|
||
<div class="col-num">B</div>
|
||
<div class="col-name">shared config file</div>
|
||
<p class="col-desc">One JSON on disk every app reads. Removes drift but adds a second source of truth.</p>
|
||
</div>
|
||
<div class="col reveal d3">
|
||
<div class="col-num">C</div>
|
||
<div class="col-name">daemon-resolved root</div>
|
||
<p class="col-desc">server.ts resolves OD_DATA_DIR once into RUNTIME_DATA_DIR; every path derives from it.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<footer class="meta meta-bottom mono">
|
||
<span>1920 × 1080 · CANVAS · KBD ← →</span>
|
||
<span class="link">github.com/nexu-io/open-design</span>
|
||
<span>00 : 10 : 15</span>
|
||
</footer>
|
||
</section>
|
||
|
||
<!-- 06 · comparison spread: the bill -->
|
||
<section class="slide" data-slide-id="6">
|
||
<header class="meta meta-top mono">
|
||
<span>OPEN DESIGN · DECK · OPEN-SLIDE CANVAS</span>
|
||
<span>SEA INDIGO</span>
|
||
<span>№06 / 10</span>
|
||
</header>
|
||
|
||
<div>
|
||
<div class="kicker mono reveal d1">The Tradeoff</div>
|
||
<div class="cmp-row">
|
||
<div class="reveal d2">
|
||
<div class="cmp-label mono">Shared config file (Option B)</div>
|
||
<div class="cmp-old">2 wk</div>
|
||
<div class="cmp-sub">ship time, new failure mode</div>
|
||
</div>
|
||
<div class="cmp-arrow reveal d3">→</div>
|
||
<div class="reveal d4">
|
||
<div class="cmp-label mono on">Daemon-resolved root (Option C)</div>
|
||
<div class="cmp-new">5 wk</div>
|
||
<div class="cmp-sub">one truth source, harder to bypass</div>
|
||
</div>
|
||
</div>
|
||
<p class="cmp-foot mono reveal d5">2wk → 5wk (+3wk) · PAY THE MIGRATION ONCE, NOT PER INCIDENT</p>
|
||
</div>
|
||
|
||
<footer class="meta meta-bottom mono">
|
||
<span>1920 × 1080 · CANVAS · KBD ← →</span>
|
||
<span class="link">x.com/nexudotio</span>
|
||
<span>00 : 13 : 00</span>
|
||
</footer>
|
||
</section>
|
||
|
||
<!-- 07 · flow built from positioned blocks -->
|
||
<section class="slide" data-slide-id="7">
|
||
<header class="meta meta-top mono">
|
||
<span>OPEN DESIGN · DECK · OPEN-SLIDE CANVAS</span>
|
||
<span>SEA INDIGO</span>
|
||
<span>№07 / 10</span>
|
||
</header>
|
||
|
||
<div>
|
||
<div class="kicker mono reveal d1">The Recommendation</div>
|
||
<div class="flow">
|
||
<div class="node reveal d2" style="left:0;top:30px;width:430px">
|
||
<div class="n mono">01 · RESOLVE</div>
|
||
<h3>server.ts owns it</h3>
|
||
<p>OD_DATA_DIR is read exactly once, at daemon startup, into RUNTIME_DATA_DIR.</p>
|
||
</div>
|
||
<div class="edge" style="left:430px;top:160px;width:212px;transform:rotate(33deg)"></div>
|
||
<div class="node on reveal d3" style="left:610px;top:190px;width:460px">
|
||
<div class="n mono">02 · DERIVE</div>
|
||
<h3>Every path descends</h3>
|
||
<p>PROJECTS_DIR, ARTIFACTS_DIR, SQLite, MCP tokens — all constants of RUNTIME_DATA_DIR.</p>
|
||
</div>
|
||
<div class="edge" style="left:1070px;top:330px;width:200px;transform:rotate(36deg)"></div>
|
||
<div class="node reveal d4" style="left:1190px;top:360px;width:410px">
|
||
<div class="n mono">03 · INHERIT</div>
|
||
<h3>Agents don't guess</h3>
|
||
<p>Subprocesses receive the resolved root as OD_DATA_DIR; adapters stop inventing their own.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<footer class="meta meta-bottom mono">
|
||
<span>1920 × 1080 · CANVAS · KBD ← →</span>
|
||
<span class="link">github.com/nexu-io/open-design</span>
|
||
<span>00 : 16 : 20</span>
|
||
</footer>
|
||
</section>
|
||
|
||
<!-- 08 · editorial long-quote -->
|
||
<section class="slide" data-slide-id="8">
|
||
<header class="meta meta-top mono">
|
||
<span>OPEN DESIGN · DECK · OPEN-SLIDE CANVAS</span>
|
||
<span>SEA INDIGO</span>
|
||
<span>№08 / 10</span>
|
||
</header>
|
||
|
||
<div class="quote-wrap">
|
||
<div class="qmark reveal d1">“</div>
|
||
<blockquote class="reveal d2">
|
||
If a change needs a data-path rule not covered here, request a
|
||
core-maintainer decision — <span class="u">don't invent a new convention</span>.
|
||
</blockquote>
|
||
<div class="cite mono reveal d3">— Architecture review · daemon data directory contract, decision record</div>
|
||
</div>
|
||
|
||
<footer class="meta meta-bottom mono">
|
||
<span>1920 × 1080 · CANVAS · KBD ← →</span>
|
||
<span class="link">discord.gg/mHAjSMV6gz</span>
|
||
<span>00 : 19 : 45</span>
|
||
</footer>
|
||
</section>
|
||
|
||
<!-- 09 · principles list -->
|
||
<section class="slide" data-slide-id="9">
|
||
<header class="meta meta-top mono">
|
||
<span>OPEN DESIGN · DECK · OPEN-SLIDE CANVAS</span>
|
||
<span>SEA INDIGO</span>
|
||
<span>№09 / 10</span>
|
||
</header>
|
||
|
||
<div>
|
||
<h2 class="list-head reveal d1">Lock these four, <span class="u">nothing else</span>.</h2>
|
||
<ul class="plist">
|
||
<li class="reveal d2">
|
||
<span class="pnum mono">01</span>
|
||
<span class="pname">Single root</span>
|
||
<span class="pdesc">RUNTIME_DATA_DIR is the only daemon data-root truth source — no exceptions.</span>
|
||
</li>
|
||
<li class="reveal d3">
|
||
<span class="pnum mono">02</span>
|
||
<span class="pname">Named exceptions only</span>
|
||
<span class="pdesc">OD_MEDIA_CONFIG_DIR and OD_LEGACY_DATA_DIR are the sole sanctioned overrides.</span>
|
||
</li>
|
||
<li class="reveal d4">
|
||
<span class="pnum mono">03</span>
|
||
<span class="pname">Inherited, not inferred</span>
|
||
<span class="pdesc">Agent subprocesses receive OD_DATA_DIR from the daemon; they never resolve their own.</span>
|
||
</li>
|
||
<li class="reveal d5">
|
||
<span class="pnum mono">04</span>
|
||
<span class="pname">Escape hatches banned</span>
|
||
<span class="pdesc">Cwd-relative defaults and per-adapter data-root helpers are blocked in review, not just noted.</span>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<footer class="meta meta-bottom mono">
|
||
<span>1920 × 1080 · CANVAS · KBD ← →</span>
|
||
<span class="link">github.com/nexu-io/open-design</span>
|
||
<span>00 : 22 : 10</span>
|
||
</footer>
|
||
</section>
|
||
|
||
<!-- 10 · closing CTA -->
|
||
<section class="slide" data-slide-id="10">
|
||
<header class="meta meta-top mono">
|
||
<span>OPEN DESIGN · DECK · OPEN-SLIDE CANVAS</span>
|
||
<span>SEA INDIGO</span>
|
||
<span>№10 / 10</span>
|
||
</header>
|
||
|
||
<div>
|
||
<div class="kicker mono reveal d1">Closing</div>
|
||
<h2 class="cta-head reveal d2">Run it <span class="u">tonight</span>.</h2>
|
||
<div class="cta-links reveal d3">
|
||
<div class="cta-link">
|
||
<div class="ch mono">Star & fork</div>
|
||
<div class="cv mono">github.com/nexu-io/open-design</div>
|
||
</div>
|
||
<div class="cta-link">
|
||
<div class="ch mono">Community</div>
|
||
<div class="cv mono">discord.gg/mHAjSMV6gz</div>
|
||
</div>
|
||
<div class="cta-link">
|
||
<div class="ch mono">Updates</div>
|
||
<div class="cv mono">x.com/nexudotio</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<footer class="meta meta-bottom mono">
|
||
<span>1920 × 1080 · CANVAS · KBD ← →</span>
|
||
<span class="link">github.com/nexu-io/open-design</span>
|
||
<span>00 : 24 : 30</span>
|
||
</footer>
|
||
</section>
|
||
|
||
</div>
|
||
|
||
<script>
|
||
// keyboard left/right + hash sync (#1 .. #10)
|
||
(function(){
|
||
var slides = Array.prototype.slice.call(document.querySelectorAll('.slide'));
|
||
var cur = 0;
|
||
function show(i){
|
||
i = Math.max(0, Math.min(slides.length - 1, i));
|
||
if (i === cur && slides[cur].classList.contains('active')) return;
|
||
slides[cur].classList.remove('active');
|
||
cur = i;
|
||
slides[cur].classList.add('active');
|
||
var h = '#' + (cur + 1);
|
||
if (location.hash !== h) history.replaceState(null, '', h);
|
||
}
|
||
function fromHash(){
|
||
var n = parseInt(location.hash.slice(1), 10);
|
||
if (n >= 1 && n <= slides.length) show(n - 1);
|
||
}
|
||
addEventListener('keydown', function(e){
|
||
if (e.key === 'ArrowRight' || e.key === 'PageDown' || e.key === ' ') show(cur + 1);
|
||
else if (e.key === 'ArrowLeft' || e.key === 'PageUp') show(cur - 1);
|
||
});
|
||
addEventListener('hashchange', fromHash);
|
||
fromHash();
|
||
})();
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|