style(pet): полностью переработан вид блока «Кастомизация»

Премиальная карточка с градиентом и заголовком-иконкой; сегментные вкладки
с иконками и подсветкой активной; аксессуары — тайлы по зонам с галочкой
вместо текстовых чипов; узор — крупные превью-плитки с подписью; фон —
увеличенные карточки; плавное появление панелей.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-06-05 14:05:23 +03:00
parent 6880e1a55a
commit 7db337eccd
+80 -49
View File
@@ -319,43 +319,73 @@
/* B3 — Rainbow collar keyframe */ /* B3 — Rainbow collar keyframe */
@keyframes rbRot { to { transform:rotate(360deg); } } @keyframes rbRot { to { transform:rotate(360deg); } }
/* ── Customize panel (аксессуары / цвет / фон) ── */ /* ── Customize panel (полностью переработанный вид) ── */
.pet-customize { margin-bottom:18px; } .pet-customize { background:linear-gradient(165deg,rgba(155,93,229,.10),rgba(6,214,224,.045)),var(--surface);
.pc-tabs { display:flex; gap:6px; margin:4px 0 14px; flex-wrap:wrap; } border:1.5px solid rgba(155,93,229,.2); border-radius:20px; padding:16px 18px 20px; margin-bottom:18px; }
.pc-tab { padding:7px 16px; border-radius:99px; border:1.5px solid var(--border-h); background:transparent; .pc-head { display:flex; align-items:center; gap:11px; margin-bottom:15px; }
color:var(--text-2); font:700 .78rem 'Manrope',sans-serif; cursor:pointer; transition:all .15s; } .pc-head-ico { width:34px; height:34px; border-radius:11px; flex-shrink:0; display:flex; align-items:center; justify-content:center;
.pc-tab:hover { border-color:var(--violet); color:var(--text); } background:linear-gradient(135deg,rgba(155,93,229,.3),rgba(6,214,224,.2)); color:#c9a6ff; }
.pc-tab.active { background:var(--violet); border-color:var(--violet); color:#fff; } .pc-head-ico svg { width:17px; height:17px; }
.pc-hint { font-size:.72rem; color:var(--text-3); margin-bottom:11px; line-height:1.5; } .pc-head-title { font-family:'Unbounded',sans-serif; font-size:.92rem; font-weight:800; line-height:1.1; }
.pc-panel .pet-color-picker { display:flex; gap:9px; flex-wrap:wrap; } .pc-head-sub { font-size:.68rem; color:var(--text-3); margin-top:2px; }
.pc-panel .pet-color-dot { width:30px; height:30px; } .pc-tabs { display:flex; gap:4px; padding:4px; background:rgba(0,0,0,.2); border-radius:13px; margin-bottom:16px; }
.pc-bg-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(118px,1fr)); gap:10px; } .pc-tab { flex:1; display:inline-flex; align-items:center; justify-content:center; gap:6px; padding:9px 6px; border:none;
border-radius:9px; background:transparent; color:var(--text-2); font:700 .76rem 'Manrope',sans-serif; cursor:pointer; transition:all .18s; }
.pc-tab svg { width:14px; height:14px; }
.pc-tab:hover { color:var(--text); background:rgba(255,255,255,.05); }
.pc-tab.active { background:var(--violet); color:#fff; box-shadow:0 5px 16px rgba(155,93,229,.45); }
.pc-hint { font-size:.72rem; color:var(--text-3); margin-bottom:13px; line-height:1.5; }
.pc-panel { animation:pcFade .25s ease; }
@keyframes pcFade { from{opacity:0;transform:translateY(5px)} to{opacity:1;transform:translateY(0)} }
.pet-evo-legend { font-size:.6rem; color:var(--text-3); margin-top:7px; line-height:1.45; text-align:center; .pet-evo-legend { font-size:.6rem; color:var(--text-3); margin-top:7px; line-height:1.45; text-align:center;
cursor:help; max-width:230px; } cursor:help; max-width:230px; }
/* Гардероб: панель действий + зоны */
.wr-bar { display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:12px; flex-wrap:wrap; } /* Гардероб по зонам */
.wr-bar { display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:4px; flex-wrap:wrap; }
.wr-count { font-size:.74rem; color:var(--text-2); font-weight:700; } .wr-count { font-size:.74rem; color:var(--text-2); font-weight:700; }
.wr-count b { color:var(--violet); } .wr-count b { color:#c9a6ff; }
.wr-actions { display:flex; gap:7px; flex-wrap:wrap; } .wr-actions { display:flex; gap:7px; flex-wrap:wrap; }
.wr-btn { padding:5px 12px; border-radius:99px; border:1.5px solid var(--border-h); background:transparent; .wr-btn { display:inline-flex; align-items:center; gap:5px; padding:6px 13px; border-radius:99px; border:1.5px solid var(--border-h);
color:var(--text-2); font:700 .72rem 'Manrope',sans-serif; cursor:pointer; transition:all .15s; } background:rgba(255,255,255,.03); color:var(--text-2); font:700 .72rem 'Manrope',sans-serif; cursor:pointer; transition:all .15s; }
.wr-btn:hover { border-color:var(--violet); color:var(--text); } .wr-btn:hover { border-color:var(--violet); color:var(--text); }
.wr-zone { margin-bottom:11px; } .wr-zone { display:flex; align-items:flex-start; gap:12px; padding:10px 0; border-bottom:1px solid rgba(255,255,255,.06); }
.wr-zone-lbl { font-size:.6rem; font-weight:800; color:var(--text-3); text-transform:uppercase; letter-spacing:.06em; margin-bottom:6px; } .wr-zone:last-child { border-bottom:none; }
.wr-chips { display:flex; flex-wrap:wrap; gap:7px; } .wr-zone-lbl { width:60px; flex-shrink:0; padding-top:8px; font-size:.62rem; font-weight:800; color:var(--text-3);
/* Узор: свотчи */ text-transform:uppercase; letter-spacing:.05em; }
.pc-pattern-grid { display:flex; flex-wrap:wrap; gap:8px; } .wr-chips { display:flex; flex-wrap:wrap; gap:7px; flex:1; }
.pc-swatch { display:inline-flex; align-items:center; gap:7px; padding:6px 12px 6px 6px; border-radius:99px; .wr-tile { display:inline-flex; align-items:center; gap:6px; padding:7px 13px; border-radius:12px; border:1.5px solid var(--border-h);
border:1.5px solid var(--border-h); background:transparent; color:var(--text-2); background:rgba(255,255,255,.03); color:var(--text-2); font:600 .76rem 'Manrope',sans-serif; cursor:pointer; transition:all .15s; }
font:700 .76rem 'Manrope',sans-serif; cursor:pointer; transition:all .15s; } .wr-tile svg { width:12px; height:12px; flex-shrink:0; }
.pc-swatch:hover { border-color:var(--violet); color:var(--text); } .wr-tile:hover:not(.locked) { border-color:var(--violet); color:var(--text); transform:translateY(-1px); }
.pc-swatch.active { border-color:var(--violet); background:rgba(155,93,229,.18); color:#fff; } .wr-tile.on { border-color:var(--violet); background:rgba(155,93,229,.22); color:#fff; }
.pc-swatch-dot { width:24px; height:24px; border-radius:50%; flex-shrink:0; border:1.5px solid rgba(255,255,255,.18); } .wr-tile.on svg { color:#c9a6ff; }
.wr-tile.locked { opacity:.5; cursor:not-allowed; }
.wr-tile .wr-hint { font-size:.62rem; color:var(--text-3); }
/* Цвет */
.pc-panel .pet-color-picker { display:flex; gap:13px; flex-wrap:wrap; }
.pc-panel .pet-color-dot { width:36px; height:36px; border-width:3px; }
.pc-panel .pet-color-dot.active { box-shadow:0 0 0 3px rgba(155,93,229,.5); }
/* Узор — превью-плитки */
.pc-pattern-grid { display:flex; flex-wrap:wrap; gap:10px; }
.pc-swatch { display:flex; flex-direction:column; align-items:center; gap:7px; width:80px; padding:9px 6px; border-radius:14px;
border:1.5px solid var(--border-h); background:rgba(255,255,255,.03); color:var(--text-2); cursor:pointer; transition:all .15s; }
.pc-swatch:hover { border-color:var(--violet); transform:translateY(-2px); }
.pc-swatch.active { border-color:var(--violet); background:rgba(155,93,229,.18); }
.pc-swatch-name { font:700 .68rem 'Manrope',sans-serif; }
.pc-swatch.active .pc-swatch-name { color:#fff; }
.pc-swatch-dot { width:48px; height:48px; border-radius:13px; flex-shrink:0; border:1.5px solid rgba(255,255,255,.18); }
.pc-swatch-dot.pat-none { background:#9B5DE5; } .pc-swatch-dot.pat-none { background:#9B5DE5; }
.pc-swatch-dot.pat-spots { background:radial-gradient(circle at 32% 32%,#5a2da0 2.2px,transparent 2.4px),radial-gradient(circle at 70% 66%,#5a2da0 2.2px,transparent 2.4px),#9B5DE5; } .pc-swatch-dot.pat-spots { background:radial-gradient(circle at 32% 32%,#5a2da0 3px,transparent 3.2px),radial-gradient(circle at 70% 66%,#5a2da0 3px,transparent 3.2px),radial-gradient(circle at 45% 80%,#5a2da0 2.6px,transparent 2.8px),#9B5DE5; }
.pc-swatch-dot.pat-stripes { background:repeating-linear-gradient(45deg,#9B5DE5 0 4px,#5a2da0 4px 7px); } .pc-swatch-dot.pat-stripes { background:repeating-linear-gradient(45deg,#9B5DE5 0 5px,#5a2da0 5px 9px); }
.pc-swatch-dot.pat-gradient{ background:linear-gradient(180deg,#c9a6ec,#5a2da0); } .pc-swatch-dot.pat-gradient{ background:linear-gradient(180deg,#c9a6ec,#4a2398); }
.pc-swatch-dot.pat-galaxy { background:radial-gradient(circle at 62% 40%,#1a0a3a 55%,#9B5DE5); } .pc-swatch-dot.pat-galaxy { background:radial-gradient(circle at 62% 38%,#1a0a3a 50%,#9B5DE5); }
/* Фон — превью-карточки крупнее */
.pc-bg-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(124px,1fr)); gap:11px; }
.pc-bg-grid .pet-bg-card { border-radius:14px; }
.pc-bg-grid .pet-bg-preview { height:76px; }
@media(max-width:768px) { @media(max-width:768px) {
.pet-hero { grid-template-columns:1fr; } .pet-hero { grid-template-columns:1fr; }
@@ -508,13 +538,19 @@
</div> </div>
<!-- ── Кастомизация ── --> <!-- ── Кастомизация ── -->
<div class="pet-card pet-customize"> <div class="pet-customize">
<div class="pet-card-title"><i data-lucide="palette" width="12" height="12"></i> Кастомизация</div> <div class="pc-head">
<div class="pc-head-ico"><i data-lucide="palette"></i></div>
<div>
<div class="pc-head-title">Кастомизация</div>
<div class="pc-head-sub">Наряди питомца: аксессуары, цвет, узор и фон</div>
</div>
</div>
<div class="pc-tabs"> <div class="pc-tabs">
<button class="pc-tab active" data-tab="acc" type="button">Аксессуары</button> <button class="pc-tab active" data-tab="acc" type="button"><i data-lucide="shirt"></i> Аксессуары</button>
<button class="pc-tab" data-tab="color" type="button">Цвет</button> <button class="pc-tab" data-tab="color" type="button"><i data-lucide="droplet"></i> Цвет</button>
<button class="pc-tab" data-tab="pattern" type="button">Узор</button> <button class="pc-tab" data-tab="pattern" type="button"><i data-lucide="grid-2x2"></i> Узор</button>
<button class="pc-tab" data-tab="bg" type="button">Фон</button> <button class="pc-tab" data-tab="bg" type="button"><i data-lucide="image"></i> Фон</button>
</div> </div>
<div class="pc-panel" id="pc-acc"> <div class="pc-panel" id="pc-acc">
<div class="pc-hint">Нажми, чтобы надеть или снять. Заблокированные открываются за достижения. По одному предмету на зону (голова / лицо / шея / уши / акцент).</div> <div class="pc-hint">Нажми, чтобы надеть или снять. Заблокированные открываются за достижения. По одному предмету на зону (голова / лицо / шея / уши / акцент).</div>
@@ -1257,18 +1293,13 @@ async function selectColor(colorKey) {
} }
/* ── Гардероб (выбор аксессуаров, по зонам) ── */ /* ── Гардероб (выбор аксессуаров, по зонам) ── */
const LOCK_ICO = '<svg class="ic" viewBox="0 0 24 24" style="width:11px;height:11px;flex-shrink:0"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>'; const LOCK_ICO = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>';
const CHECK_ICO = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>';
const ZONE_LABELS = { head:'Голова', face:'Лицо', neck:'Шея', ears:'Уши', accent:'Акцент' }; const ZONE_LABELS = { head:'Голова', face:'Лицо', neck:'Шея', ears:'Уши', accent:'Акцент' };
function wearChip(it) { function wearChip(it) {
const base = 'display:inline-flex;align-items:center;gap:5px;padding:6px 11px;border-radius:99px;font:600 .74rem Manrope,sans-serif;border:1.5px solid;transition:all .15s;user-select:none;'; if (it.locked)
const style = it.locked return `<span class="wr-tile locked" title="Откроется: ${escHtml(it.hint)}">${LOCK_ICO}${escHtml(it.name)}${it.hint ? ` <span class="wr-hint">${escHtml(it.hint)}</span>` : ''}</span>`;
? base + 'border-color:rgba(255,255,255,.1);color:var(--text-3);background:transparent;cursor:not-allowed;opacity:.6' return `<span class="wr-tile tgl${it.equipped ? ' on' : ''}" data-id="${it.id}" title="${it.equipped ? 'Снять' : 'Надеть'}">${it.equipped ? CHECK_ICO : ''}${escHtml(it.name)}</span>`;
: it.equipped
? base + 'border-color:var(--violet);color:#fff;background:rgba(155,93,229,.22);cursor:pointer'
: base + 'border-color:var(--border-h);color:var(--text-2);background:transparent;cursor:pointer';
const title = it.locked ? `Откроется: ${it.hint}` : (it.equipped ? 'Снять' : 'Надеть');
const tail = it.locked && it.hint ? ` · ${it.hint}` : '';
return `<span class="pet-wear${it.locked?'':' tgl'}" data-id="${it.id}" title="${title}" style="${style}">${it.locked?LOCK_ICO:''}${escHtml(it.name)}${tail}</span>`;
} }
function renderWardrobe(items) { function renderWardrobe(items) {
const el = document.getElementById('pet-accessories'); const el = document.getElementById('pet-accessories');
@@ -1287,7 +1318,7 @@ function renderWardrobe(items) {
html += `<div class="wr-zone"><div class="wr-zone-lbl">${ZONE_LABELS[z]||z}</div><div class="wr-chips">${zi.map(wearChip).join('')}</div></div>`; html += `<div class="wr-zone"><div class="wr-zone-lbl">${ZONE_LABELS[z]||z}</div><div class="wr-chips">${zi.map(wearChip).join('')}</div></div>`;
}); });
el.innerHTML = html; el.innerHTML = html;
el.querySelectorAll('.pet-wear.tgl').forEach(ch => ch.addEventListener('click', () => toggleEquip(ch.dataset.id))); el.querySelectorAll('.wr-tile.tgl').forEach(ch => ch.addEventListener('click', () => toggleEquip(ch.dataset.id)));
document.getElementById('wr-clear')?.addEventListener('click', () => setEquipped([])); document.getElementById('wr-clear')?.addEventListener('click', () => setEquipped([]));
document.getElementById('wr-random')?.addEventListener('click', randomLook); document.getElementById('wr-random')?.addEventListener('click', randomLook);
} }
@@ -1327,7 +1358,7 @@ function renderPatternPicker(list, current) {
if (!el) return; if (!el) return;
el.innerHTML = (list || []).map(p => { el.innerHTML = (list || []).map(p => {
const on = p.id === current; const on = p.id === current;
return `<button type="button" class="pc-swatch${on?' active':''}" data-pat="${p.id}"><span class="pc-swatch-dot pat-${p.id}"></span>${escHtml(p.name)}</button>`; return `<button type="button" class="pc-swatch${on?' active':''}" data-pat="${p.id}"><span class="pc-swatch-dot pat-${p.id}"></span><span class="pc-swatch-name">${escHtml(p.name)}</span></button>`;
}).join(''); }).join('');
el.querySelectorAll('.pc-swatch').forEach(b => b.addEventListener('click', () => applyPattern(b.dataset.pat))); el.querySelectorAll('.pc-swatch').forEach(b => b.addEventListener('click', () => applyPattern(b.dataset.pat)));
} }