From 94d2b4bbda6451043606856f2885d342093ceb6f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 00:59:06 +0000 Subject: [PATCH 1/2] Initial plan From edde446366042af5e49ccfc5c5e8ddf2eec26b38 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 01:14:59 +0000 Subject: [PATCH 2/2] Implement ADR-006 Level Zero Adaptive Onboarding Flow - Remove beginPulse glow from Begin Setup button (glow only on Get Started) - Add hover tooltip explainers to 3 hero feature pills - Robot Phase 1: Hover over icons instruction + pill tour animation - Robot Phase 2: Get Started button in speech bubble + 60s inactivity glow - Get Started -> Trade Window -> rocket -> fireworks -> Genesis Pioneer - Achievement gating: all except Discover Profiles locked until Trade Window - Pre-trade content gating via body.pre-trade class - Second achievement: Discover Profiles unlock on browse/fork/begin setup - Robot excited transition to achievements section - AGENT_GUIDE.md bug log entries BUG-007/008/009" Co-authored-by: Maangled <108793241+Maangled@users.noreply.github.com> Agent-Logs-Url: https://github.com/Maangled/ferros/sessions/ed22ea0b-d5e8-4cd9-a93f-20af00714b28 --- docs/AGENT_GUIDE.md | 22 +++ docs/personal-profile.html | 276 +++++++++++++++++++++++++++++++++---- 2 files changed, 275 insertions(+), 23 deletions(-) diff --git a/docs/AGENT_GUIDE.md b/docs/AGENT_GUIDE.md index 24ed3e0..d6d5099 100644 --- a/docs/AGENT_GUIDE.md +++ b/docs/AGENT_GUIDE.md @@ -163,6 +163,28 @@ Documented bugs, root causes, and their fixes. Check here before fixing anything **Root cause:** If alias state were stored in localStorage instead of sessionStorage, it would persist. **Prevention:** `ferros_alias_session` MUST use `sessionStorage`, never `localStorage`. Do not move it. +### BUG-007: Begin Setup Button Had Wrong Glow Animation +**Symptom:** "Begin Setup →" button in the genesis card was pulsing with `beginPulse` glow animation, making it appear to be the primary CTA when it is a secondary path. +**Root cause:** PR #23 added `beginPulse` to `.begin-btn` in CSS (and PR A re-applied it in `_postBootReveal()`). The glow belongs ONLY on the "Get Started" button inside the robot's speech bubble dialog, after ~60 seconds of user inactivity. +**Fixed in:** PR D (ADR-006 implementation) +**Fix:** Removed `animation: beginPulse …` from the `.begin-btn` CSS rule. The Begin Setup button is now a static button with no glow. The adaptive glow (`getStartedPulse`) is applied only to `#get-started-btn` inside the robot dialog after a 60-second inactivity timeout. +**Button differentiation (per ADR-006):** +- **"Get Started"** → inside robot speech bubble, opens Trade Window, glows after ~60s inactivity +- **"Begin Setup →"** → in "Welcome to Your Progression System" box, proceeds to Stage 1, **no glow** +- **"🍴 Fork this Profile"** → on featured profile cards, starts alias mode, **no glow** + +### BUG-008: Achievement Tooltips Dismissed Before Clicking Buttons Inside +**Symptom:** Flowchart/diagram popups on achievement cards dismissed when moving cursor from the card to the popup button inside it, because the `:hover` state was on the card and moving to the popup broke the hover chain. +**Root cause:** CSS `:hover`-only tooltip pattern: as soon as the pointer left the `.genesis-ach-card` boundary (even to enter the `.ach-hover-diagram` child), the tooltip collapsed. +**Fixed in:** PR A (click-to-toggle pattern) — click card to toggle `.ach-active` class; click outside to dismiss. +**Note:** The click-to-toggle pattern is already implemented. Do not revert to `:hover`-only. + +### BUG-009: Scroll Gating Clipped Begin Button Below Fold +**Symptom:** On viewports shorter than the total hero content height, the "Begin Setup →" button was unreachable because `body.scroll-gated { height: 100vh; overflow: hidden }` prevented scrolling past the fold. +**Root cause:** PR #24's scroll gating used `overflow: hidden` on `body` without allowing internal scroll on `#stage-0`. +**Fixed in:** PR #26 — `body.scroll-gated #stage-0 { max-height: 100vh; overflow-y: auto }` so the stage can scroll internally while the body is gated. +**Do not remove** the `#stage-0` internal scroll rule when modifying scroll gating CSS. + --- ## What Not To Do (Anti-Patterns) diff --git a/docs/personal-profile.html b/docs/personal-profile.html index 11228fc..800639f 100644 --- a/docs/personal-profile.html +++ b/docs/personal-profile.html @@ -113,7 +113,7 @@ .assist-lock-tooltip{background:rgba(245,158,11,.1);border:1px solid rgba(245,158,11,.3);border-radius:5px;color:var(--accent-amber);font-size:.75rem;margin-top:4px;padding:4px 10px;animation:tooltipFadeOut 2.5s ease-out forwards} @keyframes tooltipFadeOut{0%{opacity:1}70%{opacity:1}100%{opacity:0}} @keyframes beginPulse{0%,100%{box-shadow:0 0 20px rgba(45,212,191,.2)}50%{box-shadow:0 0 40px rgba(45,212,191,.65),0 0 64px rgba(74,144,217,.3);filter:brightness(1.12)}} - .begin-btn{width:100%;background:linear-gradient(90deg,var(--accent-blue),var(--accent-cyan));border:none;border-radius:8px;color:#fff;cursor:pointer;font-size:1.1rem;font-weight:700;letter-spacing:.05em;padding:16px 32px;transition:all .2s;box-shadow:0 0 20px rgba(45,212,191,.2);animation:beginPulse 2.4s ease-in-out 8s infinite} + .begin-btn{width:100%;background:linear-gradient(90deg,var(--accent-blue),var(--accent-cyan));border:none;border-radius:8px;color:#fff;cursor:pointer;font-size:1.1rem;font-weight:700;letter-spacing:.05em;padding:16px 32px;transition:all .2s;box-shadow:0 0 20px rgba(45,212,191,.2)} .begin-btn:hover{transform:translateY(-2px);box-shadow:0 4px 24px rgba(45,212,191,.4)} .begin-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;animation:none} /* Android Companion */ @@ -586,6 +586,40 @@ body.boot-speech .speech-boot{opacity:1!important} .speech-boot{font-size:.65rem!important;line-height:1.45!important;opacity:0;animation:none!important} body.boot-speech .speech-bubble-wrap{height:auto;min-height:52px} + /* Phase speech bubbles — robot onboarding phases 1 & 2 */ + .speech-phase1,.speech-phase2,.speech-congrats{font-size:.65rem!important;line-height:1.45!important;opacity:0;animation:none!important} + body.phase1-speech .speech-b1,body.phase1-speech .speech-b2,body.phase1-speech .speech-b3,body.phase1-speech .speech-boot{opacity:0!important;animation:none!important} + body.phase1-speech .speech-phase1{opacity:1!important} + body.phase2-speech .speech-b1,body.phase2-speech .speech-b2,body.phase2-speech .speech-b3,body.phase2-speech .speech-boot{opacity:0!important;animation:none!important} + body.phase2-speech .speech-phase2{opacity:1!important} + body.congrats-speech .speech-b1,body.congrats-speech .speech-b2,body.congrats-speech .speech-b3,body.congrats-speech .speech-boot,body.congrats-speech .speech-phase2{opacity:0!important;animation:none!important} + body.congrats-speech .speech-congrats{opacity:1!important} + body.phase1-speech .speech-bubble-wrap,body.phase2-speech .speech-bubble-wrap,body.congrats-speech .speech-bubble-wrap{height:auto;min-height:52px} + /* Get Started button inside robot dialog */ + .get-started-btn{display:block;width:calc(100% - 14px);margin:6px 7px 2px;background:linear-gradient(90deg,var(--accent-blue),var(--accent-cyan));border:none;border-radius:6px;color:#fff;cursor:pointer;font-size:.72rem;font-weight:700;padding:7px 10px;transition:all .2s;text-align:center;letter-spacing:.03em} + .get-started-btn:hover{transform:translateY(-1px);box-shadow:0 3px 14px rgba(45,212,191,.4)} + .get-started-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;animation:none!important} + @keyframes getStartedPulse{0%,100%{box-shadow:0 0 10px rgba(45,212,191,.2)}50%{box-shadow:0 0 28px rgba(45,212,191,.8),0 0 52px rgba(74,144,217,.35);filter:brightness(1.18)}} + .get-started-btn.glow{animation:getStartedPulse 2s ease-in-out infinite} + /* Feature pill tooltip system */ + .feature-pill-wrap{position:relative;display:inline-block} + .feature-pill-tooltip{position:absolute;bottom:calc(100% + 10px);left:50%;transform:translateX(-50%);min-width:190px;max-width:230px;background:var(--bg-panel);border:1px solid var(--accent-cyan);border-radius:8px;padding:10px 12px;font-size:.68rem;color:var(--text-secondary);line-height:1.5;z-index:500;opacity:0;pointer-events:none;transition:opacity .25s ease;box-shadow:var(--shadow-panel),0 0 16px rgba(45,212,191,.12);text-align:left} + .feature-pill-tooltip::after{content:'';position:absolute;top:100%;left:50%;transform:translateX(-50%);border:5px solid transparent;border-top-color:var(--accent-cyan)} + .feature-pill-wrap:hover .feature-pill-tooltip,.feature-pill-wrap.pill-active .feature-pill-tooltip{opacity:1;pointer-events:auto} + /* Pre-Trade state: achievements and profiles hidden until Get Started → Trade Window accepted */ + body.pre-trade .genesis-ach-section,body.pre-trade .gallery-preview-section,body.pre-trade .alias-entry-section,body.pre-trade .recovery-entry-section{display:none!important} + /* Locked achievements: greyed out but still hoverable/clickable */ + .genesis-ach-card.ach-locked{opacity:.5;filter:grayscale(40%)} + .genesis-ach-card.ach-locked:hover{opacity:.7;filter:grayscale(20%)} + /* Robot transition between sections */ + .android-companion{transition:transform .5s ease} + @keyframes robotExitRight{from{opacity:1;transform:translateX(0)}to{opacity:0;transform:translateX(150px)}} + @keyframes robotEnterLeft{from{opacity:0;transform:translateX(-150px)}to{opacity:1;transform:translateX(0)}} + .android-companion.robot-exit-right{animation:robotExitRight .6s ease-in forwards!important;transition:none} + .android-companion.robot-enter-left{animation:robotEnterLeft .7s ease-out forwards!important;transition:none} + /* Robot excited: faster bob animation */ + @keyframes androidBobFast{0%,100%{transform:translateY(0)}50%{transform:translateY(-9px)}} + .android-companion.robot-excited .android-figure{animation:androidBobFast .45s ease-in-out infinite!important} @@ -704,9 +738,18 @@
Level up your life. Track your growth. Earn real skills.
Start at Level 1. Complete quests. Unlock your full dashboard.
- ⛏ Cryptographic Seals - 🏆 Achievement System - 🔒 100% Local — No Servers +
+ ⛏ Cryptographic Seals +
Every action you log is sealed with a cryptographic hash, creating a tamper-evident chain of your progress that nobody can alter — not even you.
+
+
+ 🏆 Achievement System +
Completing milestones earns Seal Points (SP) and unlocks new stages of your FERROS profile, dashboard panels, and assist levels.
+
+
+ 🔒 100% Local — No Servers +
Nothing leaves your device — your data lives in your browser's localStorage. Works on file://, no cloud, no tracking, no accounts required.
+
@@ -716,6 +759,9 @@
Take your time... ✨
Press Begin when ready →
FERROS is free for you for life — so long as you take care of me! 🖥
+
Hover over each of the icons to see more information 👆
+
FERROS is free, for you, for life.
+
Congrats! 🎉 You got your first achievement!
@@ -1415,6 +1461,23 @@

Your First Protocol

},1800); } + /* Discover Profiles achievement unlock — triggered by Browse Profiles or Begin Setup */ + var _discoverProfilesUnlocked=false; + function _unlockDiscoverProfiles(){ + if(_discoverProfilesUnlocked)return; + if(!_tradeWindowAccepted&&!sessionMode)return; // Genesis Pioneer must come first + _discoverProfilesUnlocked=true; + var card=$('ach-discover-profiles'); + if(card){ + card.classList.remove('ach-locked'); + setTimeout(function(){ + card.classList.add('pioneer-unlocked'); + showSPFloat(15,card); + showXPToast('🌎','Discover Profiles \u2014 +15 SP!'); + },400); + } + } + async function init(){ const exists=loadProfile(); selectedAssistLevel=(exists?profile.meta.assistanceLevel:null)||1; @@ -1514,11 +1577,14 @@

Your First Protocol

async function completeStage0(){ unlockScroll(); + // Trigger Discover Profiles achievement (second achievement in chain) + _unlockDiscoverProfiles(); function doRocketThenStage(){ const btn=$('begin-btn');if(btn)btn.disabled=true; launchRocketAnimation(function(){_doCompleteStage0();}); } - if(!sessionMode&&localStorage.getItem('ferros_profile')===null){ + // Skip Trade Window if already accepted via Get Started button (ADR-006) + if(!sessionMode&&!_tradeWindowAccepted&&localStorage.getItem('ferros_profile')===null){ showTradeDialog(doRocketThenStage); return; } @@ -2394,11 +2460,11 @@

Your First Protocol

+'' +'
'; }).join(''); - const blankCard='