Skip to content

feat(persona-room): Phase 2 room shell — designed self-contained page - #2237

Merged
POWERFULMOVES merged 1 commit into
mainfrom
feat/persona-room-shell
Jul 26, 2026
Merged

POWERFULMOVES merged 1 commit into
mainfrom
feat/persona-room-shell

Conversation

@POWERFULMOVES

@POWERFULMOVES POWERFULMOVES commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Item 5 (living-doc room) — Phase 2: a self-contained, host-agnostic static page rendering the persona (Phase-1 persona.json).

Preview: the rendered room (design + all sections) — https://claude.ai/code/artifact/bee111bb-6cdf-4ca2-8482-d51d90260e22

Design (editorial treatment)

  • Dual-frequency palette — warm amber (beats/soul) + electric cyan (code/signal), the 'same person, different frequency' thesis; theme-aware light + dark, responsive.
  • Orbitron display (the website's identity) inlined as base64 woff2 (11.8KB) — no external font fetch; works on any host + offline + as an Artifact.
  • Waveform/signal hero (canvas, reduced-motion aware) evoking BPM / the Geometry Bus; scroll reveals.
  • Sections: plain-language lead (employer-first per notes2), highlights, skills clusters, featured (filled links + investor/SoundCloud TODOs), PMOVES→employer table, automation fabric, Remotion + PreTeXt 'coming' slots, closer/connect.

Host-agnostic — deployable behind the #2221 Traefik edge (non-CF).

Next

Phase 3 Remotion walkthrough (a2ui renderer) · Phase 4 PreTeXt panels · Phase 5 host cutover to pmoves.ai.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added a complete Persona room landing page with hero, highlights, skills, featured content, translation, media, contact, and footer sections.
    • Added light and dark theme support with a persistent theme toggle.
    • Added animated hero waveform visuals and scroll-based content reveal effects.
    • Added reduced-motion support for a more accessible experience.

Living-doc room (plan 07_...md), Phase 2: a self-contained, host-agnostic static
page rendering the persona (Phase-1 content model). Editorial treatment:
- Dual-frequency palette (warm=beats, cool=code — 'same person, different
  frequency'), theme-aware light+dark, responsive.
- Orbitron display (website design language) inlined as base64 woff2 (11.8KB) —
  no external font fetch; works on any host + offline.
- Waveform/signal hero motif (canvas, reduced-motion aware) evoking BPM/Geometry
  Bus; scroll reveals.
- Sections: plain-language lead (employer-first), highlights, skills clusters,
  featured (filled links + investor/soundcloud TODOs), PMOVES→employer table,
  automation fabric, Remotion + PreTeXt 'coming' slots, closer/connect.

Deployable behind the #2221 Traefik edge (non-CF). Preview rendered + reviewed.
Next: Phase 3 Remotion walkthrough, Phase 4 PreTeXt panels, Phase 5 host cutover.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The persona room landing page is implemented as a self-contained HTML document with responsive themed styling, structured content sections, and client-side theme toggling, scroll reveals, and an animated hero waveform.

Changes

Persona room page

Layer / File(s) Summary
Visual system and page structure
pmoves/rooms/persona/index.html
Inline CSS and body markup define the responsive dark/light-themed layout, hero, content sections, calls to action, media areas, and footer.
Theme, reveal, and waveform interactions
pmoves/rooms/persona/index.html
Client-side behavior toggles data-theme, applies scroll-triggered .in reveals, and renders a responsive dual-frequency canvas waveform with reduced-motion handling.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Visitor
  participant PersonaPage
  participant IntersectionObserver
  participant HeroWaveCanvas
  Visitor->>PersonaPage: Click theme button
  PersonaPage->>PersonaPage: Toggle data-theme
  IntersectionObserver->>PersonaPage: Observe reveal elements
  PersonaPage->>PersonaPage: Apply .in on intersection
  PersonaPage->>HeroWaveCanvas: Resize and animate waveform
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning It describes the feature, but it misses the template's required Summary, Testing, Required Checks, and Review Coordination sections. Add the required Summary and Testing sections, plus the checkbox lists for Required Checks and Review Coordination, following the template.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the self-contained persona room page and its Phase 2 scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/persona-room-shell

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 695309ebf5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


<footer><div class="wrap">
<span>© 2026 Russell Richardson · CATACLYSM STUDIOS INC</span>
<span>Rendered from <code>pmoves/rooms/persona/persona.json</code> · a room on pmoves.ai</span>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Render the page from the canonical persona model

The page claims to be rendered from persona.json, but the inspected script only handles theme switching, reveal effects, and the canvas; every identity, highlight, skill, and link is duplicated as literal HTML. Consequently, updates to the declared single source of truth will leave the published room stale unless every value is manually synchronized. Add a generation/rendering step or load the model at runtime rather than presenting this snapshot as model-backed.

Useful? React with 👍 / 👎.

Comment on lines +122 to +123
.reveal{opacity:0;transform:translateY(14px);transition:opacity .6s ease,transform .6s ease}
.reveal.in{opacity:1;transform:none}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep room content visible before JavaScript enhancement

When JavaScript is disabled, blocked by a host CSP, or fails before the IntersectionObserver setup completes, every section carrying class="reveal" remains permanently transparent; only users with reduced-motion enabled bypass this rule. Because all six substantive sections use that class, affected visitors receive essentially only the hero and footer. Default the sections to visible and apply the hidden state only after JavaScript has initialized.

Useful? React with 👍 / 👎.

Comment on lines +23 to +25
--ground:#f5f4ef; --panel:#ffffff; --panel-2:#f0efe8; --line:#e0ddd2;
--ink:#15161c; --ink-dim:#4b4f5e; --ink-faint:#7c8092;
--warm:#c9761a; --warm-soft:#a75f13; --cool:#0f9c93; --cool-soft:#0b7c74; --focus:#0f9c93;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Raise light-theme contrast for small text

When light theme is selected, several normal-size foreground colors fail the 4.5:1 contrast threshold against the shipped light background: --cool is about 3.08:1, --warm about 3.13:1, and --ink-faint about 3.56:1. These variables are used for 11–14px section numbers, headings, links, table cells, eyebrow text, and footer text, making those elements difficult to read for low-vision users. Use darker light-theme accent and faint-text values while retaining the current decorative palette.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
pmoves/rooms/persona/index.html (2)

1-7: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider Open Graph/social preview tags for this outreach page.

There's no og:title/og:description/og:image here; given this page is meant to be shared for job/collaboration outreach (per PR objectives), link previews on LinkedIn/X/Slack will fall back to generic rendering.

<meta property="og:title" content="Russell Richardson (DARKXSIDE) — Founder, PMOVES.AI">
<meta property="og:description" content="Founder of PMOVES.AI and Applied AI Architect. Open to mission-aligned roles.">
<meta property="og:type" content="profile">
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/rooms/persona/index.html` around lines 1 - 7, Add Open Graph metadata
in the head of the persona page alongside the existing description meta tag:
define og:title, og:description, and og:type with outreach-appropriate values,
and include an og:image referencing the page’s share preview asset if one
exists.

244-266: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Waveform loop recomputes styles every frame and never pauses off-screen/hidden.

css() calls getComputedStyle(root) twice per draw() (Lines 252-253), and the rAF loop (Line 265) runs indefinitely even when the tab is backgrounded. Caching the two colors (recompute only on theme toggle/resize) and pausing via visibilitychange would cut unnecessary work for a purely decorative background animation.

Suggested optimization
+  var warmCol, coolCol;
+  function refreshColors(){ warmCol=css('--warm'); coolCol=css('--cool'); }
   function draw(){
     var w=c.width,h=c.height; ctx.clearRect(0,0,w,h);
-    var waves=[{col:css('--warm'),amp:h*0.10,freq:2.1,ph:t*0.9,y:h*0.52},
-               {col:css('--cool'),amp:h*0.13,freq:1.4,ph:-t*0.7,y:h*0.56}];
+    var waves=[{col:warmCol,amp:h*0.10,freq:2.1,ph:t*0.9,y:h*0.52},
+               {col:coolCol,amp:h*0.13,freq:1.4,ph:-t*0.7,y:h*0.56}];
     ...
   }
-  size(); draw(); window.addEventListener('resize',function(){size();draw();});
-  if(!reduce){ (function loop(){ t+=0.02; draw(); requestAnimationFrame(loop); })(); }
+  refreshColors(); size(); draw(); window.addEventListener('resize',function(){size();draw();});
+  document.addEventListener('visibilitychange',function(){ if(!document.hidden){ refreshColors(); draw(); } });
+  var running=false;
+  if(!reduce){ (function loop(){ if(document.hidden){ running=false; return; } t+=0.02; draw(); requestAnimationFrame(loop); })(); }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/rooms/persona/index.html` around lines 244 - 266, Optimize the
waveform animation around draw(), css(), and the requestAnimationFrame loop by
caching the --warm and --cool colors instead of calling getComputedStyle(root)
on every frame, refreshing the cache on theme changes or resize as appropriate.
Add visibilitychange handling to pause the animation while the document is
hidden and resume it when visible, while preserving reduced-motion behavior and
the existing rendering.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pmoves/rooms/persona/index.html`:
- Around line 122-126: Ensure the main content remains visible when JavaScript
is unavailable or fails: update the reveal styling and IntersectionObserver flow
around the `.reveal` class so its hidden state has a non-JavaScript fallback,
while preserving the animation when the script runs. Apply the fix consistently
to all primary sections using `class="reveal"`.
- Line 2: Remove the hardcoded data-theme value from the html element and update
the theme initialization logic to choose localStorage’s saved theme first, then
the system prefers-color-scheme preference, with the existing dark theme as
fallback. Update the toggle handler to persist each theme change to localStorage
so the selection survives reloads, and remove the now-unreachable CSS guard that
depends on the missing data-theme attribute.
- Line 230: The persona page must either load, render, and validate
pmoves/rooms/persona/persona.json or stop claiming it is rendered from that
file; align the implementation and displayed source accordingly. Also update the
PMOVES roadmap and next-steps documents with this room/persona shipment, current
“_Last updated” timestamps, and the applicable local-check output or an
explicitly documented intentional skip.

---

Nitpick comments:
In `@pmoves/rooms/persona/index.html`:
- Around line 1-7: Add Open Graph metadata in the head of the persona page
alongside the existing description meta tag: define og:title, og:description,
and og:type with outreach-appropriate values, and include an og:image
referencing the page’s share preview asset if one exists.
- Around line 244-266: Optimize the waveform animation around draw(), css(), and
the requestAnimationFrame loop by caching the --warm and --cool colors instead
of calling getComputedStyle(root) on every frame, refreshing the cache on theme
changes or resize as appropriate. Add visibilitychange handling to pause the
animation while the document is hidden and resume it when visible, while
preserving reduced-motion behavior and the existing rendering.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 864a59a8-12cd-4904-86bf-ea6865e9b878

📥 Commits

Reviewing files that changed from the base of the PR and between 3ce59e1 and 695309e.

📒 Files selected for processing (1)
  • pmoves/rooms/persona/index.html

@@ -0,0 +1,269 @@
<!doctype html>
<html lang="en" data-theme="dark">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Prefers-color-scheme light theme is dead code; theme choice isn't persisted.

<html data-theme="dark"> is hardcoded on Line 2, so the guard on Line 28 (:root:not([data-theme])) can never match — the entire @media (prefers-color-scheme:light) block (Lines 27-33) never applies. Visitors with a light-mode OS preference still get the dark theme on first load, contradicting the "responsive light/dark themes" goal. Separately, the toggle handler (Lines 236-240) only mutates the attribute in memory — there's no localStorage read/write, so the choice resets to dark on every reload.

Proposed fix: initialize theme from storage/system preference in JS, and drop the hardcoded attribute
-<html lang="en" data-theme="dark">
+<html lang="en">
   var root=document.documentElement, btn=document.getElementById('theme');
+  (function initTheme(){
+    var saved=localStorage.getItem('theme');
+    if(saved){ root.setAttribute('data-theme', saved); }
+  })();
   btn.addEventListener('click',function(){
     var cur=root.getAttribute('data-theme')||'dark';
-    root.setAttribute('data-theme', cur==='dark'?'light':'dark');
+    var next=cur==='dark'?'light':'dark';
+    root.setAttribute('data-theme', next);
+    localStorage.setItem('theme', next);
   });

Also applies to: 22-33, 236-240

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/rooms/persona/index.html` at line 2, Remove the hardcoded data-theme
value from the html element and update the theme initialization logic to choose
localStorage’s saved theme first, then the system prefers-color-scheme
preference, with the existing dark theme as fallback. Update the toggle handler
to persist each theme change to localStorage so the selection survives reloads,
and remove the now-unreachable CSS guard that depends on the missing data-theme
attribute.

Comment on lines +122 to +126
.reveal{opacity:0;transform:translateY(14px);transition:opacity .6s ease,transform .6s ease}
.reveal.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){
html{scroll-behavior:auto}.reveal{opacity:1;transform:none;transition:none}.btn:hover,.card:hover{transform:none}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

All main content is invisible without JavaScript.

Every primary section (Lines 155-216) carries class="reveal", and .reveal{opacity:0;...} (Lines 122-123) is only cleared by the IntersectionObserver in the script (Lines 242-243). If JS fails to load/execute for any reason (blocked, error, disabled), the entire body content — the whole point of this outreach page — stays permanently invisible with no fallback.

Proposed fix: noscript fallback
 </style>
+<noscript><style>.reveal{opacity:1!important;transform:none!important}</style></noscript>
 </head>

Also applies to: 155-216, 242-243

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/rooms/persona/index.html` around lines 122 - 126, Ensure the main
content remains visible when JavaScript is unavailable or fails: update the
reveal styling and IntersectionObserver flow around the `.reveal` class so its
hidden state has a non-JavaScript fallback, while preserving the animation when
the script runs. Apply the fix consistently to all primary sections using
`class="reveal"`.


<footer><div class="wrap">
<span>© 2026 Russell Richardson · CATACLYSM STUDIOS INC</span>
<span>Rendered from <code>pmoves/rooms/persona/persona.json</code> · a room on pmoves.ai</span>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check whether ROADMAP/NEXT_STEPS were touched alongside this file, and whether persona.json exists for drift comparison.
fd -a ROADMAP.md pmoves/docs
fd -a NEXT_STEPS.md pmoves/docs
fd -a persona.json pmoves/rooms/persona
git log --oneline -3 -- pmoves/docs/NEXT_STEPS.md pmoves/docs/PMOVES.AI\ PLANS/ROADMAP.md 2>/dev/null

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 859


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== repo status/stat =="
git diff --stat HEAD~1..HEAD 2>/dev/null || git diff --stat 2>/dev/null || true

echo
echo "== tracked relevant files =="
git ls-files 'pmoves/rooms/persona/*' 'pmoves/docs/PMOVES.AI PLANS/ROADMAP.md' 'pmoves/docs/PMOVES.AI PLANS/NEXT_STEPS.md' 'docs/NEXT_STEPS.md' 'docs/LOCAL_CI_CHECKS.md' | sort

echo
echo "== git status concise =="
git status --short --untracked-files=no 2>/dev/null || true

echo
echo "== persona html/footer/json structure =="
wc -l pmoves/rooms/persona/index.html pmoves/rooms/persona/persona.json
sed -n '215,235p' pmoves/rooms/persona/index.html
python3 - <<'PY'
import json
from pathlib import Path
p=Path("pmoves/rooms/persona/persona.json")
try:
    data=json.loads(p.read_text())
    print("persona.json keys:", sorted(data.keys())[:20], "top-level keys count", len(data))
    for k,v in data.items():
        if isinstance(v, dict):
            print(f"  {k}: keys={sorted(v.keys())[:20]}, type_dict")
        elif isinstance(v, list):
            print(f"  {k}: len={len(v)}, type_list, sample={v[:3]}")
        else:
            print(f"  {k}: {type(v).__name__}: {repr(v)[:200]}")
except Exception as e:
    print("persona.json parse/read error:", repr(e))
PY

echo
echo "== search persona json fetch/render/process mentions =="
rg -n "persona\.json|fetch\\(|fetchJSON|load|render|persona" pmoves/rooms/persona/index.html pmoves/rooms/persona -g '*.{js,ts,html,json,md}' | head -200

echo
echo "== roadmap/next_updates snippets =="
for f in \
  'pmoves/docs/PMOVES.AI PLANS/ROADMAP.md' \
  'pmoves/docs/PMOVES.AI PLANS/NEXT_STEPS.md' \
  'docs/NEXT_STEPS.md' \
  'docs/LOCAL_CI_CHECKS.md'
do
  echo "--- $f ---"
  if [ -f "$f" ]; then
    wc -l "$f"
    rg -n "_Last updated|Last updated|persona|PMOVES.AI|check|LOCAL_CI_CHECKS|CI|room|persona" "$f" -A 3 -B 3 | head -200
  else
    echo "missing"
  fi
done

echo
echo "== recent commits touching all relevant trees =="
git log --oneline -10 --all -- 'pmoves/rooms/*' 'pmoves/docs/*' 'docs/ROADMAP.md' 'docs/NEXT_STEPS.md' 'docs/LOCAL_CI_CHECKS.md'

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 45553


Align the persona room source with its rendered claim and update the required PMOVES docs.

pmoves/rooms/persona/index.html declares itself as rendered from pmoves/rooms/persona/persona.json, but the page is hand-authored static HTML and contains no JSON load/render/validation, so future persona.json changes won’t be automatically reconciled. This also needs documentation/practical gating consistent with the pmoves/**/* guidelines: update pmoves/docs/PMOVES.AI PLANS/ROADMAP.md and pmoves/docs/PMOVES.AI PLANS/NEXT_STEPS.md for this room/persona shipment with _Last updated timestamps, and include the applicable local checks output or an intentional skip.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/rooms/persona/index.html` at line 230, The persona page must either
load, render, and validate pmoves/rooms/persona/persona.json or stop claiming it
is rendered from that file; align the implementation and displayed source
accordingly. Also update the PMOVES roadmap and next-steps documents with this
room/persona shipment, current “_Last updated” timestamps, and the applicable
local-check output or an explicitly documented intentional skip.

Source: Coding guidelines

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant