mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-07-28 23:52:16 +00:00
Adds the Achievements & Feats of Power local engine, fully offline. Core (static/v3/profile.js): the Profile screen becomes tabbed exactly like v3 Settings (.fb-tabbar/.fb-tab/.fb-tabpanel, active tab persisted in localStorage 'v3-profile-tab'). A Profile (main) tab carries the existing cards + a Feats trophy-shelf mount (#v3-profile-feats-slot, earned-only), and an Achievements tab carries a plugin mount (#v3-profile-achievements-mount) + empty-state note. A new `v3:profile-rendered` event fires after every render so the plugin re-injects (mirrors v3:settings-rendered). New bundled plugin (plugins/achievements/): SQLite engine (unlocks/counters/comp_ledger/sync_queue) with pure threshold/criterion math in the testable sibling engine.py (P-V); routes activity/ report-unlock/report-criterion/catalog/earned/feats/remove-me. Feats read activity counters only (batched song:ended POST; notes only when notedetect present — graceful degradation); competency Achievements evaluate from progression events only — the integration law, never crossed. Catalogue is always shown (locked=greyed), grouped by the real progression paths (Global/Guitar/Bass/Drums/Keys, auto-extending) with per-category earned badges. Versioned window.feedBack.achievements registration API with the __feedBackAchievementsPending load-order queue + achievements:ready event. Verified natively (uvicorn) end-to-end + Playwright (tabbar, earned-only Feats shelf, greyed catalogue, registration API, zero console errors); 24 plugin tests pass incl. the integration-law assertion. Opt-in/privacy/data-min gate (PR2) and the hosted wall (PR3) follow. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
85 lines
2.7 KiB
CSS
85 lines
2.7 KiB
CSS
/* Achievements & Feats of Power — plugin styles (plain CSS, no Tailwind build;
|
|
* P-II: plugins ship their own stylesheet for non-core classes). Mirrors the v3
|
|
* dark surface tokens used across the Profile page. */
|
|
|
|
/* Secondary category pill row inside the Achievements tab (lighter .fb-tab). */
|
|
.fb-ach-pillrow {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: .4rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
.fb-ach-pill {
|
|
appearance: none;
|
|
background: rgba(30, 41, 59, .5);
|
|
border: 1px solid rgba(51, 65, 85, .6);
|
|
color: #94a3b8;
|
|
border-radius: 9999px;
|
|
padding: .35rem .75rem;
|
|
font-size: .8rem;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
transition: color .15s, border-color .15s, background .15s;
|
|
}
|
|
.fb-ach-pill:hover { color: #e2e8f0; border-color: rgba(14, 165, 233, .4); }
|
|
.fb-ach-pill.active { color: #f8fafc; background: rgba(14, 165, 233, .15); border-color: #0ea5e9; }
|
|
.fb-ach-pill-badge {
|
|
font-size: .7rem;
|
|
font-weight: 700;
|
|
color: #64748b;
|
|
margin-left: .15rem;
|
|
}
|
|
.fb-ach-pill.active .fb-ach-pill-badge { color: #7dd3fc; }
|
|
|
|
/* Catalogue list. */
|
|
.fb-ach-list { display: flex; flex-direction: column; gap: .5rem; }
|
|
.fb-ach-item {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: .85rem;
|
|
padding: .75rem .9rem;
|
|
border-radius: .6rem;
|
|
border: 1px solid rgba(51, 65, 85, .5);
|
|
background: rgba(30, 41, 59, .35);
|
|
}
|
|
.fb-ach-item.locked { opacity: .45; filter: grayscale(.6); }
|
|
.fb-ach-item.earned { border-color: rgba(14, 165, 233, .35); background: rgba(14, 165, 233, .06); }
|
|
.fb-ach-item-icon { font-size: 1.4rem; line-height: 1.6rem; flex: 0 0 auto; }
|
|
.fb-ach-item-body { min-width: 0; }
|
|
.fb-ach-item-title {
|
|
font-size: .9rem;
|
|
font-weight: 700;
|
|
color: #f1f5f9;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .4rem;
|
|
}
|
|
.fb-ach-tier {
|
|
font-size: .65rem;
|
|
text-transform: uppercase;
|
|
letter-spacing: .04em;
|
|
font-weight: 700;
|
|
color: #7dd3fc;
|
|
border: 1px solid rgba(125, 211, 252, .35);
|
|
border-radius: 9999px;
|
|
padding: .05rem .4rem;
|
|
}
|
|
.fb-ach-item-desc { font-size: .78rem; color: #94a3b8; margin-top: .15rem; }
|
|
|
|
/* Feats of Power trophy shelf (profile main page). */
|
|
.fb-feat-shelf {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
|
gap: .75rem;
|
|
}
|
|
.fb-feat-card {
|
|
text-align: center;
|
|
padding: 1rem .75rem;
|
|
border-radius: .7rem;
|
|
border: 1px solid rgba(234, 179, 8, .35);
|
|
background: linear-gradient(180deg, rgba(234, 179, 8, .1), rgba(30, 41, 59, .3));
|
|
}
|
|
.fb-feat-icon { font-size: 1.9rem; }
|
|
.fb-feat-title { font-size: .85rem; font-weight: 800; color: #fde68a; margin-top: .3rem; }
|
|
.fb-feat-desc { font-size: .72rem; color: #cbd5e1; margin-top: .25rem; }
|