From 9d6a7085dcc1cdbbe5579c9874cd57f7cceb8919 Mon Sep 17 00:00:00 2001 From: jisangs Date: Thu, 14 May 2026 10:08:53 +0900 Subject: [PATCH] =?UTF-8?q?CSS=20=ED=8C=8C=EC=9D=BC=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.html | 284 +------------------------------------------------ src/style.css | 281 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 282 insertions(+), 283 deletions(-) create mode 100644 src/style.css diff --git a/src/index.html b/src/index.html index 7b1f003..6f5018b 100644 --- a/src/index.html +++ b/src/index.html @@ -4,289 +4,7 @@ Photo Renamer - + diff --git a/src/style.css b/src/style.css new file mode 100644 index 0000000..f15b10b --- /dev/null +++ b/src/style.css @@ -0,0 +1,281 @@ +@import url('https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;600&display=swap'); + +:root { + --bg: #0f0f17; + --surface: #17172a; + --card: #1e1e34; + --border: #2e2e50; + --accent: #7c6af7; + --accent2: #e96af7; + --success: #6af7a0; + --text: #e8e8f0; + --muted: #6b6b8a; + --drag-over: #3a2e70; + --sel-bg: rgba(124,106,247,0.22); + --sel-border: #7c6af7; + --thumb-size: 250px; +} + +* { box-sizing: border-box; margin: 0; padding: 0; } + +body { + font-family: 'Instrument Sans', -apple-system, sans-serif; + background: var(--bg); + color: var(--text); + height: 100vh; + display: flex; + flex-direction: column; + overflow: hidden; + user-select: none; + -webkit-app-region: no-drag; +} + +/* ── 타이틀바 ── */ +#titlebar { + height: 44px; + background: var(--bg); + -webkit-app-region: drag; + display: flex; + align-items: center; + padding: 0 80px 0 20px; + border-bottom: 1px solid var(--border); + flex-shrink: 0; +} +#titlebar h1 { + font-size: 13px; font-weight: 600; color: var(--muted); + letter-spacing: .08em; text-transform: uppercase; +} +#titlebar .dir-path { + margin-left: 16px; + font-family: 'JetBrains Mono', monospace; + font-size: 11px; color: var(--muted); opacity: .7; + max-width: 600px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; +} + +/* ── 툴바 ── */ +#toolbar { + display: flex; align-items: center; gap: 8px; + padding: 10px 16px; + background: var(--surface); + border-bottom: 1px solid var(--border); + flex-shrink: 0; +} +.btn { + display: inline-flex; align-items: center; gap: 6px; + padding: 7px 14px; border-radius: 8px; border: none; + font-family: inherit; font-size: 13px; font-weight: 600; + cursor: pointer; transition: all .15s; +} +.btn-primary { background: var(--accent); color: #fff; } +.btn-primary:hover { background: #9180ff; transform: translateY(-1px); } +.btn-ghost { background: transparent; color: var(--muted); border: 1px solid var(--border); } +.btn-ghost:hover { background: var(--card); color: var(--text); } +.btn-success { background: #1a4a2e; color: var(--success); border: 1px solid #2a6a40; } +.btn-success:hover { background: #204a34; } +.btn-success:disabled { opacity: .4; cursor: not-allowed; transform: none; } +.separator { width: 1px; height: 24px; background: var(--border); margin: 0 4px; } + +/* ── 포맷 바 ── */ +#format-bar { + display: flex; align-items: center; gap: 10px; + padding: 10px 16px; + background: var(--bg); + border-bottom: 1px solid var(--border); + flex-shrink: 0; +} +#format-bar label { + font-size: 12px; color: var(--muted); font-weight: 600; + text-transform: uppercase; letter-spacing: .06em; +} +#format-bar input { + background: var(--card); border: 1px solid var(--border); + color: var(--text); font-family: 'JetBrains Mono', monospace; + font-size: 13px; padding: 5px 10px; border-radius: 6px; outline: none; + transition: border-color .15s; +} +#format-bar input:focus { border-color: var(--accent); } +#input-prefix { width: 160px; } +#input-digits { width: 50px; text-align: center; } +.format-sep { color: var(--muted); font-family: 'JetBrains Mono', monospace; font-size: 14px; } +#preview-name { + font-family: 'JetBrains Mono', monospace; font-size: 13px; + color: var(--accent2); background: rgba(124,106,247,.1); + padding: 4px 12px; border-radius: 6px; border: 1px solid rgba(124,106,247,.2); +} +#file-count { margin-left: auto; font-size: 12px; color: var(--muted); } +#sel-count { font-size: 12px; color: var(--accent); font-weight: 700; display: none; } +#sel-count.visible { display: inline; } + +/* ── 그리드 컨테이너 ── */ +#grid-container { + flex: 1; overflow-y: auto; padding: 20px; + position: relative; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; +} +#grid-container::-webkit-scrollbar { width: 6px; } +#grid-container::-webkit-scrollbar-track { background: transparent; } +#grid-container::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } + +/* ── 그리드: 고정 열 폭 (--thumb-size) ── */ +#grid { + display: grid; + grid-template-columns: repeat(auto-fill, var(--thumb-size)); + gap: 14px; + justify-content: start; +} + +/* ── 빈 상태 ── */ +#empty-state { + display: flex; flex-direction: column; align-items: center; + justify-content: center; height: 100%; gap: 16px; color: var(--muted); +} +#empty-state .icon { font-size: 64px; opacity: .3; } +#empty-state p { font-size: 15px; text-align: center; line-height: 1.6; } + +/* ── 카드 ── */ +.card { + background: var(--card); + border: 2px solid transparent; + border-radius: 12px; + overflow: hidden; + cursor: grab; + transition: border-color .15s, transform .15s, box-shadow .15s, background .15s; + position: relative; + width: var(--thumb-size); +} +.card:hover { + border-color: var(--border); + transform: translateY(-2px); + box-shadow: 0 8px 24px rgba(0,0,0,.4); +} +.card.selected { + border-color: var(--sel-border) !important; + background: var(--sel-bg); + box-shadow: 0 0 0 1px var(--sel-border), 0 8px 24px rgba(124,106,247,.2); +} +.card.dragging, +.card.multi-dragging { opacity: .3; transform: scale(.96); cursor: grabbing; } +.card.drag-over { border-color: var(--accent) !important; background: var(--drag-over); } + +/* ── 썸네일: 정사각형 + object-fit: contain ── */ +.card-thumb { + width: 100%; + aspect-ratio: 1 / 1; + object-fit: contain; + background: #08080f; + display: block; +} +.card-thumb-placeholder { + width: 100%; + aspect-ratio: 1 / 1; + background: #08080f; + display: flex; align-items: center; justify-content: center; + font-size: 52px; opacity: .25; +} + +.card-body { padding: 8px 10px; } + +.card-num { + position: absolute; top: 8px; left: 8px; + background: var(--accent); color: #fff; + font-size: 11px; font-weight: 700; + font-family: 'JetBrains Mono', monospace; + padding: 2px 7px; border-radius: 99px; line-height: 1.6; + pointer-events: none; z-index: 2; +} +.card-check { + position: absolute; top: 8px; right: 8px; + width: 22px; height: 22px; border-radius: 50%; + background: var(--accent); color: #fff; + font-size: 13px; display: flex; align-items: center; justify-content: center; + opacity: 0; transition: opacity .15s; + pointer-events: none; z-index: 2; +} +.card.selected .card-check { opacity: 1; } + +.card-name { + font-size: 11px; color: var(--muted); + font-family: 'JetBrains Mono', monospace; + overflow: hidden; text-overflow: ellipsis; white-space: nowrap; +} +.card-new-name { + font-size: 11px; color: var(--accent2); + font-family: 'JetBrains Mono', monospace; + overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + margin-top: 2px; +} + +/* ── Rubber-band 선택 사각형 ── */ +#rubber-band { + position: fixed; + border: 1.5px solid var(--accent); + background: rgba(124,106,247,.1); + border-radius: 3px; + pointer-events: none; + display: none; + z-index: 40; +} + +/* ── 다중 드래그 고스트 배지 ── */ +#drag-ghost { + position: fixed; + pointer-events: none; + z-index: 9999; + display: none; + background: var(--accent); + color: #fff; + font-size: 13px; font-weight: 700; + font-family: 'Instrument Sans', sans-serif; + padding: 6px 16px; + border-radius: 99px; + box-shadow: 0 4px 20px rgba(0,0,0,.5); +} + +/* ── 상태바 ── */ +#statusbar { + height: 28px; background: var(--bg); + border-top: 1px solid var(--border); + display: flex; align-items: center; padding: 0 16px; gap: 12px; flex-shrink: 0; +} +#statusbar span { font-size: 11px; color: var(--muted); } +.status-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--muted); } +.status-dot.ready { background: var(--success); } + +/* ── 핀치 크기 힌트 ── */ +#thumb-size-hint { + position: fixed; bottom: 40px; right: 24px; + background: rgba(124,106,247,.9); + color: #fff; font-size: 12px; font-weight: 700; + font-family: 'JetBrains Mono', monospace; + padding: 5px 12px; border-radius: 8px; + opacity: 0; transition: opacity .2s; + pointer-events: none; z-index: 500; +} +#thumb-size-hint.show { opacity: 1; } + +/* ── 로딩 ── */ +#loading { + display: none; position: fixed; inset: 0; + background: rgba(15,15,23,.85); backdrop-filter: blur(4px); + z-index: 100; align-items: center; justify-content: center; + flex-direction: column; gap: 16px; +} +#loading.show { display: flex; } +.spinner { + width: 40px; height: 40px; + border: 3px solid var(--border); border-top-color: var(--accent); + border-radius: 50%; animation: spin .8s linear infinite; +} +@keyframes spin { to { transform: rotate(360deg); } } +#loading p { color: var(--text); font-size: 14px; } + +/* ── 토스트 ── */ +#toast { + position: fixed; bottom: 40px; left: 50%; + transform: translateX(-50%) translateY(20px); + background: var(--success); color: #0a2a1a; + font-weight: 700; font-size: 14px; + padding: 12px 24px; border-radius: 12px; + opacity: 0; transition: all .3s; pointer-events: none; z-index: 200; +} +#toast.show { opacity: 1; transform: translateX(-50%) translateY(0); } \ No newline at end of file