diff --git a/docs/screenshots/issue-62/home-1440x900.png b/docs/screenshots/issue-62/home-1440x900.png new file mode 100644 index 000000000..978c7bf09 Binary files /dev/null and b/docs/screenshots/issue-62/home-1440x900.png differ diff --git a/docs/screenshots/issue-62/home-390x844.png b/docs/screenshots/issue-62/home-390x844.png new file mode 100644 index 000000000..9000e4221 Binary files /dev/null and b/docs/screenshots/issue-62/home-390x844.png differ diff --git a/site/favicon.svg b/site/favicon.svg new file mode 100644 index 000000000..75fcad056 --- /dev/null +++ b/site/favicon.svg @@ -0,0 +1 @@ + diff --git a/site/index.html b/site/index.html new file mode 100644 index 000000000..db7e2c95b --- /dev/null +++ b/site/index.html @@ -0,0 +1,61 @@ + + + + + +thirdshift: your issues go to press overnight + + + + + + + + + + + + + +
+
+
+ + +
+
+ + + Proof · pulled at 03:12 · unit 4 of 4 +
+

Your issues go to press overnight.

+
+
+

The humans are the day shift: you talk the idea through, write the spec and cut it into issues. The agents work the third shift: give thirdshift an Issue URL and it implements the issue, reviews its own work and opens a pull request that is ready for review by morning.

+

Built on Matt Pocock's skills: aihero.dev/skills · mattpocock/skills

+
+
+

Install

+
curl -fsSL https://thirdshift.app/install.sh | sh
+
Show the full commandcurl -LsSf https://github.com/JacobStephens2/thirdshift/releases/latest/download/thirdshift-installer.sh | sh
+
+
+ +
+
+
+
+ + + + + diff --git a/site/main.js b/site/main.js new file mode 100644 index 000000000..08d026ba2 --- /dev/null +++ b/site/main.js @@ -0,0 +1,15 @@ +// Copy buttons: put the command next to the button on the clipboard. +for (const button of document.querySelectorAll(".install button.copy")) { + const code = button.closest(".install").querySelector("code"); + button.addEventListener("click", async () => { + try { + await navigator.clipboard.writeText(code.textContent); + button.textContent = "Copied"; + } catch { + // No clipboard access (e.g. an insecure origin): select the command so it can be copied by hand. + getSelection().selectAllChildren(code); + button.textContent = "Selected"; + } + setTimeout(() => { button.textContent = "Copy"; }, 1600); + }); +} diff --git a/site/robots.txt b/site/robots.txt new file mode 100644 index 000000000..c2a49f4fb --- /dev/null +++ b/site/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Allow: / diff --git a/site/styles.css b/site/styles.css new file mode 100644 index 000000000..ec6e13c1b --- /dev/null +++ b/site/styles.css @@ -0,0 +1,131 @@ +/* thirdshift.app: the one shared stylesheet. No build step. */ + +/* ---------- Tokens: ink set A "Process" and the "Subtle" effects (prototype/site @ 5b559d0) ---------- */ +:root { + color-scheme: dark; + --k: #0A0A0A; --k2: #141414; --k3: #1E1E1E; + --paper: #E8E6E1; --dim: #9A978F; --rule: #2A2A2A; + /* Process magenta (--m) is for large text and fills only; small magenta text uses --m-text. */ + --c: #00AEEF; --m: #EC008C; --m-text: #FF5CB8; --y: #FFF200; + --nc: #00FFFF; --nm: #FF00FF; --ny: #FFFF00; /* glows only */ + --grid: rgba(0,174,239,.07); + --f-head: "Big Shoulders Display", "Big Shoulders", Impact, sans-serif; + --f-head-w: 800; + --f-body: "JetBrains Mono", ui-monospace, monospace; + --f-body-size: 15px; + --f-mono: "JetBrains Mono", ui-monospace, monospace; + --f-colo: "Playfair Display", Georgia, serif; + /* Effects: halftone 35%, misregistration 1px, scanlines 12%. */ + --ht: .35; --mr: 1px; --sl: .12; +} + +/* ---------- Base ---------- */ +* { box-sizing: border-box; } +[hidden] { display: none !important; } +html { background: var(--k); } +body { + margin: 0; color: var(--paper); + font: 400 var(--f-body-size)/1.6 var(--f-body); + padding-inline: max(16px, env(safe-area-inset-left, 0px)); + -webkit-font-smoothing: antialiased; +} +a { color: var(--c); text-underline-offset: 3px; } +a:hover { color: var(--nc); } +:focus-visible { outline: 2px solid var(--y); outline-offset: 3px; } +code, kbd, pre { font-family: var(--f-mono); } +h1, h2, h3 { font-family: var(--f-head); font-weight: var(--f-head-w); line-height: .95; text-wrap: balance; margin: 0; letter-spacing: .01em; } +.wrap { max-width: 1180px; margin-inline: auto; } +.eyebrow { font: 700 12px/1 var(--f-mono); letter-spacing: .18em; text-transform: uppercase; color: var(--dim); margin: 0; } + +/* ---------- Print effects ---------- */ +/* The faint blueprint grid, for the diagrams drawn on it. */ +.grid-bg { + background-color: var(--k); + background-image: + linear-gradient(var(--grid) 1px, transparent 1px), + linear-gradient(90deg, var(--grid) 1px, transparent 1px); + background-size: 24px 24px; +} +body::after { /* scanlines */ + content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 50; + background: repeating-linear-gradient(to bottom, rgba(0,0,0,var(--sl)) 0 1px, transparent 1px 3px); +} +.misreg { text-shadow: + calc(var(--mr) * -1) 0 0 color-mix(in srgb, var(--c) 75%, transparent), + var(--mr) calc(var(--mr) * .6) 0 color-mix(in srgb, var(--m) 70%, transparent); } +.ht { position: relative; isolation: isolate; } +.ht::after { /* halftone screen over an ink fill */ + content: ""; position: absolute; inset: 0; pointer-events: none; opacity: var(--ht); + background: radial-gradient(circle at center, rgba(0,0,0,.85) 0 1.1px, transparent 1.6px) 0 0 / 5px 5px; + mix-blend-mode: multiply; +} + +/* ---------- Press marks ---------- */ +.colorbar { display: flex; gap: 2px; align-items: stretch; height: 14px; } +.colorbar i { flex: 1; min-width: 10px; } +.colorbar .cb-c { background: var(--c); } .colorbar .cb-m { background: var(--m); } +.colorbar .cb-y { background: var(--y); } .colorbar .cb-k { background: #000; outline: 1px solid var(--dim); outline-offset: -1px; } +.colorbar .cb-c50 { background: color-mix(in srgb, var(--c) 50%, var(--k)); } +.colorbar .cb-m50 { background: color-mix(in srgb, var(--m) 50%, var(--k)); } +.colorbar .cb-y50 { background: color-mix(in srgb, var(--y) 50%, var(--k)); } +.reg { width: 28px; height: 28px; color: var(--paper); flex: none; } +.crop { position: absolute; width: 22px; height: 22px; border-color: var(--dim); border-style: solid; border-width: 0; } +.crop.tl { top: 0; left: 0; border-right-width: 1px; border-bottom-width: 1px; } +.crop.tr { top: 0; right: 0; border-left-width: 1px; border-bottom-width: 1px; } +.crop.bl { bottom: 0; left: 0; border-right-width: 1px; border-top-width: 1px; } +.crop.br { bottom: 0; right: 0; border-left-width: 1px; border-top-width: 1px; } + +/* ---------- Install block ---------- */ +.install { display: flex; align-items: stretch; border: 1px solid var(--rule); background: #000; max-width: 100%; } +.install code { flex: 1; min-width: 0; padding: 14px 16px; font-size: 15px; white-space: nowrap; overflow-x: auto; color: var(--paper); } +.install code::before { content: "$ "; color: var(--dim); } +.install button { font: 700 12px/1 var(--f-mono); letter-spacing: .12em; text-transform: uppercase; border: 0; border-left: 1px solid var(--rule); + background: var(--y); color: #000; padding: 0 18px; cursor: pointer; } +.install button:hover { background: var(--ny); } +.install-more { margin-top: 10px; font-size: 13px; color: var(--dim); } +.install-more summary { cursor: pointer; width: fit-content; } +.install-more code { display: block; margin-top: 8px; padding: 10px 12px; background: #000; border: 1px dashed var(--rule); color: var(--paper); overflow-x: auto; white-space: nowrap; } +.credit { font-size: 14px; color: var(--dim); margin: 0; } +.framing { max-width: 62ch; margin: 0; } +.framing b { color: var(--paper); font-weight: 700; } + +/* ---------- Hero: the proof sheet ("Proof, compact") ---------- */ +/* Never faded in: the hero is visible on first paint. */ +.hero { padding-block: 28px 44px; } +.hero .wrap { display: grid; justify-items: center; } +.sheet-wrap { position: relative; padding: 26px; width: min(100%, 1060px); } +.sheet-wrap .reg { position: absolute; top: calc(50% - 14px); } +.sheet-wrap .reg.l { left: -10px; } .sheet-wrap .reg.r { right: -10px; } +.paper-sheet { background: var(--paper); color: #111; padding: clamp(20px, 4vw, 44px); display: grid; gap: 18px; transform: rotate(-.5deg); + box-shadow: 0 30px 60px -20px rgba(0,0,0,.9), 0 0 0 1px rgba(255,255,255,.05); } +.paper-sheet .topline { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; flex-wrap: wrap; border-bottom: 2px solid #111; padding-bottom: 8px; } +.paper-sheet .mark { display: block; height: clamp(30px, 5vw, 52px); width: auto; fill: currentColor; } +.paper-sheet .slug { font: 700 11px/1.3 var(--f-mono); letter-spacing: .14em; text-transform: uppercase; color: #555; } +.paper-sheet h1 { font-size: clamp(44px, 7.2vw, 100px); color: #0b0b0b; } +.paper-sheet .framing { color: #2a2a2a; font-size: 16px; } +.paper-sheet .framing b { color: #000; } +.paper-sheet .credit { color: #444; } +.paper-sheet a { color: #0070a8; } +.paper-sheet .colorbar { height: 16px; margin-top: 6px; } +.paper-sheet .install { border-color: #000; } +.paper-sheet .install code { font-size: 13px; padding-inline: 12px; } +.paper-sheet .install-more { color: #555; } +.proof-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr); gap: 28px; align-items: start; } +.proof-row > div { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; } +.proof-row .eyebrow { color: #555; } +@media (max-width: 800px) { .proof-row { grid-template-columns: 1fr; } } +/* Phones: tighter margins, so the install command stays on the first screen. */ +@media (max-width: 560px) { + .hero { padding-block: 8px 28px; } + .sheet-wrap { padding: 16px 12px; } + .paper-sheet { gap: 14px; } + .paper-sheet .framing { font-size: 14px; line-height: 1.5; } + .proof-row { gap: 18px; } +} + +/* ---------- Footer ---------- */ +.foot { border-top: 1px solid var(--rule); padding-block: 28px; display: flex; flex-wrap: wrap; gap: 10px 26px; font-size: 13px; color: var(--dim); } + +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { animation: none !important; transition: none !important; } +}