recognition: page, palette modal, & dashboard palette unlock — TDD

- billboard/recognition/ view + template; recognition/<slug>/set-palette endpoint (no trailing slash)
- recognition.html: <template>-based modal (clone on open, remove on close — Selenium find_elements compatible)
- recognition-page.js: image-box → modal → swatch preview → body-click restore → OK → confirm → POST set-palette
- _palettes_for_user() replaces static PALETTES; Recognition.palette unlocks swatch + populates data-shoptalk
- _unlocked_palettes_for_user() wires dynamic unlock check into set_palette view
- _applet-palette.html: data-shoptalk from context instead of hard-coded "Placeholder"
- _recognition.scss: banner, recog-list/item, image-box, modal, palette-confirm; :not([hidden]) pattern avoids display override
- FT T2 split into T2a (banner → FYI → recog page), T2b (palette modal flow), T2c (dashboard palette applet)
- 684 ITs green; 7 FTs green

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Disco DeDisco
2026-04-22 04:02:14 -04:00
parent 565f727aa6
commit 6d9d3d4f54
11 changed files with 683 additions and 53 deletions

View File

@@ -0,0 +1,180 @@
// ── Recognition banner (slides in below page h2 after unlock) ─────────────
.recog-banner {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.75rem 1rem;
background: rgba(var(--priUser), 0.12);
border-left: 3px solid rgba(var(--priUser), 0.6);
margin-bottom: 0.75rem;
.recog-banner__body {
flex: 1;
min-width: 0;
}
.recog-banner__title {
margin: 0;
font-weight: bold;
}
.recog-banner__description,
.recog-banner__timestamp {
margin: 0.1rem 0 0;
font-size: 0.85rem;
opacity: 0.75;
}
.recog-banner__image {
width: 3rem;
height: 3rem;
flex-shrink: 0;
background: rgba(var(--priUser), 0.15);
border-radius: 2px;
}
.recog-banner__nvm,
.recog-banner__fyi {
flex-shrink: 0;
font-size: 0.8rem;
padding: 0.25rem 0.6rem;
}
}
// ── Recognition page ───────────────────────────────────────────────────────
.recognition-page {
padding: 0.75rem;
}
.recog-list {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.recog-item {
position: relative;
display: flex;
flex-direction: column;
gap: 0.4rem;
padding: 0.75rem;
background: rgba(var(--priUser), 0.06);
border: 1px solid rgba(var(--priUser), 0.2);
border-radius: 4px;
width: 14rem;
.recog-item__title {
margin: 0;
font-weight: bold;
}
.recog-item__description {
margin: 0;
font-size: 0.85rem;
opacity: 0.75;
}
}
// Image box — must have a defined size so Selenium can interact with it.
.recog-item__image-box {
width: 5rem;
height: 5rem;
display: flex;
align-items: center;
justify-content: center;
background: rgba(var(--priUser), 0.12);
border: 1px dashed rgba(var(--priUser), 0.4);
border-radius: 2px;
cursor: pointer;
font-size: 1.5rem;
opacity: 0.6;
&:hover { opacity: 1; }
}
// Unlocked palette swatch inside a recognition item
.recog-item__palette {
width: 5rem;
height: 5rem;
border-radius: 2px;
border: 2px solid rgba(var(--priUser), 0.4);
}
// ── Palette modal ──────────────────────────────────────────────────────────
.recog-palette-modal {
position: absolute;
top: 0;
left: 0;
z-index: 200;
background: var(--bg, #1a1a1a);
border: 1px solid rgba(var(--priUser), 0.4);
border-radius: 4px;
padding: 0.75rem;
gap: 0.5rem;
min-width: 12rem;
&:not([hidden]) { display: flex; flex-direction: column; }
// Each palette swatch option inside the modal
> [class*="palette-"] {
display: flex;
align-items: center;
gap: 0.5rem;
.recog-swatch-body {
width: 2.5rem;
height: 2.5rem;
border-radius: 2px;
cursor: pointer;
border: 2px solid rgba(var(--priUser), 0.3);
flex-shrink: 0;
&:hover { border-color: rgba(var(--priUser), 0.8); }
}
.btn {
font-size: 0.75rem;
padding: 0.2rem 0.5rem;
}
}
}
// ── Palette swatch color fills ─────────────────────────────────────────────
// These match the actual palette CSS variables — used both in modal swatches
// and as the confirmed .recog-item__palette swatch.
.palette-bardo .recog-swatch-body,
.recog-item__palette.palette-bardo {
background: #2a1a2e;
}
.palette-sheol .recog-swatch-body,
.recog-item__palette.palette-sheol {
background: #1a1a2e;
}
// ── Confirm submenu ────────────────────────────────────────────────────────
.recog-palette-confirm {
border-top: 1px solid rgba(var(--priUser), 0.2);
padding-top: 0.5rem;
gap: 0.4rem;
&:not([hidden]) { display: flex; flex-direction: column; }
p {
margin: 0;
font-size: 0.85rem;
}
.btn {
font-size: 0.8rem;
padding: 0.2rem 0.5rem;
}
}

View File

@@ -10,6 +10,7 @@
@import 'natus';
@import 'tray';
@import 'billboard';
@import 'recognition';
@import 'tooltips';
@import 'game-kit';
@import 'wallet-tokens';