600 lines
20 KiB
HTML
600 lines
20 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<title>Pinkudex — Actress rating banner mockup</title>
|
||
<style>
|
||
:root {
|
||
--bg-0: #0b0d10;
|
||
--bg-1: #14171c;
|
||
--bg-2: #1c2027;
|
||
--bg-3: #252a33;
|
||
--fg: #e6e8ec;
|
||
--fg-dim: #a4abb6;
|
||
--fg-muted: #6b7380;
|
||
--cyan: #22d3ee;
|
||
--mint: #34d399;
|
||
--amber: #fbbf24;
|
||
--coral: #f87171;
|
||
--violet: #a78bfa;
|
||
--pink: #f472b6;
|
||
--glass: rgba(255,255,255,0.04);
|
||
--glass-border: rgba(255,255,255,0.10);
|
||
--glass-border-strong: rgba(255,255,255,0.18);
|
||
}
|
||
* { box-sizing: border-box; }
|
||
html, body { margin: 0; padding: 0; }
|
||
body {
|
||
background: var(--bg-0);
|
||
color: var(--fg);
|
||
font: 14px/1.5 ui-sans-serif, system-ui, -apple-system, "Segoe UI";
|
||
min-height: 100vh;
|
||
}
|
||
.page { max-width: 1320px; margin: 0 auto; padding: 28px; }
|
||
h1 { font-weight: 500; font-size: 22px; margin: 0 0 6px; letter-spacing: -0.01em; }
|
||
h2 { font-weight: 600; font-size: 11px; margin: 28px 0 12px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--cyan); }
|
||
.sub { color: var(--fg-muted); font-size: 13px; margin-bottom: 20px; }
|
||
|
||
/* Control panel */
|
||
.controls {
|
||
display: flex; gap: 18px; align-items: center; flex-wrap: wrap;
|
||
background: var(--bg-1); border: 1px solid var(--glass-border);
|
||
border-radius: 12px; padding: 14px 18px; margin-bottom: 20px;
|
||
}
|
||
.ctrl-group { display: flex; align-items: center; gap: 10px; }
|
||
.ctrl-group label {
|
||
font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em;
|
||
color: var(--fg-muted); font-weight: 600;
|
||
}
|
||
.seg {
|
||
display: flex; gap: 0; padding: 3px;
|
||
background: var(--bg-0); border: 1px solid var(--glass-border);
|
||
border-radius: 7px;
|
||
}
|
||
.seg button {
|
||
background: transparent; border: 0; color: var(--fg-dim);
|
||
font-family: ui-monospace, monospace; font-size: 11px;
|
||
padding: 5px 11px; border-radius: 5px; cursor: pointer;
|
||
transition: all 120ms; min-width: 56px; text-align: center;
|
||
}
|
||
.seg button:hover { color: var(--fg); }
|
||
.seg button.active {
|
||
background: rgba(34,211,238,0.18);
|
||
color: var(--cyan);
|
||
}
|
||
.swatch-row { display: flex; gap: 6px; }
|
||
.swatch-row button {
|
||
width: 28px; height: 28px; border-radius: 6px; border: 2px solid transparent;
|
||
cursor: pointer; padding: 0; transition: border-color 120ms, transform 120ms;
|
||
}
|
||
.swatch-row button:hover { transform: scale(1.06); }
|
||
.swatch-row button.active { border-color: white; }
|
||
|
||
/* Grid */
|
||
.grid {
|
||
display: grid;
|
||
gap: 16px;
|
||
}
|
||
.grid.portrait { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
|
||
.grid.landscape { grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); }
|
||
|
||
/* Actress card */
|
||
.card {
|
||
position: relative;
|
||
background: var(--bg-1);
|
||
border: 1px solid var(--glass-border);
|
||
border-radius: 12px; overflow: hidden;
|
||
cursor: pointer;
|
||
transition: transform 180ms, border-color 180ms;
|
||
}
|
||
.card:hover {
|
||
transform: translateY(-2px);
|
||
border-color: var(--glass-border-strong);
|
||
}
|
||
.card-portrait {
|
||
position: relative; width: 100%;
|
||
background: linear-gradient(135deg, #2a2540, #15101e);
|
||
overflow: hidden;
|
||
}
|
||
.grid.portrait .card-portrait { aspect-ratio: 1 / 1.618; }
|
||
.grid.landscape .card-portrait { aspect-ratio: 1.618 / 1; }
|
||
.card-portrait .face {
|
||
position: absolute; inset: 0;
|
||
display: flex; align-items: center; justify-content: center;
|
||
color: rgba(255,255,255,0.18);
|
||
font-family: ui-monospace, monospace; font-size: 14px;
|
||
}
|
||
.card-portrait .face::before {
|
||
content: "";
|
||
width: 60%; height: 60%; border-radius: 50%;
|
||
background: radial-gradient(circle at 35% 30%, rgba(255,255,255,0.18), transparent 70%);
|
||
position: absolute;
|
||
}
|
||
.card-portrait .face::after {
|
||
content: attr(data-letter);
|
||
font-size: 64px; font-weight: 200; color: rgba(255,255,255,0.15);
|
||
z-index: 1;
|
||
}
|
||
|
||
/* Category badges (already in the codebase, matching the modified ActressCard) */
|
||
.cat-badges {
|
||
position: absolute; top: 8px; left: 8px; z-index: 10;
|
||
display: flex; flex-wrap: wrap; gap: 4px; max-width: 60%;
|
||
}
|
||
.cat-badge {
|
||
display: inline-flex; align-items: center; gap: 4px;
|
||
font-family: ui-monospace, monospace; font-size: 9px;
|
||
font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em;
|
||
background: rgba(0,0,0,0.8); backdrop-filter: blur(4px);
|
||
padding: 3px 8px; border-radius: 999px;
|
||
text-shadow: 0 1px 2px rgba(0,0,0,0.9);
|
||
}
|
||
|
||
/* === THE RATING RIBBON ===
|
||
Standard pattern:
|
||
- .ribbon = a square clipping wrap pinned to a corner of the card,
|
||
overflow:hidden so anything outside the corner triangle gets cut.
|
||
- .band = a wide strip rotated 45° and offset so its visible
|
||
portion fills the diagonal exactly. Width must exceed the wrap's
|
||
diagonal (≈ wrap × √2) so the strip reaches edge-to-edge.
|
||
*/
|
||
.ribbon {
|
||
position: absolute;
|
||
width: 96px; height: 96px;
|
||
overflow: hidden;
|
||
pointer-events: none;
|
||
z-index: 11;
|
||
}
|
||
.ribbon .band {
|
||
position: absolute;
|
||
display: block;
|
||
width: 160px; /* > 96 × √2 (~136), with margin for end clip */
|
||
line-height: 22px;
|
||
padding: 3px 0;
|
||
text-align: center;
|
||
font-family: ui-monospace, monospace;
|
||
font-size: 10px; font-weight: 700;
|
||
text-transform: uppercase; letter-spacing: 0.08em;
|
||
color: white;
|
||
text-shadow: 0 1px 2px rgba(0,0,0,0.5);
|
||
box-shadow: 0 2px 6px rgba(0,0,0,0.35);
|
||
}
|
||
/* Top-right diagonal:
|
||
pin top-right of band to (top:22px, right:-38px), rotate +45°.
|
||
Numbers chosen so the strip's cut ends sit just inside the wrap. */
|
||
.ribbon.top-right { top: 0; right: 0; }
|
||
.ribbon.top-right .band {
|
||
top: 22px;
|
||
right: -38px;
|
||
transform: rotate(45deg);
|
||
}
|
||
/* Top-left mirror */
|
||
.ribbon.top-left { top: 0; left: 0; }
|
||
.ribbon.top-left .band {
|
||
top: 22px;
|
||
left: -38px;
|
||
transform: rotate(-45deg);
|
||
}
|
||
|
||
/* Variants */
|
||
.ribbon.coral .band { background: var(--coral); }
|
||
.ribbon.amber .band { background: var(--amber); color: #2a1a00; text-shadow: none; }
|
||
.ribbon.gradient .band {
|
||
background: linear-gradient(90deg, var(--cyan), var(--violet));
|
||
}
|
||
.ribbon.cyan .band { background: var(--cyan); color: #002028; text-shadow: none; }
|
||
.ribbon.pink .band { background: var(--pink); }
|
||
|
||
/* Style: stars vs numeric */
|
||
.ribbon.numeric .band::before { content: "RATING: " attr(data-r); }
|
||
.ribbon.numeric.compact .band::before { content: "★ " attr(data-r); letter-spacing: 0.04em; }
|
||
.ribbon.stars .band::before {
|
||
content: attr(data-stars);
|
||
letter-spacing: 0.18em;
|
||
}
|
||
|
||
/* Card meta strip */
|
||
.card-meta {
|
||
background: var(--bg-2);
|
||
padding: 10px 12px;
|
||
display: flex; flex-direction: column; gap: 4px;
|
||
}
|
||
.card-name {
|
||
display: flex; align-items: center; gap: 6px;
|
||
font-weight: 500;
|
||
}
|
||
.card-name .gender {
|
||
color: var(--pink);
|
||
font-size: 14px;
|
||
}
|
||
.card-age {
|
||
font-size: 11px; color: var(--fg-muted);
|
||
}
|
||
.card-count {
|
||
margin-top: 6px;
|
||
background: var(--bg-3);
|
||
border-radius: 6px;
|
||
padding: 6px 10px;
|
||
font-family: ui-monospace, monospace; font-size: 11px;
|
||
color: var(--fg-dim);
|
||
display: flex; align-items: center; gap: 8px;
|
||
}
|
||
.card-count .play { color: var(--cyan); font-size: 12px; }
|
||
|
||
/* Editor panel */
|
||
.editor {
|
||
margin-top: 28px;
|
||
background: var(--bg-1);
|
||
border: 1px solid var(--glass-border);
|
||
border-radius: 14px; padding: 18px 20px;
|
||
}
|
||
.editor h3 {
|
||
margin: 0 0 12px;
|
||
font-size: 13px; font-weight: 600;
|
||
text-transform: uppercase; letter-spacing: 0.08em;
|
||
color: var(--cyan);
|
||
}
|
||
.editor .row {
|
||
display: grid; grid-template-columns: 130px 1fr; gap: 14px;
|
||
align-items: center;
|
||
padding: 8px 0;
|
||
border-bottom: 1px dashed var(--glass-border);
|
||
}
|
||
.editor .row:last-child { border-bottom: 0; }
|
||
.editor .lbl {
|
||
font-size: 12px; color: var(--fg-muted);
|
||
text-transform: uppercase; letter-spacing: 0.06em;
|
||
font-weight: 600;
|
||
}
|
||
.stars {
|
||
display: flex; gap: 2px;
|
||
}
|
||
.stars button {
|
||
background: transparent; border: 0;
|
||
color: var(--fg-muted); cursor: pointer;
|
||
font-size: 22px; line-height: 1;
|
||
padding: 4px;
|
||
transition: color 120ms, transform 120ms;
|
||
}
|
||
.stars button:hover { transform: scale(1.15); }
|
||
.stars button.on { color: var(--amber); }
|
||
.stars button.clear {
|
||
margin-left: 8px;
|
||
font-size: 11px; font-family: ui-monospace, monospace;
|
||
color: var(--fg-muted);
|
||
text-transform: uppercase; letter-spacing: 0.06em;
|
||
border: 1px solid var(--glass-border-strong);
|
||
border-radius: 5px; padding: 4px 8px;
|
||
}
|
||
.stars button.clear:hover { color: var(--coral); border-color: var(--coral); }
|
||
|
||
/* Detail hero (showing what the bigger ribbon looks like on /actress/[slug]) */
|
||
.detail {
|
||
display: grid; grid-template-columns: 320px 1fr; gap: 20px;
|
||
background: var(--bg-1); border: 1px solid var(--glass-border);
|
||
border-radius: 14px; overflow: hidden;
|
||
margin-top: 20px;
|
||
}
|
||
.detail .hero {
|
||
position: relative;
|
||
aspect-ratio: 1 / 1.618;
|
||
background: linear-gradient(135deg, #3a2a52, #1c1430);
|
||
}
|
||
.detail .hero .face {
|
||
position: absolute; inset: 0;
|
||
display: flex; align-items: center; justify-content: center;
|
||
}
|
||
.detail .hero .face::after {
|
||
content: attr(data-letter);
|
||
font-size: 96px; font-weight: 200; color: rgba(255,255,255,0.18);
|
||
}
|
||
.detail .hero .ribbon {
|
||
width: 140px; height: 140px;
|
||
}
|
||
.detail .hero .ribbon .band {
|
||
width: 220px;
|
||
line-height: 28px;
|
||
padding: 4px 0;
|
||
font-size: 12px;
|
||
}
|
||
.detail .hero .ribbon.top-right .band {
|
||
top: 32px;
|
||
right: -52px;
|
||
transform: rotate(45deg);
|
||
}
|
||
.detail .hero .ribbon.top-left .band {
|
||
top: 32px;
|
||
left: -52px;
|
||
transform: rotate(-45deg);
|
||
}
|
||
.detail .info {
|
||
padding: 24px;
|
||
}
|
||
.detail .info h3 {
|
||
margin: 0 0 4px; font-size: 28px; font-weight: 500;
|
||
display: flex; align-items: center; gap: 12px;
|
||
}
|
||
.detail .info h3 .female { color: var(--pink); font-size: 22px; }
|
||
.detail .info .meta-grid {
|
||
display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
|
||
gap: 14px; margin-top: 22px;
|
||
border-top: 1px solid var(--glass-border); padding-top: 18px;
|
||
}
|
||
.detail .info .meta-grid .it {
|
||
display: flex; flex-direction: column;
|
||
}
|
||
.detail .info .meta-grid .it .k {
|
||
font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em;
|
||
color: var(--fg-muted); font-family: ui-monospace, monospace;
|
||
}
|
||
.detail .info .meta-grid .it .v {
|
||
font-size: 14px; color: var(--fg);
|
||
}
|
||
|
||
/* Comparison row showing top-left vs top-right with categories */
|
||
.comparison {
|
||
display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px;
|
||
}
|
||
.comparison .label {
|
||
font-family: ui-monospace, monospace; font-size: 10px;
|
||
text-transform: uppercase; letter-spacing: 0.08em;
|
||
color: var(--fg-muted);
|
||
margin-bottom: 8px;
|
||
}
|
||
.comparison .label.bad { color: var(--coral); }
|
||
.comparison .label.good { color: var(--mint); }
|
||
|
||
/* Demo data positioning */
|
||
.legend {
|
||
background: var(--bg-1);
|
||
border: 1px solid var(--glass-border);
|
||
border-radius: 10px;
|
||
padding: 12px 16px;
|
||
margin-bottom: 16px;
|
||
color: var(--fg-dim);
|
||
font-size: 12px;
|
||
line-height: 1.7;
|
||
}
|
||
.legend strong { color: var(--fg); }
|
||
.legend code {
|
||
background: var(--bg-0); padding: 1px 5px; border-radius: 4px;
|
||
font-size: 11px; color: var(--cyan);
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<div class="page">
|
||
<h1>Actress rating banner — visual mockup</h1>
|
||
<div class="sub">
|
||
Click the stars in the editor to apply a rating to all cards. Use the controls to swap color / position / style.
|
||
</div>
|
||
|
||
<div class="controls">
|
||
<div class="ctrl-group">
|
||
<label>View</label>
|
||
<div class="seg" id="seg-view">
|
||
<button class="active" data-view="portrait">Portrait</button>
|
||
<button data-view="landscape">Landscape</button>
|
||
</div>
|
||
</div>
|
||
<div class="ctrl-group">
|
||
<label>Style</label>
|
||
<div class="seg" id="seg-style">
|
||
<button class="active" data-style="numeric">RATING: N</button>
|
||
<button data-style="compact">★ N</button>
|
||
<button data-style="stars">★★★★★</button>
|
||
</div>
|
||
</div>
|
||
<div class="ctrl-group">
|
||
<label>Position</label>
|
||
<div class="seg" id="seg-pos">
|
||
<button class="active" data-pos="top-right">Top-right</button>
|
||
<button data-pos="top-left">Top-left</button>
|
||
</div>
|
||
</div>
|
||
<div class="ctrl-group">
|
||
<label>Color</label>
|
||
<div class="swatch-row" id="swatch-row">
|
||
<button class="active" data-color="coral" style="background: #f87171;" title="coral"></button>
|
||
<button data-color="amber" style="background: #fbbf24;" title="amber"></button>
|
||
<button data-color="gradient" style="background: linear-gradient(90deg, #22d3ee, #a78bfa);" title="cyan→violet"></button>
|
||
<button data-color="cyan" style="background: #22d3ee;" title="cyan"></button>
|
||
<button data-color="pink" style="background: #f472b6;" title="pink"></button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<h2>Actress grid · current view</h2>
|
||
<div class="grid portrait" id="grid"></div>
|
||
|
||
<div class="editor">
|
||
<h3>Meta editor — set ratings</h3>
|
||
<div id="editor-rows"></div>
|
||
</div>
|
||
|
||
<h2>Detail page hero</h2>
|
||
<div class="detail">
|
||
<div class="hero">
|
||
<div class="ribbon top-right coral numeric" id="hero-ribbon">
|
||
<div class="band" data-r="5" data-stars="★★★★★"></div>
|
||
</div>
|
||
<div class="face" data-letter="V"></div>
|
||
</div>
|
||
<div class="info">
|
||
<h3><span class="female">♀</span> Vina Sky</h3>
|
||
<div style="color: var(--fg-muted); font-family: ui-monospace, monospace; font-size: 13px;">
|
||
Age 27 · 20 covers · 5 categories
|
||
</div>
|
||
<div class="meta-grid">
|
||
<div class="it"><span class="k">Ethnicity</span><span class="v">Asian</span></div>
|
||
<div class="it"><span class="k">Country</span><span class="v">USA</span></div>
|
||
<div class="it"><span class="k">Eye color</span><span class="v">Brown</span></div>
|
||
<div class="it"><span class="k">Hair color</span><span class="v">Black</span></div>
|
||
<div class="it"><span class="k">First seen</span><span class="v">2018</span></div>
|
||
<div class="it"><span class="k">Active</span><span class="v">Yes</span></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<h2>Position trade-off · with category badges</h2>
|
||
<div class="legend">
|
||
<strong>The clash.</strong> The actress card already renders category chips at <code>top-2 left-2 z-10</code> (see ActressCard.tsx:182).
|
||
Top-left ribbon overlaps them. Top-right is conflict-free.
|
||
</div>
|
||
<div class="comparison">
|
||
<div>
|
||
<div class="label bad">✗ Top-left collides with category chips</div>
|
||
<div class="card" style="max-width: 240px;">
|
||
<div class="card-portrait">
|
||
<div class="cat-badges">
|
||
<span class="cat-badge" style="color: #fbbf24; border: 1px solid #fbbf24aa;">★ Top</span>
|
||
<span class="cat-badge" style="color: #22d3ee; border: 1px solid #22d3eeaa;">◆ VIP</span>
|
||
</div>
|
||
<div class="ribbon top-left coral numeric">
|
||
<div class="band" data-r="5" data-stars="★★★★★"></div>
|
||
</div>
|
||
<div class="face" data-letter="X"></div>
|
||
</div>
|
||
<div class="card-meta">
|
||
<div class="card-name"><span class="gender">♀</span>Xoey Li</div>
|
||
<div class="card-count"><span class="play">▶</span>4</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<div class="label good">✓ Top-right keeps both visible</div>
|
||
<div class="card" style="max-width: 240px;">
|
||
<div class="card-portrait">
|
||
<div class="cat-badges">
|
||
<span class="cat-badge" style="color: #fbbf24; border: 1px solid #fbbf24aa;">★ Top</span>
|
||
<span class="cat-badge" style="color: #22d3ee; border: 1px solid #22d3eeaa;">◆ VIP</span>
|
||
</div>
|
||
<div class="ribbon top-right coral numeric">
|
||
<div class="band" data-r="5" data-stars="★★★★★"></div>
|
||
</div>
|
||
<div class="face" data-letter="X"></div>
|
||
</div>
|
||
<div class="card-meta">
|
||
<div class="card-name"><span class="gender">♀</span>Xoey Li</div>
|
||
<div class="card-count"><span class="play">▶</span>4</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<script>
|
||
// Synthetic data
|
||
const ACTRESSES = [
|
||
{ name: "Xoey Li", age: 28, count: 4, letter: "X", rating: 4 },
|
||
{ name: "Willa", age: 34, count: 1, letter: "W", rating: 0 },
|
||
{ name: "Vina Sky", age: 27, count: 20, letter: "V", rating: 5 },
|
||
{ name: "Aria Kai", age: 25, count: 12, letter: "A", rating: 3 },
|
||
{ name: "Mira Saito", age: 31, count: 7, letter: "M", rating: 0 },
|
||
{ name: "Yui Nanase", age: 24, count: 33, letter: "Y", rating: 5 },
|
||
{ name: "Elena Voss", age: 29, count: 8, letter: "E", rating: 2 },
|
||
{ name: "Luna Park", age: 26, count: 15, letter: "L", rating: 4 },
|
||
];
|
||
|
||
let state = {
|
||
view: "portrait",
|
||
style: "numeric",
|
||
pos: "top-right",
|
||
color: "coral",
|
||
};
|
||
|
||
function ribbonHTML(r) {
|
||
if (r <= 0) return "";
|
||
const stars = "★".repeat(r) + "☆".repeat(5 - r);
|
||
return `
|
||
<div class="ribbon ${state.pos} ${state.color} ${state.style}">
|
||
<div class="band" data-r="${r}" data-stars="${stars}"></div>
|
||
</div>
|
||
`;
|
||
}
|
||
|
||
function cardHTML(a) {
|
||
return `
|
||
<div class="card" data-name="${a.name}">
|
||
<div class="card-portrait">
|
||
${ribbonHTML(a.rating)}
|
||
<div class="face" data-letter="${a.letter}"></div>
|
||
</div>
|
||
<div class="card-meta">
|
||
<div class="card-name">
|
||
<span class="gender">♀</span>
|
||
<span>${a.name}</span>
|
||
</div>
|
||
<div class="card-age">${a.age} years old</div>
|
||
<div class="card-count"><span class="play">▶</span>${a.count}</div>
|
||
</div>
|
||
</div>
|
||
`;
|
||
}
|
||
|
||
function render() {
|
||
const grid = document.getElementById("grid");
|
||
grid.className = "grid " + state.view;
|
||
grid.innerHTML = ACTRESSES.map(cardHTML).join("");
|
||
// Detail hero ribbon
|
||
const hero = document.getElementById("hero-ribbon");
|
||
const heroR = ACTRESSES.find(a => a.name === "Vina Sky").rating;
|
||
if (heroR > 0) {
|
||
const stars = "★".repeat(heroR) + "☆".repeat(5 - heroR);
|
||
hero.className = `ribbon ${state.pos} ${state.color} ${state.style}`;
|
||
hero.innerHTML = `<div class="band" data-r="${heroR}" data-stars="${stars}"></div>`;
|
||
hero.style.display = "";
|
||
} else {
|
||
hero.style.display = "none";
|
||
}
|
||
// Editor rows
|
||
document.getElementById("editor-rows").innerHTML = ACTRESSES.map((a) => `
|
||
<div class="row">
|
||
<div class="lbl">${a.name}</div>
|
||
<div class="stars" data-actress="${a.name}">
|
||
${[1,2,3,4,5].map(i => `<button class="${i <= a.rating ? "on" : ""}" data-v="${i}">${i <= a.rating ? "★" : "☆"}</button>`).join("")}
|
||
<button class="clear" data-v="0">Clear</button>
|
||
</div>
|
||
</div>
|
||
`).join("");
|
||
|
||
// wire stars
|
||
document.querySelectorAll(".stars").forEach(el => {
|
||
el.addEventListener("click", (e) => {
|
||
const t = e.target.closest("button");
|
||
if (!t) return;
|
||
const v = Number(t.dataset.v);
|
||
const name = el.dataset.actress;
|
||
const a = ACTRESSES.find(x => x.name === name);
|
||
if (a) a.rating = v;
|
||
render();
|
||
});
|
||
});
|
||
}
|
||
|
||
// Wire controls
|
||
document.querySelectorAll("#seg-view button").forEach(b => b.addEventListener("click", () => {
|
||
document.querySelectorAll("#seg-view button").forEach(x => x.classList.remove("active"));
|
||
b.classList.add("active"); state.view = b.dataset.view; render();
|
||
}));
|
||
document.querySelectorAll("#seg-style button").forEach(b => b.addEventListener("click", () => {
|
||
document.querySelectorAll("#seg-style button").forEach(x => x.classList.remove("active"));
|
||
b.classList.add("active"); state.style = b.dataset.style; render();
|
||
}));
|
||
document.querySelectorAll("#seg-pos button").forEach(b => b.addEventListener("click", () => {
|
||
document.querySelectorAll("#seg-pos button").forEach(x => x.classList.remove("active"));
|
||
b.classList.add("active"); state.pos = b.dataset.pos; render();
|
||
}));
|
||
document.querySelectorAll("#swatch-row button").forEach(b => b.addEventListener("click", () => {
|
||
document.querySelectorAll("#swatch-row button").forEach(x => x.classList.remove("active"));
|
||
b.classList.add("active"); state.color = b.dataset.color; render();
|
||
}));
|
||
|
||
render();
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|