|
| 1 | +# iOS Skin + OS Auto-Detection Implementation Plan |
| 2 | + |
| 3 | +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. |
| 4 | +
|
| 5 | +**Goal:** Add a third skin to captkernel.com — an iPhone-springboard iOS UI — with OS auto-detection routing iPhone→iOS, Mac/iPad→macOS, everything else→Linux. |
| 6 | + |
| 7 | +**Architecture:** All inside `index.html` (single-file site, no build step). `body.ios` + `osMode==='ios'`; `initIOS()` builds the springboard DOM (the `initMobile()` precedent) reusing the existing `FEATURED`/`WIP`/`WORKROWS`/kernel/terminal data and builders. All new CSS scoped under `body.ios`. |
| 8 | + |
| 9 | +**Tech Stack:** Vanilla JS + CSS in `index.html`; verification via `node` syntax check + Playwright MCP iPhone emulation. |
| 10 | + |
| 11 | +## Global Constraints |
| 12 | + |
| 13 | +- Linux and macOS skins must be pixel-untouched (all new CSS scoped `body.ios`). |
| 14 | +- Skin priority: `?os=` → localStorage explicit choice → platform detection → linux. Detection never overrides an explicit choice. |
| 15 | +- iPad routes to **macOS** (UA `iPad`, or Mac platform + `maxTouchPoints > 1`). |
| 16 | +- No dates or cadence promises in any new copy. |
| 17 | +- Single file, no libraries, GitHub Pages static. |
| 18 | +- Safe areas: `viewport-fit=cover` + `env(safe-area-inset-*)`. |
| 19 | + |
| 20 | +**Verification harness (used by every task):** `node -e "<extract inline <script> blocks, new Function() each>"` for syntax; Playwright MCP with iPhone 15 viewport (393×852, DPR 3) + iPhone UA for behavior; desktop viewport for regression. |
| 21 | + |
| 22 | +--- |
| 23 | + |
| 24 | +### Task 1: Detection + routing + 3-way OS switch |
| 25 | + |
| 26 | +**Files:** Modify `index.html` (~line 559-562 OS switch buttons; ~line 1605-1613 osMode boot block) |
| 27 | + |
| 28 | +**Interfaces — Produces:** global `osMode` may now be `'ios'`; `body.ios` class set at boot; localStorage key `capk.os` stores explicit choice; `detectOS()` returns `'ios'|'macos'|'linux'`. |
| 29 | + |
| 30 | +- [ ] Add `detectOS()` and rework the boot block: |
| 31 | + |
| 32 | +```js |
| 33 | +function detectOS(){ |
| 34 | + try{ |
| 35 | + var ua=navigator.userAgent||'', plat=(navigator.userAgentData&&navigator.userAgentData.platform)||navigator.platform||''; |
| 36 | + if(/iPhone/.test(ua)) return 'ios'; |
| 37 | + if(/iPad/.test(ua) || (/^Mac/.test(plat)&&navigator.maxTouchPoints>1)) return 'macos'; // iPadOS masquerades as Mac |
| 38 | + if(/^Mac/.test(plat) || plat==='macOS') return 'macos'; |
| 39 | + return 'linux'; |
| 40 | + }catch(e){ return 'linux'; } |
| 41 | +} |
| 42 | +``` |
| 43 | + |
| 44 | +Boot priority (replace the existing `?os=` try/catch; keep variable name `osMode`): |
| 45 | + |
| 46 | +```js |
| 47 | +var osMode='linux'; |
| 48 | +try{ var _sav=localStorage.getItem('capk.os'); if(_sav==='macos'||_sav==='linux'||_sav==='ios') osMode=_sav; else osMode=detectOS(); }catch(e){ osMode=detectOS(); } |
| 49 | +try{ var _qos=new URLSearchParams(location.search).get('os'); if(_qos==='macos'||_qos==='linux'||_qos==='ios') osMode=_qos; }catch(e){} |
| 50 | +``` |
| 51 | + |
| 52 | +- [ ] Add third switch button `<button type="button" data-os="ios">iOS</button>`; the existing switch click handler must write `localStorage.setItem('capk.os', chosen)` and reload/apply. Check how linux/macos switching applies today and extend identically. |
| 53 | +- [ ] Verify: node syntax check passes; Playwright with iPhone UA lands on `body.ios` (empty for now is fine — guard `initIOS` calls until Task 2 with `typeof initIOS==='function'`), Mac UA → `body.macos`, Windows UA → linux; `?os=linux` on iPhone UA → linux. |
| 54 | +- [ ] Commit: `feat: OS auto-detection + 3-way skin switch (ios mode scaffold)` |
| 55 | + |
| 56 | +### Task 2: Springboard DOM + core iOS CSS |
| 57 | + |
| 58 | +**Files:** Modify `index.html` (new `<div id="ios"></div>` near `#mobile`; new `body.ios` CSS section after the macOS section; new `initIOS()` near `initMobile()`; boot: `if(osMode==='ios'){document.body.classList.add('ios');initIOS();}` — iOS mode bypasses `initMobile`) |
| 59 | + |
| 60 | +**Interfaces — Produces:** `initIOS()`; `#ios .sb-icon[data-app]` grid icons; `#ios .dock-ios`; `iosOpen(appKey)` stub called on icon tap (implemented Task 3). |
| 61 | + |
| 62 | +- [ ] Build springboard in `initIOS()`: status bar (`.sb-status` with live clock via `setInterval` 30s + static signal/wifi/battery glyphs), wallpaper (reuse starfield canvas behind, reduced count), hero widget (`.sb-widget`: name / @captkernel / "solo AI builder — I direct, agents build" / status line from existing About copy), icon grid (About ◎, Systems ▦, The Kernel ✎, System Info ◐, Connect ✉, C2B ◆→`location.href='/c2b/'`), dock (Systems, Kernel, Terminal ▸_, Connect), home indicator (`.sb-home`). |
| 63 | +- [ ] Core CSS tokens under `body.ios`: `-apple-system,system-ui` type; bg `#000`; accent `#0a84ff`; icons 60×60 r=14 gradient tiles with 11px labels; dock frosted (`backdrop-filter:blur(20px);background:rgba(60,60,67,.4)`); grid `padding: calc(env(safe-area-inset-top) + 54px) 24px 0`; home indicator 134×5 r=3 `rgba(255,255,255,.6)`. |
| 64 | +- [ ] Verify: Playwright iPhone UA screenshot shows status bar, widget, 6-icon grid, 4-icon dock, indicator; desktop linux/macos screenshots unchanged. |
| 65 | +- [ ] Commit: `feat(ios): springboard home screen (status bar, widget, icon grid, dock)` |
| 66 | + |
| 67 | +### Task 3: App sheets — open/close + iOS content restyle |
| 68 | + |
| 69 | +**Files:** Modify `index.html` (`iosOpen`/`iosClose` in the iOS section; sheet CSS under `body.ios`) |
| 70 | + |
| 71 | +**Interfaces — Consumes:** existing content builders (`workHtml()`, kernel/about/fetch/connect window content markup — reuse exactly what `initMobile()` reuses). **Produces:** `.ios-sheet` full-screen container with `.ios-nav` (`‹ Back` + title) + `.ios-body`. |
| 72 | + |
| 73 | +- [ ] `iosOpen(key)`: build (once, cache) a `.ios-sheet` per app; populate `.ios-body` from the same content source `initMobile` uses for that window; add `.open` class → CSS transition `transform:scale(.92)→1` + opacity, 260ms cubic-bezier(.32,.72,.35,1). `iosClose()`: reverse, return to springboard. Back button + home-indicator tap/swipe-up (touchend after upward touchmove ≥40px on `.sb-home`) both close. |
| 74 | +- [ ] Sheet content CSS: grouped cards `border-radius:14px;background:#1c1c1e`; section headers uppercase 13px `#8e8e93`; links/accents `#0a84ff`; nav bar 52px + safe-area top, blurred `rgba(28,28,30,.72)`; strip Linux-specific chrome (dmesg boot lines etc.) the way `body.macos` does (`display:none` rules). |
| 75 | +- [ ] Verify: Playwright — tap each of About/Systems/Kernel/System Info/Connect: sheet opens with title + content, Back closes; C2B icon navigates to `/c2b/`. |
| 76 | +- [ ] Commit: `feat(ios): full-screen app sheets with iOS chrome over existing content` |
| 77 | + |
| 78 | +### Task 4: Terminal app |
| 79 | + |
| 80 | +**Files:** Modify `index.html` (terminal wiring in `iosOpen('term')`) |
| 81 | + |
| 82 | +**Interfaces — Consumes:** existing terminal command handler (the function the desktop `term` window uses for input → output; reuse, do not fork command logic). |
| 83 | + |
| 84 | +- [ ] `iosOpen('term')` builds a full-screen terminal sheet: mono font, existing prompt string, an `<input>` pinned above the keyboard (`position:sticky;bottom:0` + safe-area), output log scrolls. Wire input to the existing command handler; `clear` works; history renders. |
| 85 | +- [ ] Verify: Playwright — open Terminal, type `help` then `whoami`, output appears; Back returns to springboard. |
| 86 | +- [ ] Commit: `feat(ios): terminal app reusing the zsh command engine` |
| 87 | + |
| 88 | +### Task 5: Polish + full regression + deploy |
| 89 | + |
| 90 | +**Files:** Modify `index.html` (`theme-color` meta per skin; `viewport-fit=cover`; final tweaks) |
| 91 | + |
| 92 | +- [ ] `viewport-fit=cover` in the viewport meta; set `theme-color` to `#000` when `body.ios` (JS swap at boot). |
| 93 | +- [ ] Full Playwright pass: detection matrix (iPhone/iPad/Mac/Windows/Android UAs → ios/macos/macos/linux/linux); `?os=ios` on desktop renders; switch tap persists across reload (`capk.os`); linux + macos desktop and ≤820px mobile screenshots unchanged vs pre-branch; node syntax check. |
| 94 | +- [ ] Commit + push master; post-deploy check `https://captkernel.com/?os=ios`. |
| 95 | +- [ ] Commit: `feat: ship iOS springboard skin + OS auto-detection` |
| 96 | + |
| 97 | +--- |
| 98 | + |
| 99 | +**Self-review done:** every spec section maps to a task (detection→1, springboard→2, sheets→3, terminal→4, constraints/testing→5); no placeholders — where code is summarized (CSS values) the exact values are stated inline; names consistent (`osMode`, `capk.os`, `initIOS`, `iosOpen`/`iosClose`, `.ios-sheet`). |
0 commit comments