fix: improve mobile navigation and calculator usability
Publish GitHub Pages output / publish (push) Successful in 32s
Publish GitHub Pages output / publish (push) Successful in 32s
This commit is contained in:
@@ -123,7 +123,9 @@
|
||||
{#each result.order as cardId}<span><i style={`background: ${memberColor(cardId)};`}></i>{cardName(cardId)}</span>{/each}
|
||||
</div>
|
||||
</div>
|
||||
<div class="timeline-scroll" role="region" aria-label="스킬 발동 시간대 그래프">
|
||||
<p class="scroll-guide">그래프를 좌우로 밀면 전체 시간대를 확인할 수 있습니다.</p>
|
||||
<!-- svelte-ignore a11y_no_noninteractive_tabindex (Keyboard users must be able to scroll the timeline.) -->
|
||||
<div class="timeline-scroll" role="region" aria-label="스킬 발동 시간대 그래프" tabindex="0">
|
||||
<div class="timeline-canvas" style={`width: ${timelineWidth + 156}px;`}>
|
||||
<div class="timeline-row note-row">
|
||||
<strong class="lane-label">초당 노트</strong>
|
||||
@@ -172,6 +174,7 @@
|
||||
<SpecialNoteSummary {result} {cardName} />
|
||||
|
||||
<style>
|
||||
.scroll-guide { color: #adb5c2; font-size: 13px; line-height: 1.5; }
|
||||
.order-sections { display: grid; grid-template-columns: 1fr; gap: 14px; margin-top: 18px; }
|
||||
.order-section { min-width: 0; }
|
||||
.order-section h3 { margin: 0 0 9px; color: #aeb7c5; font-size: 14px; }
|
||||
|
||||
@@ -71,6 +71,8 @@
|
||||
background: rgb(24 28 36 / 97%);
|
||||
box-shadow: 0 18px 50px rgb(0 0 0 / 42%);
|
||||
color: #e8ebf1;
|
||||
max-height: calc(100dvh - 36px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.consent-copy { min-width: 0; flex: 1; }
|
||||
@@ -94,11 +96,10 @@
|
||||
.primary { color: #21121a; background: #ef8bb6; }
|
||||
.secondary { border-color: #596273; color: #d4dae4; background: #303641; }
|
||||
.analytics-settings {
|
||||
position: fixed;
|
||||
z-index: 90;
|
||||
right: 12px;
|
||||
bottom: 12px;
|
||||
min-height: 30px;
|
||||
display: block;
|
||||
margin: 16px 12px max(12px, env(safe-area-inset-bottom));
|
||||
margin-left: auto;
|
||||
min-height: 44px;
|
||||
padding: 5px 9px;
|
||||
border-color: rgb(255 255 255 / 12%);
|
||||
color: #8e98a8;
|
||||
@@ -107,7 +108,8 @@
|
||||
}
|
||||
|
||||
@media (max-width: 560px) {
|
||||
.analytics-consent { right: 12px; bottom: 12px; width: calc(100% - 24px); align-items: stretch; flex-direction: column; gap: 14px; }
|
||||
.analytics-consent { right: 12px; bottom: max(12px, env(safe-area-inset-bottom)); width: calc(100% - 24px); align-items: stretch; flex-direction: column; gap: 14px; }
|
||||
.consent-actions { justify-content: flex-end; }
|
||||
.consent-actions button { min-height: 44px; flex: 1; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
let sort: SongSort = 'title';
|
||||
|
||||
$: options = songOptions(charts, difficulty, query, sort);
|
||||
$: selectedTitle = charts.find((chart) => chart.songId === value)?.title;
|
||||
|
||||
function selectSong(event: Event) {
|
||||
const nextValue = (event.currentTarget as HTMLSelectElement).value;
|
||||
@@ -48,6 +49,7 @@
|
||||
{/if}
|
||||
</select>
|
||||
</label>
|
||||
{#if selectedTitle}<p class="selected-title">선택한 악곡: {selectedTitle}</p>{/if}
|
||||
{#if query.trim()}
|
||||
<p class:no-results={options.length === 0} class="search-status" aria-live="polite">
|
||||
{options.length > 0
|
||||
@@ -59,6 +61,7 @@
|
||||
|
||||
<style>
|
||||
.song-picker { display: grid; grid-template-columns: minmax(180px, .9fr) minmax(140px, .55fr) minmax(260px, 1.4fr); gap: 9px; }
|
||||
.selected-title { grid-column: 1 / -1; margin: 0; color: #b9c1cd; font-size: 12px; line-height: 1.5; overflow-wrap: anywhere; }
|
||||
label { display: grid; gap: 7px; min-width: 0; color: #8f98a8; font-size: 14px; font-weight: 750; }
|
||||
label > span { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
||||
small { color: #737d8d; font-size: 11px; }
|
||||
|
||||
@@ -6,3 +6,12 @@
|
||||
--page-header-bottom: 28px;
|
||||
--page-description-size: 16px;
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
:root { --page-title-size: 30px; --page-description-size: 15px; }
|
||||
/* Keep editable text readable without triggering focus zoom on mobile Safari. */
|
||||
body input:not([type='checkbox']):not([type='radio']):not([type='range']):not([type='file']),
|
||||
body select, body textarea { font-size: 16px; }
|
||||
}
|
||||
|
||||
html { scroll-padding-top: 80px; }
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
let eventClock = createInitialReleaseClock($page.data?.serverNow);
|
||||
let eventNow = eventClock.now();
|
||||
let menuOpen = false;
|
||||
$: if ($page.url.pathname) menuOpen = false;
|
||||
$: showEventTab = Boolean(activeEventAt(events, eventNow));
|
||||
|
||||
onMount(() => {
|
||||
@@ -32,7 +34,8 @@
|
||||
<header class="site-nav">
|
||||
<div class="nav-inner">
|
||||
<a class="brand" href="/" aria-label="홀로도리 계산기 홈">홀로도리 계산기</a>
|
||||
<nav aria-label="주요 메뉴">
|
||||
<button class="menu-toggle" type="button" aria-controls="primary-navigation" aria-expanded={menuOpen} on:click={() => menuOpen = !menuOpen}>{menuOpen ? '메뉴 닫기' : '전체 메뉴'}</button>
|
||||
<nav id="primary-navigation" class:open={menuOpen} aria-label="주요 메뉴">
|
||||
<a href="/cards" aria-current={$page.url.pathname.startsWith('/cards') ? 'page' : undefined}>카드 목록</a>
|
||||
<a href="/analysis" aria-current={$page.url.pathname.startsWith('/analysis') ? 'page' : undefined}>배치 분석</a>
|
||||
<a href="/rating" aria-current={$page.url.pathname.startsWith('/rating') ? 'page' : undefined}>리더 레이팅</a>
|
||||
@@ -101,7 +104,9 @@
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
nav { display: flex; min-width: 0; flex: 1; align-items: center; justify-content: flex-end; gap: 4px; overflow-x: auto; scrollbar-width: none; }
|
||||
.brand { flex-shrink: 0; }
|
||||
.menu-toggle { display: none; }
|
||||
nav { display: flex; min-width: 0; flex: 1; align-items: center; justify-content: safe flex-end; gap: 4px; overflow-x: auto; scrollbar-width: thin; }
|
||||
nav::-webkit-scrollbar { display: none; }
|
||||
|
||||
nav a {
|
||||
@@ -124,6 +129,15 @@
|
||||
.report-link span { margin-left: 2px; font-size: 11px; }
|
||||
a:focus-visible { outline: 3px solid rgb(239 139 182 / 28%); outline-offset: 2px; }
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
.nav-inner { flex-wrap: wrap; padding-block: 5px; }
|
||||
.menu-toggle { display: block; min-height: 44px; padding: 8px 14px; border: 1px solid #694256; border-radius: 9px; color: #f1a1c3; background: #29202a; font: inherit; font-size: 14px; cursor: pointer; }
|
||||
.menu-toggle:focus-visible { outline: 3px solid #ef8bb6; outline-offset: 2px; }
|
||||
nav { display: none; flex: 0 0 100%; grid-template-columns: repeat(2, minmax(0, 1fr)); max-height: 65dvh; overflow-y: auto; padding: 4px 2px 10px; }
|
||||
nav.open { display: grid; }
|
||||
nav a { display: flex; align-items: center; min-height: 44px; white-space: normal; }
|
||||
}
|
||||
|
||||
@media (max-width: 560px) {
|
||||
:global(:root) { --page-gutter: 24px; }
|
||||
.nav-inner { width: calc(100% - 24px); min-height: 54px; }
|
||||
|
||||
@@ -1053,8 +1053,10 @@
|
||||
<option value={card.id} disabled={selectedCardIds.some((id, index) => index !== slot && cardById.get(id)?.characterId === card.characterId)}>{collection[card.id]?.owned ? '● ' : ''}{cardLabel(card)}</option>
|
||||
{/each}
|
||||
</select>
|
||||
{#if selectedId && cardById.get(selectedId)}<small class="selected-card-name">{cardLabel(cardById.get(selectedId)!)}</small>{/if}
|
||||
</label>
|
||||
<div class="awakening">
|
||||
<span class="mobile-field-label">개화 (0~5)</span>
|
||||
<div class="awakening-stepper">
|
||||
<button
|
||||
type="button"
|
||||
@@ -1072,6 +1074,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="cooldown-lock">
|
||||
<span class="mobile-field-label">빈도 감소 고정</span>
|
||||
<div class="reduction-options">
|
||||
{#each REDUCTION_LOCK_OPTIONS as reduction}
|
||||
<button
|
||||
@@ -1084,6 +1087,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="board-overrides">
|
||||
<span class="mobile-field-label">파란 노드 전체</span>
|
||||
<span class="mobile-field-label">기수 보너스 덮어쓰기 (0~900)</span>
|
||||
<label class="override-checkbox">
|
||||
<input type="checkbox" checked={allBlueNodes[slot]} aria-label={`${slot + 1}번 카드 파란 노드 전체 활성화`} on:change={() => toggleAllBlueNodes(slot)}>
|
||||
<span aria-hidden="true"></span>
|
||||
@@ -1237,7 +1242,26 @@
|
||||
{/if}
|
||||
</p>
|
||||
{/if}
|
||||
<div class="timeline-scroll" role="region" aria-label="스킬 발동 시간대 그래프">
|
||||
{#if mode === 'analysis'}
|
||||
<details class="active-window-list">
|
||||
<summary>액티브 발동 목록 · 눌러서 미발동/복원</summary>
|
||||
<p>작은 그래프 대신 아래 버튼으로도 조작할 수 있습니다. 미발동으로 설정한 구간은 다시 누르면 복원됩니다.</p>
|
||||
<div>
|
||||
{#each result.activeWindows as window}
|
||||
{@const excluded = excludedActiveWindows.some((item) => item.cardId === window.cardId && item.startSeconds === window.startSeconds)}
|
||||
{@const impact = activeImpacts.get(activeWindowKey(window))}
|
||||
<button type="button" disabled={!simulationContext || running} aria-pressed={excluded} on:click={() => toggleActiveWindow(window)}>
|
||||
<strong>{resultCardName(window.cardId)}</strong>
|
||||
<span>{formatSeconds(window.startSeconds)}~{formatSeconds(window.endSeconds)} · 효과 {window.scoreUpPercent}% · {excluded ? '미발동 (눌러서 복원)' : '발동 (눌러서 제외)'}</span>
|
||||
{#if impact}<span>변경 시 최고점 {signedScoreChange(impact.scoreChange)}</span>{/if}
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
</details>
|
||||
{/if}
|
||||
<p class="board-guide">그래프를 좌우로 밀면 전체 시간대를 확인할 수 있습니다.</p>
|
||||
<!-- svelte-ignore a11y_no_noninteractive_tabindex (Keyboard users must be able to scroll the timeline.) -->
|
||||
<div class="timeline-scroll" role="region" aria-label="스킬 발동 시간대 그래프" tabindex="0">
|
||||
<div class="timeline-canvas" style={`width: ${timelineWidth + 156}px;`}>
|
||||
<ScoreTimelineChart notes={displayedResult!.notes} {maximumScoreProbabilities} durationSeconds={timelineDuration} minimumWidth={timelineWidth} timeTicks={timelineTicks} />
|
||||
{#each result.order as cardId, slot}
|
||||
@@ -1308,6 +1332,14 @@
|
||||
</main>
|
||||
|
||||
<style>
|
||||
.mobile-field-label, .selected-card-name { display: none; }
|
||||
.active-window-list { margin: 12px 0; padding: 12px; border: 1px solid #343c49; border-radius: 10px; }
|
||||
.active-window-list summary { min-height: 44px; align-content: center; cursor: pointer; font-size: 14px; }
|
||||
.active-window-list p { color: #adb5c2; font-size: 13px; line-height: 1.6; }
|
||||
.active-window-list > div { display: grid; gap: 8px; max-height: 360px; overflow-y: auto; }
|
||||
.active-window-list button { display: grid; gap: 6px; min-height: 44px; padding: 12px; border: 1px solid #414b5b; border-radius: 8px; background: #202630; color: #e8ebf1; text-align: left; cursor: pointer; overflow-wrap: anywhere; }
|
||||
.active-window-list button[aria-pressed='true'] { border-color: #ef8bb6; background: #37232e; }
|
||||
.active-window-list button span { font-size: 12px; line-height: 1.5; }
|
||||
#result-title { scroll-margin-top: 90px; }
|
||||
.stale-warning { margin: 14px 0; padding: 11px 14px; border: 1px solid #665333; border-radius: 9px; color: #edcf92; background: #292319; font-size: 13px; line-height: 1.6; }
|
||||
main { width: min(var(--page-max-width), calc(100% - var(--page-gutter))); margin: 0 auto; padding: var(--page-content-top) 0 80px; }
|
||||
@@ -1475,7 +1507,7 @@
|
||||
.card-field-header, .card-field { grid-template-columns: minmax(0, 1fr) 120px 280px 180px; }
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
@media (max-width: 900px) {
|
||||
.order-sections { grid-template-columns: 1fr; }
|
||||
main { width: calc(100% - 24px); padding-top: var(--page-content-top); }
|
||||
.page-header { align-items: flex-start; }
|
||||
@@ -1504,4 +1536,19 @@
|
||||
.lane-label { flex-basis: 118px; min-width: 118px; }
|
||||
.timeline-canvas { padding-right: 0; }
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.song-fields { grid-template-columns: minmax(0, 1fr); }
|
||||
.section-title { flex-wrap: wrap; }
|
||||
.card-field { grid-template-columns: minmax(0, 1fr); padding: 14px 0; border-top: 1px solid #343c49; gap: 12px; }
|
||||
.card-field > label { grid-template-columns: minmax(0, 1fr); gap: 7px; }
|
||||
.mobile-field-label { display: block; color: #aab4c3; font-size: 13px; line-height: 1.5; margin-bottom: 6px; }
|
||||
.selected-card-name { display: block; color: #c1c8d3; font-size: 13px; line-height: 1.5; overflow-wrap: anywhere; }
|
||||
.board-overrides { height: auto; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: end; }
|
||||
.board-overrides .mobile-field-label { margin-bottom: 0; }
|
||||
.override-checkbox, .generation-input { min-height: 44px; }
|
||||
.awakening-stepper { height: 46px; grid-template-columns: 44px minmax(0, 1fr) 44px; }
|
||||
.reduction-options { height: 46px; }
|
||||
.chart-meta span { white-space: normal; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1753,7 +1753,7 @@
|
||||
}
|
||||
|
||||
.description {
|
||||
display: none;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.total {
|
||||
|
||||
@@ -1320,8 +1320,10 @@
|
||||
<option value="">고정하지 않음</option>
|
||||
{#each candidateCards as card}<option value={card.id} disabled={fixedCardIds.some((id, index) => index !== slot && cardById.get(id)?.characterId === card.characterId)}>{cardLabel(card)}</option>{/each}
|
||||
</select>
|
||||
{#if selectedId && cardById.get(selectedId)}<small class="selected-card-name">{cardLabel(cardById.get(selectedId)!)}</small>{/if}
|
||||
</label>
|
||||
<div class="fixed-awakening">
|
||||
<span class="mobile-field-label">개화 (0~5)</span>
|
||||
<div class="awakening-stepper">
|
||||
<button type="button" disabled={!selectedId || fixedAwakenings[slot] <= 0} aria-label={`${slot + 1}번 고정 카드 개화 낮추기`} on:click={() => updateFixedAwakening(slot, fixedAwakenings[slot] - 1)}>‹</button>
|
||||
<strong>{fixedAwakenings[slot]}</strong>
|
||||
@@ -1329,6 +1331,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="fixed-reduction">
|
||||
<span class="mobile-field-label">빈도 감소 고정</span>
|
||||
<div class="reduction-options">
|
||||
{#each REDUCTION_LOCK_OPTIONS as reduction}
|
||||
<button type="button" disabled={!selectedId} class:active={fixedCooldownReductions[slot] === reduction} aria-pressed={fixedCooldownReductions[slot] === reduction} on:click={() => updateFixedReduction(slot, reduction)}>{reduction === null ? '미사용' : `${reduction}%`}</button>
|
||||
@@ -1336,6 +1339,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="fixed-overrides">
|
||||
<span class="mobile-field-label">파란 노드 전체</span>
|
||||
<span class="mobile-field-label">기수 보너스 덮어쓰기 (0~900)</span>
|
||||
<label class="override-checkbox">
|
||||
<input type="checkbox" disabled={!selectedId} checked={fixedAllBlueNodes[slot]} aria-label={`${slot + 1}번 고정 카드 파란 노드 전체 활성화`} on:change={() => toggleFixedAllBlueNodes(slot)}>
|
||||
<span aria-hidden="true"></span>
|
||||
@@ -1451,6 +1456,7 @@
|
||||
</main>
|
||||
|
||||
<style>
|
||||
.mobile-field-label, .selected-card-name { display: none; }
|
||||
.result-limit { max-width: 220px; margin-top: 16px; }
|
||||
.search-inputs { min-width: 0; margin: 0; padding: 0; border: 0; }
|
||||
main { width: min(var(--page-max-width), calc(100% - var(--page-gutter))); margin: 0 auto; padding: var(--page-content-top) 0 80px; }
|
||||
@@ -1601,7 +1607,7 @@
|
||||
.fixed-field { grid-template-columns: minmax(0, 1fr) 120px 304px 180px; }
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
@media (max-width: 900px) {
|
||||
main { width: calc(100% - 24px); padding-top: var(--page-content-top); }
|
||||
.panel { padding: 17px; }
|
||||
.song-fields { grid-template-columns: 1fr 100px; }
|
||||
@@ -1624,4 +1630,19 @@
|
||||
.analysis-link { grid-column: 1 / -1; grid-row: 5; }
|
||||
.ranking-detail { padding: 0 10px 14px; }
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.song-fields { grid-template-columns: minmax(0, 1fr); }
|
||||
.section-title { flex-wrap: wrap; }
|
||||
.fixed-field { grid-template-columns: minmax(0, 1fr); padding: 14px 0; border-top: 1px solid #343c49; gap: 12px; }
|
||||
.fixed-field > label { grid-template-columns: minmax(0, 1fr); gap: 7px; }
|
||||
.mobile-field-label { display: block; color: #aab4c3; font-size: 13px; line-height: 1.5; margin-bottom: 6px; }
|
||||
.selected-card-name { display: block; color: #c1c8d3; font-size: 13px; line-height: 1.5; overflow-wrap: anywhere; }
|
||||
.fixed-overrides { height: auto; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: end; }
|
||||
.fixed-overrides .mobile-field-label { margin-bottom: 0; }
|
||||
.override-checkbox, .generation-input { min-height: 44px; }
|
||||
.awakening-stepper { height: 46px; grid-template-columns: 44px minmax(0, 1fr) 44px; }
|
||||
.reduction-options { height: 46px; }
|
||||
.chart-meta span { white-space: normal; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -317,6 +317,43 @@
|
||||
boardViewport.scrollTop = contentY * boardZoom - pointerY;
|
||||
}
|
||||
|
||||
async function changeBoardZoom(factor: number) {
|
||||
if (!boardViewport) return;
|
||||
const centerX = boardViewport.clientWidth / 2;
|
||||
const centerY = boardViewport.clientHeight / 2;
|
||||
const contentX = (boardViewport.scrollLeft + centerX) / boardZoom;
|
||||
const contentY = (boardViewport.scrollTop + centerY) / boardZoom;
|
||||
boardZoom = Math.max(0.4, Math.min(1.8, boardZoom * factor));
|
||||
await tick();
|
||||
boardViewport.scrollLeft = contentX * boardZoom - centerX;
|
||||
boardViewport.scrollTop = contentY * boardZoom - centerY;
|
||||
}
|
||||
|
||||
function manageCardDialog(node: HTMLElement) {
|
||||
const previousFocus = document.activeElement;
|
||||
const previousOverflow = document.body.style.overflow;
|
||||
document.body.style.overflow = 'hidden';
|
||||
node.focus();
|
||||
function keydown(event: KeyboardEvent) {
|
||||
if (event.key === 'Escape') { event.preventDefault(); selectedSocketGroupId = ''; }
|
||||
if (event.key !== 'Tab') return;
|
||||
const controls = Array.from(node.querySelectorAll<HTMLElement>('button:not(:disabled), input:not(:disabled), [tabindex="0"]'));
|
||||
const first = controls[0];
|
||||
const last = controls.at(-1);
|
||||
if (event.shiftKey && (document.activeElement === first || document.activeElement === node)) {
|
||||
event.preventDefault(); last?.focus();
|
||||
} else if (!event.shiftKey && document.activeElement === last) {
|
||||
event.preventDefault(); first?.focus();
|
||||
}
|
||||
}
|
||||
node.addEventListener('keydown', keydown);
|
||||
return { destroy() {
|
||||
node.removeEventListener('keydown', keydown);
|
||||
document.body.style.overflow = previousOverflow;
|
||||
if (previousFocus instanceof HTMLElement) previousFocus.focus({ preventScroll: true });
|
||||
} };
|
||||
}
|
||||
|
||||
function startBoardDrag(event: PointerEvent) {
|
||||
if (!boardViewport || event.button !== 0 || (event.target as HTMLElement).closest('.board-node')) return;
|
||||
boardDragging = true;
|
||||
@@ -1378,6 +1415,13 @@
|
||||
<p><strong>{selectedActiveBoardNodeCount}</strong> / {selectedBoardNodeCount}개 활성화</p>
|
||||
<div><button type="button" on:click={activateAllBlueNodes}>모든 파란 노드 활성화</button><button type="button" on:click={() => setAllBoardNodes(true)}>모두 활성화</button><button type="button" on:click={() => setAllBoardNodes(false)}>모두 해제</button></div>
|
||||
</div>
|
||||
<div class="board-zoom" aria-label="보드 확대 및 축소">
|
||||
<button type="button" aria-label="보드 축소" disabled={boardZoom <= .4} on:click={() => changeBoardZoom(1 / 1.25)}>−</button>
|
||||
<span>{Math.round(boardZoom * 100)}%</span>
|
||||
<button type="button" aria-label="보드 확대" disabled={boardZoom >= 1.8} on:click={() => changeBoardZoom(1.25)}>+</button>
|
||||
<button type="button" on:click={fitBoardViewport}>화면 맞춤</button>
|
||||
</div>
|
||||
<p class="board-note">보드의 빈 곳을 드래그하면 이동합니다. +·− 버튼으로 확대·축소하고, 보드 바깥을 쓸어 페이지를 이동하세요.</p>
|
||||
<div
|
||||
class="board-scroll"
|
||||
class:dragging={boardDragging}
|
||||
@@ -1451,7 +1495,7 @@
|
||||
|
||||
{#if selectedSocketGroupId}
|
||||
<div class="card-picker-backdrop" role="presentation" on:click={(event) => { if (event.target === event.currentTarget) selectedSocketGroupId = ''; }}>
|
||||
<div class="card-picker" role="dialog" aria-modal="true" aria-labelledby="card-picker-title" tabindex="-1">
|
||||
<div class="card-picker" use:manageCardDialog role="dialog" aria-modal="true" aria-labelledby="card-picker-title" tabindex="-1">
|
||||
<div class="card-picker-heading">
|
||||
<div><p class="section-label">연결 노드</p><h3 id="card-picker-title">배치할 카드 선택</h3></div>
|
||||
<button type="button" aria-label="닫기" on:click={() => selectedSocketGroupId = ''}>×</button>
|
||||
@@ -1753,7 +1797,7 @@
|
||||
.board-legend i { width: 9px; height: 9px; border-radius: 50%; }
|
||||
.board-note { margin: 10px 0 0; color: #7f8999; font-size: 13px; line-height: 1.5; }
|
||||
.card-picker-backdrop { position: fixed; inset: 0; z-index: 30; display: grid; place-items: center; padding: 20px; background: rgb(5 8 12 / 72%); }
|
||||
.card-picker { width: min(620px, 100%); max-height: min(760px, calc(100vh - 40px)); overflow: hidden; border: 1px solid #3b4453; border-radius: 16px; background: #171c24; box-shadow: 0 20px 70px rgb(0 0 0 / 45%); }
|
||||
.card-picker { display: flex; flex-direction: column; width: min(620px, 100%); max-height: min(760px, calc(100dvh - 40px)); overflow: hidden; border: 1px solid #3b4453; border-radius: 16px; background: #171c24; box-shadow: 0 20px 70px rgb(0 0 0 / 45%); }
|
||||
.card-picker-heading { display: flex; align-items: center; justify-content: space-between; padding: 20px 20px 10px; }
|
||||
.card-picker-heading h3 { margin: 2px 0 0; color: #edf0f5; font-size: 20px; }
|
||||
.card-picker-heading button { width: 34px; height: 34px; border: 1px solid #3b4453; border-radius: 9px; color: #c9d0da; background: #242b36; font-size: 22px; cursor: pointer; }
|
||||
@@ -1763,7 +1807,7 @@
|
||||
.current-placement span { color: #d990af; font-size: 12px; font-weight: 850; }
|
||||
.current-placement strong { overflow: hidden; color: #dce1e9; font-size: 14px; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.current-placement button { padding: 5px 8px; border: 1px solid #65404f; border-radius: 6px; color: #f0a8c5; background: transparent; font-size: 12px; cursor: pointer; }
|
||||
.connect-card-list { display: grid; gap: 6px; max-height: 520px; overflow-y: auto; padding: 0 20px 20px; scrollbar-width: thin; }
|
||||
.connect-card-list { min-height: 0; display: grid; gap: 6px; max-height: 520px; overflow-y: auto; padding: 0 20px 20px; scrollbar-width: thin; }
|
||||
.connect-card-list > button { display: grid; grid-template-columns: 38px minmax(0, 1fr) 54px auto; align-items: center; gap: 11px; min-height: 66px; padding: 8px 10px; border: 1px solid #303845; border-radius: 10px; color: inherit; background: #12171e; text-align: left; cursor: pointer; }
|
||||
.connect-card-list > button:hover, .connect-card-list > button.selected { border-color: #a95e7f; background: #211a23; }
|
||||
.connect-card-rarity { color: #f1a5c5; font-size: 13px; font-weight: 900; }
|
||||
@@ -1791,7 +1835,7 @@
|
||||
aside { margin-top: 16px; padding: 18px 20px; border: 1px solid #292f3b; border-radius: 14px; color: #929cad; background: #151920; font-size: 13px; line-height: 1.6; }
|
||||
aside strong { color: #cbd1db; }
|
||||
aside p { margin: 5px 0 0; }
|
||||
@media (max-width: 700px) {
|
||||
@media (max-width: 900px) {
|
||||
main { width: min(100% - 24px, 900px); padding-top: var(--page-content-top); }
|
||||
.summary { grid-template-columns: repeat(2, 1fr); }
|
||||
.settings-grid { grid-template-columns: 1fr; }
|
||||
@@ -1822,11 +1866,31 @@
|
||||
.efficiency-table-head, .efficiency-list > button { grid-template-columns: 28px 210px 100px 90px 110px 115px; min-width: 710px; }
|
||||
.board-scroll { height: min(58vh, 560px); }
|
||||
.card-picker-backdrop { align-items: end; padding: 0; }
|
||||
.card-picker { max-height: 88vh; border-radius: 16px 16px 0 0; }
|
||||
.connect-card-list { max-height: 56vh; }
|
||||
.card-picker { max-height: 88dvh; padding-bottom: env(safe-area-inset-bottom); border-radius: 16px 16px 0 0; }
|
||||
.connect-card-list { max-height: none; overflow-y: auto; }
|
||||
.connect-card-list > button { grid-template-columns: 28px minmax(0, 1fr) 48px auto; gap: 7px; padding-inline: 8px; }
|
||||
.connect-range-preview { width: 44px; height: 44px; }
|
||||
.actions { display: grid; }
|
||||
.actions .danger { margin: 10px 0 0; }
|
||||
}
|
||||
|
||||
.card-picker-heading, .card-picker-note, .card-picker-search, .current-placement { flex-shrink: 0; }
|
||||
.connect-card-list { grid-auto-rows: max-content; align-content: start; }
|
||||
.board-zoom { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
|
||||
.board-zoom button { min-width: 44px; min-height: 44px; padding: 8px 12px; border: 1px solid #465064; border-radius: 8px; color: #d5dbe4; background: #202733; cursor: pointer; }
|
||||
.board-zoom button:disabled { opacity: .45; cursor: default; }
|
||||
.board-zoom span { min-width: 42px; text-align: center; }
|
||||
.board-zoom + .board-note { margin-bottom: 10px; }
|
||||
@media (max-width: 900px) {
|
||||
.board-toolbar, .board-toolbar div { flex-wrap: wrap; }
|
||||
.board-toolbar button, .card-picker-heading button { min-height: 44px; }
|
||||
.card-picker-heading button { min-width: 44px; }
|
||||
.card-table .table-row { grid-template-columns: 34px minmax(0, 1fr); }
|
||||
.awakening-field { grid-column: 2; }
|
||||
.awakening-stepper { height: 46px; grid-template-columns: 44px minmax(0, 1fr) 44px; }
|
||||
.identity { flex-wrap: wrap; }
|
||||
.identity strong, .max-awakening-check > strong, .connect-card-name strong, .current-placement strong { white-space: normal; overflow-wrap: anywhere; }
|
||||
.connect-card-list > button { grid-template-columns: 28px minmax(0, 1fr) 48px; }
|
||||
.connect-card-effect { grid-column: 2 / -1; justify-items: start; }
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user