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.
Goal: Make www/v3/de/index.html render correctly on every screen size (320px phone → wide desktop), with no horizontal overflow and a usable mobile nav.
Architecture: Extract layout styles that are currently locked in inline style= attributes into CSS classes, then add breakpoints. Because the homepage loads v3.css and product.css (the latter wins on source order and duplicates .wrap/nav rules), all new shared responsive rules go into a new responsive.css linked last so they reliably win the cascade. Section-specific styles already in in-body <style> blocks (#integration-orbit, #north-star) are edited in place. A small Playwright script provides automated overflow checks + before/after screenshots.
Tech Stack: Static HTML/CSS, vanilla JS (chrome.de.js renders the shared header). Playwright (Chromium) for verification only.
1. Workspace & uncommitted work — already resolved. This plan executes in an isolated git worktree at /Users/maximilianbrandstaetter/Orcha/.claude/worktrees/website-v3-mobile-responsive, on branch website-v3-mobile-responsive (based off v3-agents-and-testimonials-carousel). The pre-responsive homepage work is already checkpointed in commit 7e04ad3dd "WIP: snapshot before worktree consolidation", and the working tree is clean. So per-task commits below start from a clean tree — no action needed, and the Task 5 note about resolving this is satisfied.
2. Local server. Tasks verify against http://127.0.0.1:8123/v3/de/. The controller has already started it from this worktree's www/. To restart it (kill any stale instance first):
pkill -f "http.server 8123"; cd /Users/maximilianbrandstaetter/Orcha/.claude/worktrees/website-v3-mobile-responsive/www && (python3 -m http.server 8123 --bind 127.0.0.1 >/tmp/orcha-v3-www.log 2>&1 &)
3. Cascade facts (why CSS goes where it goes).
de/index.html loads v3.css then product.css. Both define .wrap, .nav, .nav-inner, .nav-links, .nav-cta, .logo, .btn unconditionally — so product.css wins ties. A media-query override of .wrap placed in v3.css would lose to product.css's base rule. → Shared overrides go in responsive.css, linked after product.css.product.css has @media (max-width: 960px) { .nav-links > a:not(.nav-links-home) { display:none } }. The mobile nav in this plan uses the 960px breakpoint (not the spec's 768px) specifically to align with this existing rule and avoid a 768–960px dead zone. This is a deliberate, documented deviation from the spec's breakpoint standard; section grids still use 1024/768/480.<style> blocks (#integration-orbit at index.html:1193, #north-star at index.html:74) come after all <link>s in document order, so they win over responsive.css. Edits to those sections are made in those blocks, not in responsive.css.| File | Status | Responsibility |
|---|---|---|
www/v3/dev/screenshot.mjs |
create | Playwright verification harness — loads the page at 5 widths, fails on horizontal overflow, writes screenshots. |
www/v3/dev/package.json |
create | Pins Playwright for the harness. |
www/v3/dev/.gitignore |
create | Ignores node_modules/ and shots/. |
www/v3/css/responsive.css |
create | All new shared responsive rules: global .wrap/section padding, mobile nav drawer, footer grid, and #case/#security/#pricing/hero section classes. |
www/v3/de/index.html |
modify | Add responsive.css link; swap inline layout style= attrs → classes; fix orbit node positions + in-body <style>; north-star tweak; remove stray </div>s. |
www/v3/js/chrome.de.js |
modify | Add hamburger button + .nav-drawer wrapper to the rendered header; add wireNav() toggle logic. |
Files:
Create: www/v3/dev/package.json
Create: www/v3/dev/.gitignore
Create: www/v3/dev/screenshot.mjs
Step 1: Create www/v3/dev/package.json
{
"name": "orcha-v3-dev",
"private": true,
"type": "module",
"devDependencies": {
"playwright": "^1.48.0"
}
}
www/v3/dev/.gitignorenode_modules/
shots/
www/v3/dev/screenshot.mjs// Responsive verification harness for the v3 German homepage.
// Loads the page at several widths, fails on horizontal overflow,
// and writes full-page screenshots to ./shots for visual review.
import { chromium } from "playwright";
import { mkdirSync } from "node:fs";
import { fileURLToPath } from "node:url";
const URL = process.env.URL || "http://127.0.0.1:8123/v3/de/";
const WIDTHS = [320, 375, 768, 1024, 1280];
const OUT = fileURLToPath(new URL("./shots/", import.meta.url));
mkdirSync(OUT, { recursive: true });
const browser = await chromium.launch();
let failed = false;
for (const width of WIDTHS) {
const page = await browser.newPage({ viewport: { width, height: 900 } });
await page.goto(URL, { waitUntil: "networkidle" });
const overflow = await page.evaluate(() => {
const de = document.documentElement;
return de.scrollWidth - de.clientWidth;
});
await page.screenshot({ path: `${OUT}home-${width}.png`, fullPage: true });
const status = overflow > 1 ? `FAIL (+${overflow}px wide)` : "ok";
if (overflow > 1) failed = true;
console.log(` ${String(width).padStart(4)}px ${status}`);
await page.close();
}
await browser.close();
console.log(failed ? "\nHORIZONTAL OVERFLOW DETECTED" : "\nno horizontal overflow at any width");
process.exit(failed ? 1 : 0);
Run:
cd /Users/maximilianbrandstaetter/Orcha/.claude/worktrees/website-v3-mobile-responsive/www/v3/dev && npm install && npx playwright install chromium
Expected: npm install completes; playwright install downloads Chromium (may take a minute).
Ensure the server is running (see Prerequisites #2), then run:
cd /Users/maximilianbrandstaetter/Orcha/.claude/worktrees/website-v3-mobile-responsive/www/v3/dev && node screenshot.mjs
Expected: exits non-zero — HORIZONTAL OVERFLOW DETECTED, with FAIL on at least the 320px and 375px rows. This confirms the harness detects the current breakage. The shots/ PNGs are the before-state reference.
git add www/v3/dev/package.json www/v3/dev/.gitignore www/v3/dev/screenshot.mjs
git commit -m "test: add Playwright responsive verification harness for v3 homepage"
Files:
Create: www/v3/css/responsive.css
Modify: www/v3/de/index.html:12 (add stylesheet link)
Step 1: Create www/v3/css/responsive.css
/* ═══════════════════════════════════════════════════════════════
responsive.css — v3 responsive rules (added 2026-05-14)
Linked AFTER v3.css and product.css so these rules win the cascade.
Breakpoint scale: 1024px tablet · 768px large phone · 480px phone.
(Mobile nav uses 960px to align with product.css's existing nav query.)
═══════════════════════════════════════════════════════════════ */
/* ───── Global: container + section rhythm ───── */
@media (max-width: 768px) {
.wrap { padding: 0 24px; }
section { padding: 80px 0; }
section:first-of-type { padding-top: 56px; }
}
@media (max-width: 480px) {
.wrap { padding: 0 16px; }
section { padding: 56px 0; }
section:first-of-type { padding-top: 40px; }
}
responsive.css in index.htmlIn www/v3/de/index.html, find line 12:
<link rel="stylesheet" href="../css/product.css?v=checklist">
Add immediately after it:
<link rel="stylesheet" href="../css/responsive.css?v=checklist">
Run the harness:
cd /Users/maximilianbrandstaetter/Orcha/.claude/worktrees/website-v3-mobile-responsive/www/v3/dev && node screenshot.mjs
Expected: still fails overall (sections not yet fixed), but open shots/home-375.png — side padding is now visibly tighter (24px, not 32px). No new breakage vs the baseline.
git add www/v3/css/responsive.css www/v3/de/index.html
git commit -m "feat(v3): add responsive.css with global container + section padding"
Files:
Modify: www/v3/css/responsive.css (append)
Step 1: Append the mobile-nav block to responsive.css
Append at the end of www/v3/css/responsive.css:
/* ───── Mobile nav: hamburger + drawer ─────
chrome.de.js wraps .nav-links + .nav-cta in <div class="nav-drawer">
and adds <button class="nav-toggle">. .nav gets .is-open when open. */
.nav-drawer { display: contents; } /* desktop: transparent, no layout change */
.nav-toggle {
display: none;
flex-direction: column;
justify-content: center;
gap: 5px;
width: 40px;
height: 40px;
margin-left: 8px;
background: none;
border: 0;
cursor: pointer;
}
.nav-toggle span {
display: block;
width: 20px;
height: 2px;
background: var(--ink);
border-radius: 2px;
transition: transform .2s ease, opacity .2s ease;
}
.nav.is-open .nav-toggle span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav.is-open .nav-toggle span:nth-child(2) { opacity: 0; }
.nav.is-open .nav-toggle span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
@media (max-width: 960px) {
.nav-toggle { display: flex; }
.nav-drawer {
display: none;
/* anchors to .nav (position:sticky); .nav-inner is not positioned */
position: absolute;
left: 0;
right: 0;
top: 100%;
flex-direction: column;
background: var(--bg);
border-bottom: 1px solid var(--line);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.08);
padding: 12px 24px 20px;
max-height: calc(100vh - 64px);
overflow-y: auto;
}
.nav.is-open .nav-drawer { display: flex; }
.nav-links {
flex-direction: column;
align-items: stretch;
gap: 0;
}
/* override product.css @960 `.nav-links > a:not(.nav-links-home) { display:none }`:
scope to .nav-drawer so the override reaches (0,2,1) specificity and wins
on source order — a bare `.nav-links > a` (0,1,1) would lose to product.css. */
.nav-drawer .nav-links > a,
.nav-drawer .nav-links > .nav-dd > a {
display: block;
padding: 13px 0;
border-bottom: 1px solid var(--line);
font-size: 16px;
}
.nav-links > .nav-dd { width: 100%; }
.nav-dd > a::after { display: none; } /* hide the dropdown caret */
/* Produkt dropdown flattens — panel sits inline, always visible */
.nav-dd-panel {
position: static;
width: auto;
opacity: 1;
pointer-events: auto;
transform: none;
border: 0;
box-shadow: none;
padding: 4px 0 8px;
}
.nav-dd-panel::before,
.nav-dd-panel::after { display: none; }
.nav-dd-header { display: none; }
.nav-dd-grid { grid-template-columns: 1fr; }
.nav-dd-item { padding: 10px 8px; }
.nav-cta {
flex-direction: column;
align-items: stretch;
gap: 10px;
margin-top: 14px;
}
.nav-cta .btn { justify-content: center; }
.lang-switch { align-self: flex-start; }
}
Run the harness, then open shots/home-1280.png: the header must look unchanged (.nav-drawer { display: contents } makes it transparent on desktop; .nav-toggle is display:none). Mobile shots will still look unchanged until Task 4 adds the markup the selectors target.
git add www/v3/css/responsive.css
git commit -m "feat(v3): add mobile nav drawer styles"
Files:
Modify: www/v3/js/chrome.de.js:87-122 (header template), :198-205 (mount block)
Step 1: Wrap nav-links + nav-cta in .nav-drawer and add the toggle button
In www/v3/js/chrome.de.js, in renderHeader, the template currently is (lines 87-122):
target.innerHTML = `
<div class="nav">
<div class="wrap nav-inner">
<a class="logo" href="${homeHref}" aria-label="Orcha – Startseite">
<img src="${logoSrc}" alt="Orcha" height="22" style="display:block;height:22px;width:auto;">
</a>
<nav class="nav-links">
Change the opening of the inner block so <nav class="nav-links"> is preceded by a .nav-drawer wrapper — replace:
<a class="logo" href="${homeHref}" aria-label="Orcha – Startseite">
<img src="${logoSrc}" alt="Orcha" height="22" style="display:block;height:22px;width:auto;">
</a>
<nav class="nav-links">
with:
<a class="logo" href="${homeHref}" aria-label="Orcha – Startseite">
<img src="${logoSrc}" alt="Orcha" height="22" style="display:block;height:22px;width:auto;">
</a>
<button class="nav-toggle" type="button" aria-label="Menü öffnen" aria-expanded="false" aria-controls="nav-drawer">
<span></span><span></span><span></span>
</button>
<div class="nav-drawer" id="nav-drawer">
<nav class="nav-links">
Then close the .nav-drawer div after .nav-cta. The template currently ends (lines 113-122):
<div class="nav-cta">
<div class="lang-switch" role="group" aria-label="Sprache / Language">
<a href="${deHref}" lang="de" hreflang="de" class="current" aria-current="true">DE</a>
<a href="${enHref}" lang="en" hreflang="en">EN</a>
</div>
<a class="btn btn-primary" href="/v3/de/trial/">Trial starten</a>
</div>
</div>
</div>
`;
Replace with:
<div class="nav-cta">
<div class="lang-switch" role="group" aria-label="Sprache / Language">
<a href="${deHref}" lang="de" hreflang="de" class="current" aria-current="true">DE</a>
<a href="${enHref}" lang="en" hreflang="en">EN</a>
</div>
<a class="btn btn-primary" href="/v3/de/trial/">Trial starten</a>
</div>
</div><!-- /.nav-drawer -->
</div>
</div>
`;
Note: the .nav-toggle button sits between .logo and .nav-drawer in source order; CSS handles visual placement (display:none on desktop, display:flex ≤960px). With .nav-drawer { display:contents } on desktop, the flex children of .nav-inner remain .logo, .nav-links, .nav-cta (toggle is display:none) — identical desktop layout.
Also in renderHeader, add a data-no-close attribute to the "Produkt" dropdown trigger so tapping that label inside the open mobile drawer does NOT close the drawer (it has no href and on mobile is just a section heading above the flattened module links). Find the line <a tabindex="0" role="button" aria-haspopup="true" class="nav-dd-trigger ${productActive.trim()}" style="cursor: default;">Produkt</a> and add data-no-close before the closing > of the opening tag.
wireNav functionIn www/v3/js/chrome.de.js, immediately before the // Expose + auto-mount comment (currently line 195), insert:
function wireNav(root) {
const nav = root.querySelector(".nav");
const toggle = root.querySelector(".nav-toggle");
if (!nav || !toggle) return;
const close = () => {
nav.classList.remove("is-open");
toggle.setAttribute("aria-expanded", "false");
toggle.setAttribute("aria-label", "Menü öffnen");
document.body.style.overflow = "";
};
const open = () => {
nav.classList.add("is-open");
toggle.setAttribute("aria-expanded", "true");
toggle.setAttribute("aria-label", "Menü schließen");
document.body.style.overflow = "hidden";
};
toggle.addEventListener("click", () => {
nav.classList.contains("is-open") ? close() : open();
});
root.querySelectorAll(".nav-drawer a:not([data-no-close])").forEach((a) =>
a.addEventListener("click", close)
);
window.addEventListener("keydown", (e) => {
if (e.key === "Escape") close();
});
window.addEventListener("resize", () => {
if (window.innerWidth > 960) close();
});
}
wireNav after the header rendersIn www/v3/js/chrome.de.js, the mount block (lines 198-205) is:
document.addEventListener("DOMContentLoaded", () => {
const h = document.getElementById("site-header");
const f = document.getElementById("site-footer");
const x = document.getElementById("modules-cross");
if (h) renderHeader(h);
if (f) renderFooter(f);
if (x) renderCrossLinks(x, currentSlug());
});
Replace the if (h) renderHeader(h); line with:
if (h) { renderHeader(h); wireNav(h); }
Reload http://127.0.0.1:8123/v3/de/ in a browser at a narrow width (or run the harness and inspect shots/home-375.png). Expected: a hamburger button is visible at ≤960px; clicking it opens a drawer with Home / Produkt (with the 8 module links shown inline) / KI-Agenten / ROI / Implementierung / Preise / Steuerberater, plus the DE/EN switch and the Trial button stacked. Clicking any link closes the drawer. At ≥961px the header is unchanged. Run:
cd /Users/maximilianbrandstaetter/Orcha/.claude/worktrees/website-v3-mobile-responsive/www/v3/dev && node screenshot.mjs
Expected: no new overflow introduced (still fails on unfixed sections).
git add www/v3/js/chrome.de.js
git commit -m "feat(v3): add mobile hamburger nav with drawer toggle"
Resolve Prerequisites #1 before this task — it is the first task to stage
index.html.
Files:
Modify: www/v3/de/index.html:1445 and :1498 (footer markup)
Modify: www/v3/css/responsive.css (append)
Step 1: Swap the footer grid container to a class
In www/v3/de/index.html, replace:
<div style="display:grid;grid-template-columns:1.4fr 1fr 1fr 1fr 1fr;gap:32px;border-top:1px solid color-mix(in oklab,var(--bg),transparent 78%);padding-top:40px;">
with:
<div class="home-footer-grid">
In www/v3/de/index.html, replace:
<div style="margin-top:40px;padding-top:24px;border-top:1px solid color-mix(in oklab,var(--bg),transparent 78%);display:flex;justify-content:space-between;font-size:12px;color:color-mix(in oklab,var(--bg),transparent 25%);">
with:
<div class="home-footer-bottom">
responsive.css
/* ───── Homepage footer ───── */
.home-footer-grid {
display: grid;
grid-template-columns: 1.4fr 1fr 1fr 1fr 1fr;
gap: 32px;
border-top: 1px solid color-mix(in oklab, var(--bg), transparent 78%);
padding-top: 40px;
}
.home-footer-bottom {
margin-top: 40px;
padding-top: 24px;
border-top: 1px solid color-mix(in oklab, var(--bg), transparent 78%);
display: flex;
justify-content: space-between;
gap: 16px;
font-size: 12px;
color: color-mix(in oklab, var(--bg), transparent 25%);
}
@media (max-width: 768px) {
.home-footer-grid { grid-template-columns: 1fr 1fr; gap: 28px 24px; }
}
@media (max-width: 480px) {
.home-footer-grid { grid-template-columns: 1fr; gap: 24px; }
.home-footer-bottom { flex-direction: column; gap: 8px; }
}
Run the harness; open shots/home-375.png and shots/home-768.png. Expected: footer columns are 1-up at 375px and 2-up at 768px (was a crushed 5-up); the bottom copyright bar stacks vertically at 375px. Desktop footer (shots/home-1280.png) unchanged — still 5 columns.
git add www/v3/de/index.html www/v3/css/responsive.css
git commit -m "feat(v3): make homepage footer responsive"
Files:
Modify: www/v3/css/responsive.css (append)
Step 1: Append hero rules to responsive.css
/* ───── Hero & pipeline ───── */
@media (max-width: 480px) {
.hero-ctas {
flex-direction: column;
align-items: stretch;
width: 100%;
}
.hero-ctas .btn { justify-content: center; }
.pipeline-stage-head { padding: 10px 8px; font-size: 9px; }
}
Run the harness; open shots/home-320.png. Expected: the two hero buttons ("Trial starten", "Demo buchen") are stacked full-width instead of side-by-side; the 3-lane pipeline header labels still fit. Hero at 768px+ unchanged.
git add www/v3/css/responsive.css
git commit -m "feat(v3): stack hero CTAs on narrow screens"
Files:
Modify: www/v3/de/index.html — in-body <style> at :1209 (.rings-canvas) and :1325-1329 (old media query); node style= attrs at :666, 672, 678, 686, 692, 700, 706, 712, 718, 724.
Step 1: Make .rings-canvas scale fluidly
In www/v3/de/index.html, replace:
.rings-canvas {
position: relative;
width: 600px;
height: 600px;
margin: 0 auto;
}
with:
.rings-canvas {
position: relative;
width: min(600px, 92vw);
aspect-ratio: 1 / 1;
margin: 0 auto;
}
scale(0.6) hack with tile-shrink breakpointsIn www/v3/de/index.html, replace:
/* Narrow viewports – scale the fixed-size canvas down to fit */
@media (max-width: 700px) {
.rings-diagram-wrap { overflow: hidden; height: 372px; }
.rings-canvas { transform: scale(0.6); transform-origin: top center; }
}
with:
/* Narrow viewports – the canvas scales fluidly via min(600px, 92vw);
shrink the node tiles + hub so they don't overlap at small sizes. */
@media (max-width: 768px) {
.rings-node-tile { min-width: 58px; padding: 6px 8px; }
.rings-node-name { font-size: 9px; }
.rings-hub { width: 84px; height: 84px; }
}
@media (max-width: 480px) {
.rings-node-tile { min-width: 42px; padding: 4px 5px; gap: 2px; }
.rings-node-glyph { width: 16px; height: 16px; }
.rings-node-name { font-size: 7.5px; }
.rings-hub { width: 60px; height: 60px; }
.rings-hub-name { font-size: 11px; }
.rings-hub-logo { width: 16px; height: 16px; }
.rings-hub-sub { display: none; } /* "Orchestration" sublabel too small to read in the 60px hub */
}
The nodes are positioned on a 600-unit canvas; % = px ÷ 6. In www/v3/de/index.html, make these 10 replacements (each style= string is unique):
| Replace | With |
|---|---|
style="left:300px;top:430px;" |
style="left:50%;top:71.67%;" |
style="left:413px;top:235px;" |
style="left:68.83%;top:39.17%;" |
style="left:187px;top:235px;" |
style="left:31.17%;top:39.17%;" |
style="left:502px;top:336px;" |
style="left:83.67%;top:56%;" |
style="left:98px;top:336px;" |
style="left:16.33%;top:56%;" |
style="left:503px;top:130px;" |
style="left:83.83%;top:21.67%;" |
style="left:540px;top:412px;" |
style="left:90%;top:68.67%;" |
style="left:300px;top:565px;" |
style="left:50%;top:94.17%;" |
style="left:60px;top:412px;" |
style="left:10%;top:68.67%;" |
style="left:97px;top:130px;" |
style="left:16.17%;top:21.67%;" |
Run the harness; open shots/home-375.png and shots/home-320.png. Expected: the integration-orbit diagram fits within the viewport with no clipping, all 11 satellite nodes (SAP, NetSuite, DATEV, Commerzbank, Deutsche Bank, DocuWare, Teams, Slack, Power BI, SharePoint) + the Orcha hub visible and roughly evenly placed around the rings, not overlapping. Desktop (home-1280.png) unchanged. If two nodes visibly touch at 320px, reduce .rings-node-tile { min-width } in the @media (max-width: 480px) block by ~4px and re-run.
git add www/v3/de/index.html
git commit -m "feat(v3): make integration-orbit diagram scale fluidly on mobile"
Files:
Modify: www/v3/de/index.html:878
Modify: www/v3/css/responsive.css (append)
Step 1: Swap the carousel grid to a class
In www/v3/de/index.html, replace:
<div class="testimonial-carousel grid" data-interval="6000" style="grid-template-columns:1.1fr 0.9fr;gap:80px;align-items:start;">
with:
<div class="testimonial-carousel grid case-grid" data-interval="6000">
#case rules to responsive.css
/* ───── #case — testimonial + metrics split ───── */
.case-grid {
grid-template-columns: 1.1fr 0.9fr;
gap: 80px;
align-items: start;
}
@media (max-width: 1024px) {
.case-grid { gap: 48px; }
}
@media (max-width: 768px) {
.case-grid { grid-template-columns: 1fr; gap: 36px; }
}
Run the harness; open shots/home-768.png and shots/home-375.png. Expected: the testimonial quote and the metrics box are stacked (quote above metrics), each full-width and legible. Desktop unchanged — two columns.
git add www/v3/de/index.html www/v3/css/responsive.css
git commit -m "feat(v3): make case testimonial section responsive"
Files:
Modify: www/v3/de/index.html:1119 (split grid) and :1156-1180 (cert grid + 6 cells)
Modify: www/v3/css/responsive.css (append)
Step 1: Swap the security split grid to a class
In www/v3/de/index.html, replace:
<div class="grid" style="grid-template-columns:1fr 1fr;gap:80px;align-items:start;">
with:
<div class="grid security-split">
In www/v3/de/index.html, replace:
<div class="grid" style="grid-template-columns:repeat(3,1fr);gap:0;border:1px solid var(--line);border-radius:10px;overflow:hidden;background:var(--bg);">
with:
<div class="security-certs">
The cert grid has 6 cell <div>s with inline borders. They will be replaced by a single .security-cert class; borders are handled by the 1px grid gap (Step 4). Make these edits in www/v3/de/index.html:
Replace all occurrences (2 of them — cells 1 and 2) of:
<div style="padding:28px;border-right:1px solid var(--line);border-bottom:1px solid var(--line);min-height:140px;display:flex;flex-direction:column;justify-content:space-between;">
with:
<div class="security-cert">
Replace all occurrences (2 of them — cells 4 and 5) of:
<div style="padding:28px;border-right:1px solid var(--line);min-height:140px;display:flex;flex-direction:column;justify-content:space-between;">
with:
<div class="security-cert">
Replace the single occurrence (cell 3) of:
<div style="padding:28px;border-bottom:1px solid var(--line);min-height:140px;display:flex;flex-direction:column;justify-content:space-between;">
with:
<div class="security-cert">
Replace the single occurrence (cell 6) of:
<div style="padding:28px;min-height:140px;display:flex;flex-direction:column;justify-content:space-between;">
with:
<div class="security-cert">
#security rules to responsive.cssThe cert grid uses the "1px gap as borders" technique so borders are correct at any column count.
/* ───── #security ───── */
.security-split {
grid-template-columns: 1fr 1fr;
gap: 80px;
align-items: start;
}
.security-certs {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1px;
background: var(--line);
border: 1px solid var(--line);
border-radius: 10px;
overflow: hidden;
}
.security-cert {
padding: 28px;
min-height: 140px;
display: flex;
flex-direction: column;
justify-content: space-between;
background: var(--bg);
}
@media (max-width: 1024px) {
.security-split { gap: 48px; }
}
@media (max-width: 768px) {
.security-split { grid-template-columns: 1fr; gap: 40px; }
.security-certs { grid-template-columns: repeat(2, 1fr); }
.security-cert { padding: 22px; min-height: 120px; }
}
Run the harness; open shots/home-768.png and shots/home-375.png. Expected: the "Gebaut für die Prüfung" text block and the cert grid are stacked single-column; the 6 cert tiles (SOC 2, ISO 27001, HIPAA, GDPR, PCI DSS, SOX) are a clean 2-column grid with consistent 1px borders (no doubled or missing borders). Desktop (home-1280.png): split is 2-column, certs 3-column — unchanged from before.
git add www/v3/de/index.html www/v3/css/responsive.css
git commit -m "feat(v3): make security section responsive"
Files:
Modify: www/v3/de/index.html:1367 (header) and :1376 (factors grid)
Modify: www/v3/css/responsive.css (append)
Step 1: Swap the pricing header to a class
In www/v3/de/index.html, replace:
<div style="display:flex;align-items:flex-end;justify-content:space-between;gap:40px;margin-bottom:56px;">
with:
<div class="pricing-header">
In www/v3/de/index.html, replace:
<div class="grid" style="grid-template-columns:repeat(3,1fr);gap:16px;">
with:
<div class="grid pricing-factors">
#pricing rules to responsive.css
/* ───── #pricing ───── */
.pricing-header {
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 40px;
margin-bottom: 56px;
}
.pricing-factors {
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
@media (max-width: 768px) {
.pricing-header {
flex-direction: column;
align-items: flex-start;
gap: 20px;
margin-bottom: 40px;
}
.pricing-factors { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
.pricing-factors { grid-template-columns: 1fr; }
}
Run the harness; open shots/home-768.png and shots/home-375.png. Expected: the pricing headline and its intro paragraph stack vertically; the 6 factor cards are 2-up at 768px and 1-up at 375px (was a crushed 3-up). Desktop unchanged.
git add www/v3/de/index.html www/v3/css/responsive.css
git commit -m "feat(v3): make pricing section responsive"
Files:
Modify: www/v3/de/index.html — #north-star in-body <style> (before :321); stray closing divs at :867-869
Step 1: Add a phone breakpoint to the #north-star style block
In www/v3/de/index.html, the #north-star <style> block ends with the @media (max-width: 780px) rule then </style>. Replace:
.ns-fan-dests { height: auto; padding: 0; gap: 10px; }
}
</style>
with:
.ns-fan-dests { height: auto; padding: 0; gap: 10px; }
}
@media (max-width: 480px) {
.ns-bignum { font-size: 60px; }
.ns-card { padding: 24px 22px 20px; }
.ns-card-claim { font-size: 21px; }
.ns-card--wide .ns-card-claim { font-size: 23px; }
.ns-cal-row { gap: 6px; }
.ns-cal-dot { width: 12px; height: 12px; }
}
</style>
</div>s in the agents sectionThe #agents section has two unbalanced closing </div> tags. In www/v3/de/index.html, replace:
<!-- ============================================== -->
</div>
</div>
</div>
</section>
with:
<!-- ============================================== -->
</div>
</section>
(This keeps the single </div> that closes .wrap plus </section>, and drops the two strays.)
Run the harness; open shots/home-375.png. Expected: #north-star cards render tighter on phone (smaller big-number, tighter calendar dots), nothing clipped. Confirm the page structure after #agents is intact — #case still starts immediately after and renders normally (the removed </div>s were extra; removing them must not shift later sections). Visually compare #case/#support at home-375.png to confirm no layout shift.
git add www/v3/de/index.html
git commit -m "fix(v3): north-star phone tweaks + remove stray agents closing divs"
Files: none (verification only)
Ensure the server is running, then:
cd /Users/maximilianbrandstaetter/Orcha/.claude/worktrees/website-v3-mobile-responsive/www/v3/dev && node screenshot.mjs
Expected: exit code 0, every row ok, no horizontal overflow at any width.
Open all five www/v3/dev/shots/home-*.png and confirm:
320 / 375 px: no horizontal scroll; hamburger nav present; hero CTAs stacked; orbit diagram fits with all nodes visible; #case, #security, #pricing sections single-column and legible; footer stacked; no crushed grids or overlapping text.
768 px: footer 2-col, certs 2-col, pricing factors 2-col; nav still hamburger.
1024 px: layout transitional, no overflow.
1280 px: visually identical to the original desktop design — compare against the Task 1 baseline shots/ (regenerate the baseline first from git stash of the working tree if a precise diff is needed, or eyeball against the live committed design).
Step 3: Manual browser pass
In a real browser at http://127.0.0.1:8123/v3/de/, resize from wide → narrow and back. Confirm: the hamburger opens/closes, Escape closes it, clicking a link closes it, resizing above 960px closes it, body scroll locks while open.
If review finds problems, fix them in the relevant file (responsive.css for shared rules, index.html in-body styles for orbit/north-star), re-run the harness, and commit:
git add -A
git commit -m "fix(v3): responsive review adjustments"
If no issues, no commit needed — the work is already committed task-by-task.
Checked against docs/superpowers/specs/2026-05-14-homepage-mobile-responsive-design.md:
product.css's existing @media (max-width: 960px) and avoid a dead zone. ✔ covered, with rationale..wrap, section, nav, footer (spec §2): The spec assumed these go in v3.css. Implementation reality (Prerequisites §3): v3.css is overridden by product.css, and the homepage footer is bespoke inline markup (not the chrome.de.js .site-footer). Resolution: new responsive.css linked last (Tasks 2, 3, 5). Nav drawer = Tasks 3–4. ✔ covered; "carries over to other v3 pages automatically" from the spec is downgraded to "responsive.css is reusable but each page must link it" — a later-pass item, consistent with the spec's scope boundary §5.de/index.html + v3.css-adjacent shared CSS + chrome.de.js. chrome.de.js changes do reach other pages (shared header) — the hamburger will also work on subpages, which is a strict improvement and within "shared CSS/JS" scope. EN homepage + other pages' section-specific styles untouched. ✔ covered.Placeholder scan: none. Type/name consistency: .nav-drawer, .nav-toggle, wireNav, home-footer-grid, home-footer-bottom, case-grid, security-split, security-certs, security-cert, pricing-header, pricing-factors — each defined in responsive.css and referenced in the matching markup task. ✔