Website 3.0 Draft 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: Port the Website 3.0 design from ~/Downloads/Website 3.0/ into www/v3/de/ as static HTML with vanilla JS animations, isolated from production via noindex + robots.txt. German first; English follows in a separate plan.

Architecture: New www/v3/ subfolder on master. Single global CSS file (v3.css) extracted from the design's <style> block. Per-section JS files for animations (orchestration cycling, swimlane packets, nav dropdown) following the existing www/js/orb.js IIFE pattern. JSX components are converted to their rendered HTML and inlined into de/index.html in the composition order from app.jsx (Nav → Hero → ModulesGrid → Workflow → Orchestration → OrchestrationB → CaseStudy → RoiCalculator → Integrations → Security → Pricing → CtaFooter). Mode toggle, tweaks panel, and edit-mode protocol are dropped.

Tech Stack: HTML, CSS, vanilla JS. Geist + Geist Mono via Google Fonts. No bundler, no build step. Local preview via python -m http.server from www/.

Verification model: Static HTML doesn't have a unit test framework. Each task verifies via:

  1. curl -sI for HTTP 200
  2. grep for required markers (e.g., noindex, data-section="hero")
  3. Manual visual check at the end of each task — open the page in the browser and compare against the design original side-by-side

Task 1: Scaffold the v3 directory and isolation

Files:

mkdir -p www/v3/de/produkt www/v3/css www/v3/js
touch www/v3/de/produkt/.gitkeep www/v3/js/.gitkeep
User-agent: *
Disallow: /
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="robots" content="noindex, nofollow" />
<title>Orcha — Autonome Finanzoperationen</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Geist:wght@300;400;500;600;700&family=Geist+Mono:wght@400;500;600&display=swap">
<link rel="stylesheet" href="../css/v3.css">
</head>
<body data-mode="editorial">
  <!-- Sections inserted in subsequent tasks -->
</body>
</html>
/* Website 3.0 draft styles — populated in Task 2 */
cd /Users/maximilianbrandstaetter/Orcha/www && python3 -m http.server 8765 &

(Keep running for the whole plan. Stop with lsof -ti:8765 | xargs kill at the end.)

curl -s http://localhost:8765/v3/de/index.html | grep -c 'noindex'

Expected: 1

curl -s http://localhost:8765/v3/robots.txt

Expected: contains Disallow: /

git add www/v3
git commit -m "feat(v3): scaffold www/v3/ draft with noindex + robots block"

Task 2: Extract the design's CSS into v3.css

Files:

The original design has a single large <style> block in index.html (lines 10–625 of ~/Downloads/Website 3.0/index.html). Move it into v3.css verbatim. Keep the :root tokens, mode override (body[data-mode="systems"]), and prefers-reduced-motion block. Drop the tweaks panel CSS (.tweaks, .tweak-row, .tweak-btns, .swatches) since the panel is dropped.

sed -n '10,625p' "/Users/maximilianbrandstaetter/Downloads/Website 3.0/index.html"

Use the Read tool on the original file then Write to www/v3/css/v3.css. Drop only these blocks:

Keep everything else — including the editorial/systems mode tokens, even though we default to editorial. Future translation pass may want the systems variant available.

curl -sI http://localhost:8765/v3/css/v3.css | grep -i 'content-type'

Expected: text/css

curl -s http://localhost:8765/v3/css/v3.css | grep -c '^:root'

Expected: 1 (or 2 if the body[data-mode="systems"] block also matches the regex anchor — either way > 0)

git add www/v3/css/v3.css
git commit -m "feat(v3): port design tokens and global styles to v3.css"

Task 3: Port the navigation + dropdown menu

Files:

Source: ~/Downloads/Website 3.0/components/app.jsx lines 11–76 (the Nav component). The dropdown uses useState + mouseenter/leave timers; we replicate with vanilla JS. Copy is left in English in this task; German translation happens in Task 14.

After <body data-mode="editorial">, insert:

<div class="nav">
  <div class="wrap nav-inner">
    <a class="logo" href="#">
      <span class="logo-mark"></span>
      Orcha
    </a>
    <nav class="nav-links">
      <div class="nav-dropdown" data-nav-dropdown>
        <button class="nav-dropdown-trigger" data-nav-trigger aria-expanded="false">
          Product
          <svg width="10" height="10" viewBox="0 0 10 10" data-nav-chevron style="margin-left: 4px; transition: transform .18s ease;">
            <path d="M2 3.5 L5 6.5 L8 3.5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
          </svg>
        </button>
        <div class="nav-dropdown-panel" data-nav-panel hidden>
          <div class="nav-dropdown-header">
            <span class="mono" style="font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted);">Modules</span>
            <span style="font-size: 12px; color: var(--ink-2);">Choose independently · or run the full suite</span>
          </div>
          <div class="nav-dropdown-grid">
            <a href="produkt/kreditoren.html" class="nav-dropdown-item">
              <span class="nav-dropdown-item-title">Accounts Payable</span>
              <span class="nav-dropdown-item-hint">AP automation · 95% straight-through</span>
            </a>
            <a href="produkt/debitoren.html" class="nav-dropdown-item">
              <span class="nav-dropdown-item-title">Accounts Receivable</span>
              <span class="nav-dropdown-item-hint">Billing, dunning, bank match</span>
            </a>
            <a href="produkt/dokumente.html" class="nav-dropdown-item">
              <span class="nav-dropdown-item-title">Document Management</span>
              <span class="nav-dropdown-item-hint">Classify, extract, archive</span>
            </a>
            <a href="produkt/freigaben.html" class="nav-dropdown-item">
              <span class="nav-dropdown-item-title">Approval Workflows</span>
              <span class="nav-dropdown-item-hint">Multi-channel, budget-aware</span>
            </a>
            <a href="produkt/fpa.html" class="nav-dropdown-item">
              <span class="nav-dropdown-item-title">Real-Time FP&amp;A</span>
              <span class="nav-dropdown-item-hint">Excel, Power BI, AI assistants</span>
            </a>
          </div>
          <a href="produkt/index.html" class="nav-dropdown-footer">
            Platform overview
            <span aria-hidden="true">→</span>
          </a>
        </div>
      </div>
      <a href="#agents">Agents</a>
      <a href="#workflow">How it works</a>
      <a href="#orchestration">Stack</a>
      <a href="#roi">ROI</a>
      <a href="#integrations">Integrations</a>
      <a href="#security">Security</a>
      <a href="#pricing">Pricing</a>
    </nav>
    <div class="nav-cta">
      <a class="btn btn-ghost" href="#">Sign in</a>
      <a class="btn btn-primary" href="#pricing">Start trial <span aria-hidden="true">→</span></a>
    </div>
  </div>
</div>

<script src="../js/nav-dropdown.js" defer></script>
(function () {
  document.addEventListener('DOMContentLoaded', function () {
    var root = document.querySelector('[data-nav-dropdown]');
    if (!root) return;
    var trigger = root.querySelector('[data-nav-trigger]');
    var panel = root.querySelector('[data-nav-panel]');
    var chevron = root.querySelector('[data-nav-chevron]');
    var closeTimer = null;

    function open() {
      clearTimeout(closeTimer);
      panel.hidden = false;
      trigger.setAttribute('aria-expanded', 'true');
      trigger.classList.add('open');
      chevron.style.transform = 'rotate(180deg)';
    }

    function close() {
      panel.hidden = true;
      trigger.setAttribute('aria-expanded', 'false');
      trigger.classList.remove('open');
      chevron.style.transform = 'none';
    }

    root.addEventListener('mouseenter', open);
    root.addEventListener('mouseleave', function () {
      closeTimer = setTimeout(close, 120);
    });
    trigger.addEventListener('click', function () {
      panel.hidden ? open() : close();
    });
  });
})();
curl -s http://localhost:8765/v3/de/index.html | grep -c 'nav-dropdown-trigger'

Expected: 1

git add www/v3/de/index.html www/v3/js/nav-dropdown.js
git commit -m "feat(v3): add nav with product dropdown menu"

Task 4: Port the hero section

Files:

Source: ~/Downloads/Website 3.0/components/hero.jsx. Default to variant A (heroVariant: "A" in the original TWEAKS block). Read the file fully before porting — useState for any dynamic chips/badges should be flattened to their initial rendered state.

Use the Read tool on /Users/maximilianbrandstaetter/Downloads/Website 3.0/components/hero.jsx. Identify the variant-A render path. Note any dynamic state (chip rotation, etc.) — replicate the initial rendered output only; if there's a JS-driven cycle, capture timing for a later JS file.

(Engineer: copy the rendered output here — content depends on what the JSX produces. For a typical hero this is <section class="hero"> with eyebrow, h1 with .italic-swap, lede, CTA buttons.)

curl -s http://localhost:8765/v3/de/index.html | grep -c 'h-display'

Expected: >= 1

git add www/v3/de/index.html www/v3/js/hero.js 2>/dev/null
git commit -m "feat(v3): add hero section (variant A)"

Task 5: Port the agents / modules grid section

Files:

Source: ~/Downloads/Website 3.0/components/agents.jsx (the component is exported as ModulesGrid per app.jsx line 235).

Use the Read tool on /Users/maximilianbrandstaetter/Downloads/Website 3.0/components/agents.jsx. Note any JS interactivity.

curl -s http://localhost:8765/v3/de/index.html | grep -c 'id="agents"'

Expected: 1

git add www/v3/de/index.html www/v3/js/agents.js 2>/dev/null
git commit -m "feat(v3): add agents/modules grid section"

Task 6: Port the workflow section

Files:

Source: ~/Downloads/Website 3.0/components/workflow.jsx. Component is Workflow per app.jsx line 236.

Use the Read tool. Identify any animation (step progression, line drawing).

curl -s http://localhost:8765/v3/de/index.html | grep -c 'id="workflow"'

Expected: 1

git add www/v3/de/index.html www/v3/js/workflow.js 2>/dev/null
git commit -m "feat(v3): add workflow section"

Task 7: Port orchestration A (hub-and-spoke + timeline)

Files:

Source: ~/Downloads/Website 3.0/components/orchestration.jsx. The CSS for this section is already in v3.css (.orch-grid, .orch-node, .orch-line, etc.). The animation cycles through nodes by toggling .active classes on .orch-node elements and .orch-line-active on SVG lines.

Use the Read tool on /Users/maximilianbrandstaetter/Downloads/Website 3.0/components/orchestration.jsx. Capture: (a) static structure of the three-column grid + central hub + SVG lines, (b) the timeline events list, (c) the useEffect interval that drives .active cycling — record interval ms, sequence order.

Structure (fill in the actual node names, labels, timeline events from the JSX):

<section id="orchestration">
  <div class="wrap">
    <!-- Section header (eyebrow + h-section + lede) -->
    <!-- .orch-grid with three .orch-col + .orch-center containing .orch-hub + SVG lines -->
    <!-- .orch-timeline with .orch-event rows -->
  </div>
</section>

Use the actual content from the JSX render output.

Pattern:

(function () {
  document.addEventListener('DOMContentLoaded', function () {
    var section = document.getElementById('orchestration');
    if (!section) return;
    var inNodes = section.querySelectorAll('.orch-col-in .orch-node');
    var outNodes = section.querySelectorAll('.orch-col-out .orch-node');
    var lines = section.querySelectorAll('.orch-line');
    if (!inNodes.length) return;

    var step = 0;
    function tick() {
      inNodes.forEach(function (n) { n.classList.remove('active'); });
      outNodes.forEach(function (n) { n.classList.remove('active'); });
      lines.forEach(function (l) { l.classList.remove('orch-line-active'); });

      // Activate current step's input + output + line
      var inN = inNodes[step % inNodes.length];
      var outN = outNodes[step % outNodes.length];
      if (inN) inN.classList.add('active');
      if (outN) outN.classList.add('active');
      // Match line indexing to nodes (verify in source — lines may need a different mapping)
      var line = lines[step % lines.length];
      if (line) line.classList.add('orch-line-active');

      step++;
    }

    if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
    tick();
    setInterval(tick, 1800);  // Adjust to match source timing
  });
})();

Add <script src="../js/orchestration.js" defer></script> before </body> (alongside nav-dropdown.js).

Important: the exact tick interval and node→line mapping must come from the source useEffect. If the source uses a more complex mapping, port that exactly.

curl -s http://localhost:8765/v3/de/index.html | grep -c 'orch-grid'

Expected: >= 1

git add www/v3/de/index.html www/v3/js/orchestration.js
git commit -m "feat(v3): add orchestration A section with node cycling"

Task 8: Port orchestration B (swimlanes)

Files:

Source: ~/Downloads/Website 3.0/components/orchestration-b.jsx. CSS is already in v3.css (.swim-board, .swim-lane, .swim-packet, etc.). Packets animate left-to-right along tracks; some land in the warn-coloured human-escalation row.

Use the Read tool on /Users/maximilianbrandstaetter/Downloads/Website 3.0/components/orchestration-b.jsx. Capture: (a) the lane structure (human row + N agent rows), (b) packet definitions (origin lane, target lane, status, content), (c) animation timing (spawn cadence, transit duration).

Pattern (timing/sequence comes from source):

(function () {
  document.addEventListener('DOMContentLoaded', function () {
    var board = document.querySelector('.swim-board');
    if (!board) return;
    if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;

    var lanes = board.querySelectorAll('.swim-lane');
    var packetTpl = /* source-defined templates */;

    function spawnPacket(targetLane, kind, content) {
      var track = targetLane.querySelector('.swim-track');
      var packet = document.createElement('div');
      packet.className = 'swim-packet swim-packet-' + kind;
      packet.innerHTML = content;
      packet.style.position = 'absolute';
      packet.style.left = '0';
      packet.style.top = '50%';
      packet.style.transform = 'translate(-100%, -50%)';
      track.appendChild(packet);
      // Animate via requestAnimationFrame or CSS transition
      requestAnimationFrame(function () {
        packet.style.transition = 'transform 2.4s linear';
        packet.style.transform = 'translate(calc(' + track.offsetWidth + 'px), -50%)';
      });
      setTimeout(function () { packet.remove(); }, 2600);
    }

    // Schedule packet sequence using the data from the source
    var queue = [/* packet sequence from JSX */];
    var i = 0;
    setInterval(function () {
      var p = queue[i % queue.length];
      var lane = lanes[p.laneIndex];
      if (lane) spawnPacket(lane, p.kind, p.content);
      i++;
    }, 1400);  // Adjust to match source
  });
})();

Add <script src="../js/swimlanes.js" defer></script> before </body>.

curl -s http://localhost:8765/v3/de/index.html | grep -c 'swim-board'

Expected: >= 1

git add www/v3/de/index.html www/v3/js/swimlanes.js
git commit -m "feat(v3): add orchestration B (swimlanes) with packet animation"

Task 9: Port the rest of the home page (case study, ROI, integrations, security, pricing, CTA)

Files:

Source: ~/Downloads/Website 3.0/components/rest.jsx and ~/Downloads/Website 3.0/components/roi.jsx. Per app.jsx lines 239–244, the order is: CaseStudy, RoiCalculator, Integrations, Security, Pricing, CtaFooter.

Use the Read tool on rest.jsx and roi.jsx. Identify the boundaries between sections. The RoiCalculator may have interactivity (sliders that update KPI numbers).

(function () {
  document.addEventListener('DOMContentLoaded', function () {
    var section = document.getElementById('roi');
    if (!section) return;
    var inputs = section.querySelectorAll('input[type="range"], input[type="number"]');
    var outputs = section.querySelectorAll('[data-roi-output]');
    function recalc() {
      // Read inputs, apply formula from source, write to outputs
    }
    inputs.forEach(function (i) { i.addEventListener('input', recalc); });
    recalc();
  });
})();

Use the exact formula from the source.

for id in roi integrations security pricing; do
  curl -s http://localhost:8765/v3/de/index.html | grep -c "id=\"$id\"" || echo "missing: $id"
done

Expected: each prints 1.

git add www/v3/de/index.html www/v3/js/roi.js 2>/dev/null
git commit -m "feat(v3): add case study, ROI, integrations, security, pricing, CTA"

Task 10: Home-page review checkpoint (English)

Files: none

Open http://localhost:8765/v3/de/index.html and the design original side-by-side. Walk through every section. Check:

If any section is visibly off, fix in place and amend the relevant task's commit. If a fix is large, create a new follow-up commit fix(v3): [section] visual delta.

Tell the user the home is ready for visual review. Wait for sign-off (or fix list) before proceeding to product pages.


Task 11: Port the product overview page

Files:

Sources: ~/Downloads/Website 3.0/product/overview.html, ~/Downloads/Website 3.0/product/product.css, ~/Downloads/Website 3.0/product/chrome.js.

curl -sI http://localhost:8765/v3/de/produkt/index.html | head -1
curl -s http://localhost:8765/v3/de/produkt/index.html | grep -c 'noindex'

Expected: HTTP/1.0 200 OK and 1.

git add www/v3/de/produkt/index.html www/v3/css/product.css www/v3/js/chrome.js
git commit -m "feat(v3): port product overview page"

Task 12: Port the five product subpages

Files:

Each subpage gets the same head adjustments as Task 11. URL slugs match existing www/de/produkt/ conventions (Kreditoren / Debitoren / Freigaben / Dokumente / FP&A).

Read ~/Downloads/Website 3.0/product/accounts-payable.html. Write to www/v3/de/produkt/kreditoren.html with:

Verify:

curl -sI http://localhost:8765/v3/de/produkt/kreditoren.html | head -1

Expected: 200.

for p in kreditoren debitoren freigaben dokumente fpa; do
  status=$(curl -sI http://localhost:8765/v3/de/produkt/$p.html | head -1)
  noindex=$(curl -s http://localhost:8765/v3/de/produkt/$p.html | grep -c 'noindex')
  echo "$p: $status — noindex=$noindex"
done

Expected: each line shows 200 OK and noindex=1.

git add www/v3/de/produkt/
git commit -m "feat(v3): port 5 product subpages (Kreditoren/Debitoren/Freigaben/Dokumente/FPA)"

Task 13: English-version review checkpoint

Files: none

# All 7 pages return 200
for p in /v3/de/index.html /v3/de/produkt/index.html /v3/de/produkt/kreditoren.html /v3/de/produkt/debitoren.html /v3/de/produkt/freigaben.html /v3/de/produkt/dokumente.html /v3/de/produkt/fpa.html; do
  status=$(curl -sI "http://localhost:8765$p" | head -1)
  echo "$p$status"
done

# All pages have noindex
for p in /v3/de/index.html /v3/de/produkt/index.html /v3/de/produkt/kreditoren.html /v3/de/produkt/debitoren.html /v3/de/produkt/freigaben.html /v3/de/produkt/dokumente.html /v3/de/produkt/fpa.html; do
  count=$(curl -s "http://localhost:8765$p" | grep -c 'noindex')
  echo "$p — noindex=$count"
done

# robots.txt blocks
curl -s http://localhost:8765/v3/robots.txt

# No links from current site point to /v3/
grep -r '/v3/' www/de/ www/en/ www/sitemap.xml 2>&1 | grep -v 'Binary' || echo "✓ no links from current site to /v3/"

# Production unchanged
git diff master -- www/de www/en www/sitemap.xml

Expected:

Tell the user the English version is feature-complete and ask for visual sign-off before starting German translation. If fixes needed, address inline before proceeding.


Task 14: Translate the home page to German

Files:

Reference the existing www/de/index.html for tone (Sie-form, no Anglicisms where a clean German term exists, Swiss German spelling per user preference).

Spot-check by opening in browser. Run a quick grep for common English-only words:

for word in "How it works" "Sign in" "Start trial" "Approve" "Choose"; do
  count=$(grep -c "$word" www/v3/de/index.html)
  echo "$word: $count"
done

Expected: most show 0. Any non-zero hit needs review (could be intentional like a brand term).

git add www/v3/de/index.html
git commit -m "feat(v3): translate home page to German"

Task 15: Translate product pages to German

Files:

Verify:

grep -c 'How it works\|Sign in' www/v3/de/produkt/index.html

Expected: 0.

for f in www/v3/de/produkt/index.html www/v3/de/produkt/kreditoren.html www/v3/de/produkt/debitoren.html www/v3/de/produkt/freigaben.html www/v3/de/produkt/dokumente.html www/v3/de/produkt/fpa.html; do
  hits=$(grep -E "How it works|Sign in|Start trial|Approve workflow" "$f" | wc -l | tr -d ' ')
  echo "$f: $hits English hits"
done

Expected: each file shows 0.

git add www/v3/de/produkt/
git commit -m "feat(v3): translate 6 product pages to German"

Task 16: Final acceptance criteria run

Files: none

Run all six acceptance criteria from the spec.

for p in /v3/de/index.html /v3/de/produkt/index.html /v3/de/produkt/kreditoren.html /v3/de/produkt/debitoren.html /v3/de/produkt/freigaben.html /v3/de/produkt/dokumente.html /v3/de/produkt/fpa.html; do
  curl -sI "http://localhost:8765$p" | head -1
done

Expected: 7 × 200 OK.

User opens browser DevTools console on /v3/de/index.html, watches for 60 seconds. Expected: no errors, orchestration cycles through nodes, swimlane packets spawn and traverse.

for p in /v3/de/index.html /v3/de/produkt/index.html /v3/de/produkt/kreditoren.html /v3/de/produkt/debitoren.html /v3/de/produkt/freigaben.html /v3/de/produkt/dokumente.html /v3/de/produkt/fpa.html; do
  count=$(curl -s "http://localhost:8765$p" | grep -c 'noindex')
  echo "$p: noindex=$count"
done

Expected: each shows 1.

curl -s http://localhost:8765/v3/robots.txt

Expected:

User-agent: *
Disallow: /
grep -r '/v3/' www/de/ www/en/ www/index.html www/sitemap.xml 2>/dev/null || echo "✓ no leakage"

Expected: ✓ no leakage.

grep -r 'tracker.js' www/v3/ 2>/dev/null && echo "WARN: tracker referenced" || echo "✓ no tracker in v3"

Expected: ✓ no tracker in v3.

git diff master~$(git rev-list master..HEAD --count) -- www/de www/en www/sitemap.xml www/css/globals.css www/js/main.js www/js/orb.js www/js/tracker.js www/js/community-forms.js

Expected: empty diff.

lsof -ti:8765 | xargs kill 2>/dev/null

Report: "Website 3.0 draft is on master at www/v3/de/. Local preview at http://localhost:8765/v3/de/ (run cd www && python3 -m http.server 8765 to restart). All 6 acceptance criteria pass. Ready for your review. Next step is the EN translation, which is a separate plan."