123
This commit is contained in:
272
public/game.js
272
public/game.js
@ -883,6 +883,8 @@
|
|||||||
function bindGameEvents(state) {
|
function bindGameEvents(state) {
|
||||||
const you = state.players[state.yourIndex];
|
const you = state.players[state.yourIndex];
|
||||||
const isYourTurn = state.currentPlayerIndex === state.yourIndex;
|
const isYourTurn = state.currentPlayerIndex === state.yourIndex;
|
||||||
|
const sidebar = $('forge-sidebar');
|
||||||
|
const isForgeOpen = sidebar && !sidebar.classList.contains('hidden');
|
||||||
|
|
||||||
$all('.card-wrap.in-hand').forEach((wrap) => {
|
$all('.card-wrap.in-hand').forEach((wrap) => {
|
||||||
wrap.classList.toggle('disabled', !isYourTurn);
|
wrap.classList.toggle('disabled', !isYourTurn);
|
||||||
@ -891,7 +893,18 @@
|
|||||||
const isMinion = meta && meta.type === 'minion';
|
const isMinion = meta && meta.type === 'minion';
|
||||||
const canPlay = isYourTurn && !attackMode.active && !heroAbilityMode.active && meta && you.mana >= (meta.cost || 0);
|
const canPlay = isYourTurn && !attackMode.active && !heroAbilityMode.active && meta && you.mana >= (meta.cost || 0);
|
||||||
|
|
||||||
if (isMinion && canPlay && (you.board?.length ?? 0) < 7) {
|
// Если кузница открыта и карта - миньон, делаем её перетаскиваемой для кузницы
|
||||||
|
if (isForgeOpen && isMinion) {
|
||||||
|
wrap.draggable = true;
|
||||||
|
wrap.ondragstart = function (e) {
|
||||||
|
e.dataTransfer.setData('text/plain', 'hand:' + handIndex);
|
||||||
|
e.dataTransfer.setData('source', 'hand');
|
||||||
|
wrap.classList.add('dragging');
|
||||||
|
};
|
||||||
|
wrap.ondragend = function () {
|
||||||
|
wrap.classList.remove('dragging');
|
||||||
|
};
|
||||||
|
} else if (isMinion && canPlay && (you.board?.length ?? 0) < 7) {
|
||||||
wrap.draggable = true;
|
wrap.draggable = true;
|
||||||
wrap.ondragstart = function (e) {
|
wrap.ondragstart = function (e) {
|
||||||
if (!canPlay) return;
|
if (!canPlay) return;
|
||||||
@ -1420,8 +1433,12 @@
|
|||||||
forgeBtn.disabled = false;
|
forgeBtn.disabled = false;
|
||||||
forgeBtn.onclick = function () {
|
forgeBtn.onclick = function () {
|
||||||
if (attackMode.active || spellMode.active || heroAbilityMode.active) return;
|
if (attackMode.active || spellMode.active || heroAbilityMode.active) return;
|
||||||
$('forge-overlay')?.classList.remove('hidden');
|
const sidebar = $('forge-sidebar');
|
||||||
|
if (sidebar) {
|
||||||
|
sidebar.classList.remove('hidden');
|
||||||
renderForgeDeck(state);
|
renderForgeDeck(state);
|
||||||
|
setupForgeDragAndDrop(state);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} else if (forgeBtn) {
|
} else if (forgeBtn) {
|
||||||
forgeBtn.disabled = true;
|
forgeBtn.disabled = true;
|
||||||
@ -1597,6 +1614,12 @@
|
|||||||
yourBoardEl.ondragleave = null;
|
yourBoardEl.ondragleave = null;
|
||||||
yourBoardEl.ondrop = null;
|
yourBoardEl.ondrop = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Настраиваем drag-and-drop для кузницы, если она открыта
|
||||||
|
const sidebar = $('forge-sidebar');
|
||||||
|
if (sidebar && !sidebar.classList.contains('hidden')) {
|
||||||
|
setTimeout(() => setupForgeDragAndDrop(state), 100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function initLobby() {
|
function initLobby() {
|
||||||
@ -1864,12 +1887,15 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
$('btn-forge-close')?.addEventListener('click', () => {
|
$('btn-forge-close')?.addEventListener('click', () => {
|
||||||
$('forge-overlay')?.classList.add('hidden');
|
const sidebar = $('forge-sidebar');
|
||||||
});
|
if (sidebar) {
|
||||||
|
sidebar.classList.add('hidden');
|
||||||
$('forge-overlay')?.addEventListener('click', (e) => {
|
forgeSelected = [];
|
||||||
if (e.target.id === 'forge-overlay') {
|
renderForgeSelected();
|
||||||
$('forge-overlay')?.classList.add('hidden');
|
// Обновляем отображение руки и колоды
|
||||||
|
if (gameState) {
|
||||||
|
renderHand(gameState);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2024,22 +2050,207 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
let forgeSelected = [];
|
let forgeSelected = [];
|
||||||
|
|
||||||
|
function renderForgeSelected() {
|
||||||
|
const selectedEl = $('forge-selected');
|
||||||
|
if (!selectedEl) return;
|
||||||
|
|
||||||
|
if (forgeSelected.length === 0) {
|
||||||
|
selectedEl.innerHTML = '<div class="forge-selected-empty">Перетащите карты сюда</div>';
|
||||||
|
selectedEl.classList.remove('drag-over');
|
||||||
|
} else {
|
||||||
|
selectedEl.innerHTML = forgeSelected.map((cardId, idx) => {
|
||||||
|
const meta = cardDb[cardId];
|
||||||
|
if (!meta) return '';
|
||||||
|
return `<div class="card-wrap forge-selected-card" data-card-id="${cardId}" data-forge-index="${idx}" style="width: 80px; height: 112px; position: relative;">
|
||||||
|
<div class="card faction-${meta.faction || 'neutral'}">
|
||||||
|
<div class="card-art">${getCardArt(meta)}</div>
|
||||||
|
<div class="card-info">
|
||||||
|
<div class="card-name" style="font-size: 0.6rem;">${escapeHtml(meta.name)}</div>
|
||||||
|
${meta.type === 'minion' ? `<div class="card-stats"><span class="atk">${meta.attack || 0}</span><span class="hp">${meta.health || 0}</span></div>` : ''}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
|
}).filter(Boolean).join('');
|
||||||
|
|
||||||
|
// Добавляем обработчики удаления
|
||||||
|
$all('.forge-selected-card').forEach(card => {
|
||||||
|
card.onclick = function(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
const cardId = card.dataset.cardId;
|
||||||
|
const idx = forgeSelected.indexOf(cardId);
|
||||||
|
if (idx >= 0) {
|
||||||
|
forgeSelected.splice(idx, 1);
|
||||||
|
renderForgeSelected();
|
||||||
|
updateForgeCraftButton();
|
||||||
|
// Обновляем отображение в источнике
|
||||||
|
if (gameState) {
|
||||||
|
renderForgeDeck(gameState);
|
||||||
|
renderHand(gameState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateForgeCraftButton() {
|
||||||
|
const craftBtn = $('btn-forge-craft');
|
||||||
|
const you = gameState?.players?.[gameState?.yourIndex];
|
||||||
|
if (craftBtn && you) {
|
||||||
|
craftBtn.disabled = forgeSelected.length < 2 || forgeSelected.length > 3 || (you.mana || 0) < 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addCardToForge(cardId, source) {
|
||||||
|
if (forgeSelected.includes(cardId)) return; // Уже добавлена
|
||||||
|
if (forgeSelected.length >= 3) return; // Максимум 3 карты
|
||||||
|
|
||||||
|
const meta = cardDb[cardId];
|
||||||
|
if (!meta || meta.type !== 'minion') return; // Только миньоны
|
||||||
|
|
||||||
|
forgeSelected.push(cardId);
|
||||||
|
renderForgeSelected();
|
||||||
|
updateForgeCraftButton();
|
||||||
|
|
||||||
|
// Обновляем отображение в источнике (рука или колода)
|
||||||
|
if (gameState) {
|
||||||
|
if (source === 'hand') {
|
||||||
|
renderHand(gameState);
|
||||||
|
} else if (source === 'deck') {
|
||||||
|
renderForgeDeck(gameState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupForgeDragAndDrop(state) {
|
||||||
|
const selectedEl = $('forge-selected');
|
||||||
|
const sidebar = $('forge-sidebar');
|
||||||
|
if (!selectedEl || !sidebar || sidebar.classList.contains('hidden')) return;
|
||||||
|
|
||||||
|
// Обработка drop в область выбранных карт
|
||||||
|
const handleDragOver = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
selectedEl.classList.add('drag-over');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDragLeave = (e) => {
|
||||||
|
if (!selectedEl.contains(e.relatedTarget)) {
|
||||||
|
selectedEl.classList.remove('drag-over');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDrop = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
selectedEl.classList.remove('drag-over');
|
||||||
|
|
||||||
|
let cardId = null;
|
||||||
|
let source = null;
|
||||||
|
|
||||||
|
// Проверяем данные из dataTransfer
|
||||||
|
const data = e.dataTransfer.getData('text/plain');
|
||||||
|
if (data) {
|
||||||
|
if (data.startsWith('hand:')) {
|
||||||
|
const handIndex = parseInt(data.split(':')[1], 10);
|
||||||
|
const you = state.players[state.yourIndex];
|
||||||
|
if (you.hand && you.hand[handIndex]) {
|
||||||
|
cardId = you.hand[handIndex];
|
||||||
|
source = 'hand';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cardId = data;
|
||||||
|
source = e.dataTransfer.getData('source') || 'deck';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cardId) {
|
||||||
|
addCardToForge(cardId, source);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Удаляем старые обработчики, если есть
|
||||||
|
selectedEl.removeEventListener('dragover', handleDragOver);
|
||||||
|
selectedEl.removeEventListener('dragleave', handleDragLeave);
|
||||||
|
selectedEl.removeEventListener('drop', handleDrop);
|
||||||
|
|
||||||
|
// Добавляем новые обработчики
|
||||||
|
selectedEl.addEventListener('dragover', handleDragOver);
|
||||||
|
selectedEl.addEventListener('dragleave', handleDragLeave);
|
||||||
|
selectedEl.addEventListener('drop', handleDrop);
|
||||||
|
|
||||||
|
// Делаем карты в руке перетаскиваемыми в кузницу
|
||||||
|
$all('#your-hand .card-wrap').forEach(cardWrap => {
|
||||||
|
const cardId = cardWrap.dataset.cardId;
|
||||||
|
const meta = cardDb[cardId];
|
||||||
|
if (cardId && meta && meta.type === 'minion') {
|
||||||
|
// Сохраняем оригинальный draggable, если он был
|
||||||
|
const originalDraggable = cardWrap.draggable;
|
||||||
|
const originalOndragstart = cardWrap.ondragstart;
|
||||||
|
|
||||||
|
// Добавляем дополнительный обработчик для кузницы
|
||||||
|
const forgeDragStart = (e) => {
|
||||||
|
// Проверяем, открыта ли кузница
|
||||||
|
if (sidebar && !sidebar.classList.contains('hidden')) {
|
||||||
|
e.dataTransfer.setData('text/plain', cardId);
|
||||||
|
e.dataTransfer.setData('source', 'hand');
|
||||||
|
cardWrap.classList.add('dragging');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
cardWrap.addEventListener('dragstart', forgeDragStart);
|
||||||
|
|
||||||
|
// Сохраняем ссылку для последующего удаления
|
||||||
|
cardWrap._forgeDragStart = forgeDragStart;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Делаем карты в колоде перетаскиваемыми
|
||||||
|
$all('.forge-deck-card').forEach(cardWrap => {
|
||||||
|
const cardId = cardWrap.dataset.cardId;
|
||||||
|
if (cardId) {
|
||||||
|
cardWrap.draggable = true;
|
||||||
|
|
||||||
|
const deckDragStart = (e) => {
|
||||||
|
e.dataTransfer.setData('text/plain', cardId);
|
||||||
|
e.dataTransfer.setData('source', 'deck');
|
||||||
|
cardWrap.classList.add('dragging');
|
||||||
|
};
|
||||||
|
|
||||||
|
const deckDragEnd = () => {
|
||||||
|
cardWrap.classList.remove('dragging');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Удаляем старые обработчики
|
||||||
|
cardWrap.removeEventListener('dragstart', cardWrap._deckDragStart);
|
||||||
|
cardWrap.removeEventListener('dragend', cardWrap._deckDragEnd);
|
||||||
|
|
||||||
|
// Добавляем новые
|
||||||
|
cardWrap.addEventListener('dragstart', deckDragStart);
|
||||||
|
cardWrap.addEventListener('dragend', deckDragEnd);
|
||||||
|
|
||||||
|
// Сохраняем ссылки
|
||||||
|
cardWrap._deckDragStart = deckDragStart;
|
||||||
|
cardWrap._deckDragEnd = deckDragEnd;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function renderForgeDeck(state) {
|
function renderForgeDeck(state) {
|
||||||
const you = state.players[state.yourIndex];
|
const you = state.players[state.yourIndex];
|
||||||
const deckList = $('forge-deck-list');
|
const deckList = $('forge-deck-list');
|
||||||
const selectedEl = $('forge-selected');
|
if (!deckList) return;
|
||||||
const craftBtn = $('btn-forge-craft');
|
|
||||||
if (!deckList || !selectedEl) return;
|
|
||||||
|
|
||||||
deckList.innerHTML = you.deck.map((cardId, idx) => {
|
deckList.innerHTML = you.deck.map((cardId, idx) => {
|
||||||
const meta = cardDb[cardId];
|
const meta = cardDb[cardId];
|
||||||
if (!meta || meta.type !== 'minion') return '';
|
if (!meta || meta.type !== 'minion') return '';
|
||||||
const isSelected = forgeSelected.includes(cardId);
|
const isSelected = forgeSelected.includes(cardId);
|
||||||
return `<div class="card-wrap forge-deck-card ${isSelected ? 'selected' : ''}" data-card-id="${cardId}" data-deck-index="${idx}" style="width: 100px; height: 140px; cursor: pointer;">
|
return `<div class="card-wrap forge-deck-card ${isSelected ? 'selected' : ''}" data-card-id="${cardId}" data-deck-index="${idx}" draggable="true" style="width: 90px; height: 126px; cursor: grab;">
|
||||||
<div class="card faction-${meta.faction || 'neutral'}">
|
<div class="card faction-${meta.faction || 'neutral'}">
|
||||||
<div class="card-art">${getCardArt(meta)}</div>
|
<div class="card-art">${getCardArt(meta)}</div>
|
||||||
<div class="card-info">
|
<div class="card-info">
|
||||||
<div class="card-name" style="font-size: 0.7rem;">${escapeHtml(meta.name)}</div>
|
<div class="card-name" style="font-size: 0.65rem;">${escapeHtml(meta.name)}</div>
|
||||||
<div class="card-stats">
|
<div class="card-stats">
|
||||||
<span class="atk">${meta.attack || 0}</span>
|
<span class="atk">${meta.attack || 0}</span>
|
||||||
<span class="hp">${meta.health || 0}</span>
|
<span class="hp">${meta.health || 0}</span>
|
||||||
@ -2049,33 +2260,40 @@
|
|||||||
</div>`;
|
</div>`;
|
||||||
}).filter(Boolean).join('');
|
}).filter(Boolean).join('');
|
||||||
|
|
||||||
|
// Клик по карте в колоде тоже добавляет её
|
||||||
$all('.forge-deck-card').forEach(card => {
|
$all('.forge-deck-card').forEach(card => {
|
||||||
card.onclick = function() {
|
card.onclick = function() {
|
||||||
const cardId = card.dataset.cardId;
|
const cardId = card.dataset.cardId;
|
||||||
const idx = forgeSelected.indexOf(cardId);
|
addCardToForge(cardId, 'deck');
|
||||||
if (idx >= 0) {
|
|
||||||
forgeSelected.splice(idx, 1);
|
|
||||||
} else if (forgeSelected.length < 3) {
|
|
||||||
forgeSelected.push(cardId);
|
|
||||||
}
|
|
||||||
renderForgeDeck(state);
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
selectedEl.innerHTML = forgeSelected.length ? forgeSelected.map(cardId => {
|
renderForgeSelected();
|
||||||
const meta = cardDb[cardId];
|
updateForgeCraftButton();
|
||||||
return `<div class="card-wrap" style="width: 80px; height: 112px;"><div class="card faction-${meta.faction || 'neutral'}"><div class="card-art">${getCardArt(meta)}</div><div class="card-info"><div class="card-name" style="font-size: 0.6rem;">${escapeHtml(meta.name)}</div></div></div></div>`;
|
|
||||||
}).join('') : '<div class="forge-selected-empty">Выберите 2-3 карты</div>';
|
|
||||||
|
|
||||||
|
// Настраиваем drag-and-drop после рендеринга
|
||||||
|
setTimeout(() => setupForgeDragAndDrop(state), 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Обновляем drag-and-drop при каждом обновлении руки, если кузница открыта
|
||||||
|
// Это делается в bindGameEvents
|
||||||
|
|
||||||
|
// Обработчик создания улучшенной карты
|
||||||
|
const craftBtn = $('btn-forge-craft');
|
||||||
if (craftBtn) {
|
if (craftBtn) {
|
||||||
craftBtn.disabled = forgeSelected.length < 2 || forgeSelected.length > 3 || (you.mana || 0) < 2;
|
|
||||||
craftBtn.onclick = function() {
|
craftBtn.onclick = function() {
|
||||||
if (craftBtn.disabled) return;
|
if (craftBtn.disabled) return;
|
||||||
|
const you = gameState?.players?.[gameState?.yourIndex];
|
||||||
|
if (!you || forgeSelected.length < 2 || forgeSelected.length > 3 || (you.mana || 0) < 2) return;
|
||||||
|
|
||||||
socket.emit('forgeCard', { cardIds: forgeSelected });
|
socket.emit('forgeCard', { cardIds: forgeSelected });
|
||||||
forgeSelected = [];
|
forgeSelected = [];
|
||||||
$('forge-overlay')?.classList.add('hidden');
|
renderForgeSelected();
|
||||||
};
|
const sidebar = $('forge-sidebar');
|
||||||
|
if (sidebar) {
|
||||||
|
sidebar.classList.add('hidden');
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
$('music-toggle')?.addEventListener('click', () => {
|
$('music-toggle')?.addEventListener('click', () => {
|
||||||
|
|||||||
@ -241,16 +241,21 @@
|
|||||||
<p>Выберите цель для геройской способности (1 урон)</p>
|
<p>Выберите цель для геройской способности (1 урон)</p>
|
||||||
<button type="button" id="btn-cancel-hero" class="btn btn-ghost">Отмена</button>
|
<button type="button" id="btn-cancel-hero" class="btn btn-ghost">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="forge-overlay" class="modal-overlay hidden">
|
<div id="forge-sidebar" class="forge-sidebar hidden">
|
||||||
<div class="modal forge-modal">
|
<div class="forge-sidebar-header">
|
||||||
<h2>⚒ Звёздная кузница</h2>
|
<h2>⚒ Звёздная кузница</h2>
|
||||||
<p class="hint" style="font-size: 0.85rem; margin-bottom: 1rem;">Выберите 2-3 карты из колоды для улучшения</p>
|
<button type="button" id="btn-forge-close" class="btn-forge-close" title="Закрыть">×</button>
|
||||||
|
</div>
|
||||||
|
<p class="forge-hint">Перетащите 2-3 карты из руки или колоды сюда</p>
|
||||||
|
<div id="forge-selected" class="forge-selected">
|
||||||
|
<div class="forge-selected-empty">Перетащите карты сюда</div>
|
||||||
|
</div>
|
||||||
|
<div class="forge-deck-section">
|
||||||
|
<h3>Карты из колоды:</h3>
|
||||||
<div id="forge-deck-list" class="forge-deck-list"></div>
|
<div id="forge-deck-list" class="forge-deck-list"></div>
|
||||||
<div id="forge-selected" class="forge-selected"></div>
|
</div>
|
||||||
<div class="forge-actions">
|
<div class="forge-actions">
|
||||||
<button type="button" id="btn-forge-craft" class="btn btn-primary" disabled>Создать улучшенную карту</button>
|
<button type="button" id="btn-forge-craft" class="btn btn-primary" disabled>Создать улучшенную карту</button>
|
||||||
<button type="button" id="btn-forge-close" class="btn btn-ghost">Закрыть</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="card-info-overlay" class="modal-overlay hidden">
|
<div id="card-info-overlay" class="modal-overlay hidden">
|
||||||
|
|||||||
@ -1324,34 +1324,129 @@ html, body {
|
|||||||
.card-info-modal .card-info-abilities { font-size: 0.85rem; color: var(--amber); margin-bottom: 0.5rem; }
|
.card-info-modal .card-info-abilities { font-size: 0.85rem; color: var(--amber); margin-bottom: 0.5rem; }
|
||||||
.card-info-modal .card-info-bio { font-size: 0.8rem; color: #94a3b8; line-height: 1.4; margin-top: 0.75rem; padding-top: 0.75rem; border-top: 1px solid rgba(148,163,184,0.3); }
|
.card-info-modal .card-info-bio { font-size: 0.8rem; color: #94a3b8; line-height: 1.4; margin-top: 0.75rem; padding-top: 0.75rem; border-top: 1px solid rgba(148,163,184,0.3); }
|
||||||
.card-info-modal .hidden { display: none !important; }
|
.card-info-modal .hidden { display: none !important; }
|
||||||
.forge-modal {
|
/* Forge Sidebar */
|
||||||
max-width: 700px;
|
.forge-sidebar {
|
||||||
max-height: 90vh;
|
position: fixed;
|
||||||
text-align: left;
|
top: 0;
|
||||||
z-index: 600;
|
right: 0;
|
||||||
overflow-y: auto;
|
width: 400px;
|
||||||
|
max-width: 90vw;
|
||||||
|
height: 100vh;
|
||||||
|
background: linear-gradient(145deg, #2d2a22 0%, #1a1814 100%);
|
||||||
|
border-left: 3px solid var(--gold);
|
||||||
|
box-shadow: -5px 0 30px rgba(0,0,0,0.8);
|
||||||
|
z-index: 200;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
transform: translateX(100%);
|
||||||
|
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.forge-sidebar:not(.hidden) {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
.forge-sidebar.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.forge-sidebar-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 1.5rem;
|
||||||
|
border-bottom: 2px solid var(--gold);
|
||||||
|
background: rgba(0,0,0,0.3);
|
||||||
|
}
|
||||||
|
.forge-sidebar-header h2 {
|
||||||
|
margin: 0;
|
||||||
|
font-family: var(--font-display);
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: var(--gold);
|
||||||
|
}
|
||||||
|
.btn-forge-close {
|
||||||
|
background: transparent;
|
||||||
|
border: 2px solid var(--gold);
|
||||||
|
color: var(--gold);
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 50%;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.btn-forge-close:hover {
|
||||||
|
background: var(--gold);
|
||||||
|
color: #1a1814;
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
.forge-hint {
|
||||||
|
padding: 1rem 1.5rem;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: #94a3b8;
|
||||||
|
margin: 0;
|
||||||
|
text-align: center;
|
||||||
|
background: rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
.forge-selected {
|
||||||
|
min-height: 150px;
|
||||||
|
padding: 1rem;
|
||||||
|
background: rgba(0,180,255,0.1);
|
||||||
|
border: 2px dashed rgba(0,180,255,0.3);
|
||||||
|
border-radius: 8px;
|
||||||
|
margin: 1rem 1.5rem;
|
||||||
|
display: flex;
|
||||||
|
gap: 0.75rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
.forge-selected.drag-over {
|
||||||
|
background: rgba(0,180,255,0.2);
|
||||||
|
border-color: var(--cyan);
|
||||||
|
border-style: solid;
|
||||||
|
box-shadow: 0 0 20px rgba(0,180,255,0.5);
|
||||||
|
}
|
||||||
|
.forge-selected-empty {
|
||||||
|
color: #94a3b8;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
padding: 2rem 0;
|
||||||
|
}
|
||||||
|
.forge-deck-section {
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 0 1.5rem;
|
||||||
|
}
|
||||||
|
.forge-deck-section h3 {
|
||||||
|
font-size: 1rem;
|
||||||
|
color: var(--gold);
|
||||||
|
margin: 0 0 0.75rem 0;
|
||||||
|
font-family: var(--font-display);
|
||||||
}
|
}
|
||||||
.forge-deck-list {
|
.forge-deck-list {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));
|
||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
max-height: 400px;
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
margin-bottom: 1rem;
|
|
||||||
padding: 0.75rem;
|
padding: 0.75rem;
|
||||||
background: rgba(0,0,0,0.3);
|
background: rgba(0,0,0,0.3);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
position: relative;
|
flex: 1;
|
||||||
z-index: 1;
|
|
||||||
}
|
}
|
||||||
.forge-deck-card {
|
.forge-deck-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
.forge-deck-card {
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: transform 0.2s, box-shadow 0.2s;
|
transition: transform 0.2s, box-shadow 0.2s;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
.forge-deck-card:hover {
|
.forge-deck-card:hover {
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
@ -1361,28 +1456,70 @@ html, body {
|
|||||||
border-color: var(--cyan);
|
border-color: var(--cyan);
|
||||||
box-shadow: 0 0 20px rgba(0,180,255,0.7);
|
box-shadow: 0 0 20px rgba(0,180,255,0.7);
|
||||||
}
|
}
|
||||||
.forge-selected {
|
.forge-deck-card.dragging {
|
||||||
min-height: 80px;
|
opacity: 0.5;
|
||||||
padding: 0.5rem;
|
|
||||||
background: rgba(0,180,255,0.1);
|
|
||||||
border: 2px dashed rgba(0,180,255,0.3);
|
|
||||||
border-radius: 8px;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
display: flex;
|
|
||||||
gap: 0.5rem;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.forge-selected-empty {
|
|
||||||
color: #94a3b8;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
.forge-actions {
|
.forge-actions {
|
||||||
|
padding: 1.5rem;
|
||||||
|
border-top: 2px solid var(--gold);
|
||||||
|
background: rgba(0,0,0,0.3);
|
||||||
|
}
|
||||||
|
.forge-actions .btn {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.forge-selected .card-wrap {
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.forge-selected .card-wrap:hover {
|
||||||
|
transform: scale(1.1);
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
.forge-selected .card-wrap::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: -8px;
|
||||||
|
right: -8px;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
background: rgba(255,70,70,0.9);
|
||||||
|
border: 2px solid #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
z-index: 10;
|
||||||
|
transition: all 0.2s;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.forge-selected .card-wrap:hover::before {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
.forge-selected .card-wrap::after {
|
||||||
|
content: '×';
|
||||||
|
position: absolute;
|
||||||
|
top: -8px;
|
||||||
|
right: -8px;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.5rem;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 11;
|
||||||
|
transition: all 0.2s;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.forge-selected .card-wrap:hover::after {
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.forge-sidebar {
|
||||||
|
width: 100vw;
|
||||||
|
max-width: 100vw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.cards-gallery-modal {
|
.cards-gallery-modal {
|
||||||
max-width: 90vw;
|
max-width: 90vw;
|
||||||
|
|||||||
Reference in New Issue
Block a user