Homepage Mobile Responsiveness Implementation Plan

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.


Prerequisites — read before Task 1

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).


File Structure

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.

Task 1: Verification harness

Files:

{
  "name": "orcha-v3-dev",
  "private": true,
  "type": "module",
  "devDependencies": {
    "playwright": "^1.48.0"
  }
}
node_modules/
shots/
// 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"

Task 2: Create responsive.css + global padding

Files:

/* ═══════════════════════════════════════════════════════════════
   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; }
}

In 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"

Task 3: Mobile nav — CSS

Files:

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"

Task 4: Mobile nav — markup + toggle JS

Files:

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.

In 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();
    });
  }

In 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:

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">

/* ───── 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"

Task 6: Hero CTA stacking

Files:


/* ───── 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"

Task 7: #integration-orbit responsive

Files:

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;
  }

In 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:

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 — 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"

Task 9: #security responsive

Files:

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">

The 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"

Task 10: #pricing responsive

Files:

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 ───── */
.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"

Task 11: #north-star phone tweaks + agents markup fix

Files:

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>

The #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"

Task 12: Full-page verification + review

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:

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.


Self-Review Notes

Checked against docs/superpowers/specs/2026-05-14-homepage-mobile-responsive-design.md:

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. ✔