diff --git a/src/main/resources/static/css/styles.css b/src/main/resources/static/css/styles.css index b0d5280..dcf808a 100644 --- a/src/main/resources/static/css/styles.css +++ b/src/main/resources/static/css/styles.css @@ -322,6 +322,12 @@ body { border-color: rgba(148, 163, 184, 0.2); } +.badge.soft { + background: rgba(59, 130, 246, 0.12); + color: #bfdbfe; + border-color: rgba(59, 130, 246, 0.26); +} + .badge.danger { background: rgba(248, 113, 113, 0.12); color: #fecdd3; @@ -399,30 +405,38 @@ body { #0f172a; } -.admin-shell { - max-width: 1200px; - width: 100%; +.admin-frame { margin: 0 auto; - padding: 28px 18px 56px; display: flex; flex-direction: column; - gap: 18px; + width: 100%; + height: 100vh; } -.admin-header { +.admin-topbar { display: flex; align-items: center; justify-content: space-between; - gap: 16px; - padding: 18px 22px; - background: rgba(15, 23, 42, 0.92); - border: 1px solid #1f2937; - border-radius: 16px; - box-shadow: 0 18px 50px rgba(0, 0, 0, 0.4); + gap: 14px; + padding: 10px 12px; + background: linear-gradient(90deg, rgba(15, 23, 42, 0.95), rgba(12, 20, 34, 0.9)); + border-bottom: 1px solid #1f2937; + border-radius: 0; + box-shadow: 0 16px 40px rgba(0, 0, 0, 0.45); } -.admin-header h1 { - margin: 6px 0 8px; +.topbar-left { + display: flex; + align-items: center; + gap: 10px; +} + +.status-dot { + width: 12px; + height: 12px; + border-radius: 50%; + background: radial-gradient(circle, #22c55e 0%, #14532d 70%); + box-shadow: 0 0 0 6px rgba(34, 197, 94, 0.15); } .admin-identity { @@ -432,6 +446,69 @@ body { flex-direction: column; } +.admin-identity h1 { + margin: 2px 0 4px; +} + +.admin-workspace { + --sidebar-width: 300px; + display: grid; + height: 100%; + grid-template-columns: var(--sidebar-width) 1fr; + gap: 12px; + align-items: stretch; + position: relative; +} + +.admin-rail { + background: rgba(11, 18, 32, 0.92); + border-right: 1px solid #1f2937; + padding: 10px 10px 12px; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.02), 0 18px 45px rgba(0, 0, 0, 0.4); + display: flex; + flex-direction: column; + gap: 8px; +} + +.rail-header { + display: flex; + align-items: center; + justify-content: space-between; +} + +.rail-body { + display: flex; + flex-direction: column; + gap: 8px; + flex: 1; + min-height: 0; +} + +.rail-scroll { + overflow-y: auto; + padding-right: 2px; + flex: 1; + min-height: 0; +} + +.canvas-stack { + background: linear-gradient(180deg, rgba(10, 15, 26, 0.95), rgba(12, 17, 30, 0.96)); + border-radius: 16px; + padding: 12px 12px 14px; + box-shadow: 0 18px 50px rgba(0, 0, 0, 0.45); + display: flex; + flex-direction: column; + gap: 10px; + min-height: 72vh; +} + +.canvas-surface { + display: flex; + flex-direction: column; + gap: 12px; + height: 100%; +} + .header-actions.tight { gap: 8px; } @@ -651,6 +728,27 @@ body { } } +@media (max-width: 1200px) { + .admin-workspace { + grid-template-columns: 1fr; + } + + .admin-rail { + max-width: 520px; + } + + .rail-inspector { + position: static; + width: 100%; + max-height: none; + } + + .overlay { + min-height: 520px; + height: 60vh; + } +} + .controls ul { list-style: none; padding: 0; @@ -664,23 +762,17 @@ body { .overlay { position: relative; flex: 1; - min-height: 520px; - height: calc(100vh - 220px); - background: black; + min-height: clamp(520px, 72vh, 980px); + height: 100%; + background: radial-gradient(circle at 18% 20%, rgba(59, 130, 246, 0.08), transparent 38%), + radial-gradient(circle at 80% 0%, rgba(124, 58, 237, 0.08), transparent 40%), + #0b1220; overflow: hidden; border: 1px solid #1f2937; border-radius: 16px; box-shadow: 0 16px 45px rgba(0, 0, 0, 0.45); -} - -.overlay iframe { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - border: none; - filter: brightness(0.35) saturate(0.7); + display: grid; + place-items: center; } .overlay canvas { @@ -691,6 +783,13 @@ body { z-index: 2; } +#admin-canvas { + border: 1px solid rgba(148, 163, 184, 0.35); + border-radius: 10px; + box-shadow: 0 0 0 1px rgba(15, 23, 42, 0.5), 0 16px 45px rgba(0, 0, 0, 0.55); + background-color: rgba(255, 0, 255, 0.1); +} + .broadcast-body canvas { position: absolute; top: 0; @@ -718,6 +817,106 @@ body { display: none; } +.panel-title { + margin: 4px 0 0; + font-size: 18px; + color: #e5e7eb; +} + +.panel-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + margin-bottom: 10px; +} + +.canvas-panel { + padding: 18px 18px 20px; + margin-top: 0; +} + +.canvas-topbar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 14px; +} + +.canvas-meta { + display: flex; + gap: 8px; + align-items: center; +} + +.canvas-stage { + margin-top: 14px; + display: flex; + flex-direction: column; + gap: 10px; +} + +.canvas-boundary { + background-image: linear-gradient(to right, rgba(255,255,255,0.03) 1px, transparent 1px), + linear-gradient(to bottom, rgba(255,255,255,0.03) 1px, transparent 1px); + background-size: 24px 24px; + position: relative; + isolation: isolate; +} + +.canvas-boundary::after { + content: ""; + position: absolute; + border-radius: 12px; + pointer-events: none; + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.02), 0 16px 40px rgba(0, 0, 0, 0.35); +} + +.canvas-guides { + position: absolute; + inset: 0; + pointer-events: none; +} + +.canvas-footnote { + color: #94a3b8; + font-size: 13px; + margin: 0 4px; +} + +.rail-inspector { + margin-top: auto; + background: rgba(10, 14, 24, 0.96); + border: 1px solid rgba(124, 58, 237, 0.45); + border-radius: 12px; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.02), 0 16px 40px rgba(0, 0, 0, 0.45); + backdrop-filter: blur(4px); + padding: 10px 10px 12px; + display: flex; + flex-direction: column; + gap: 8px; + max-height: 48vh; + overflow: hidden; +} + +.rail-inspector .panel-section { + margin-top: 4px; + overflow-y: auto; + padding-right: 4px; + max-height: calc(48vh - 72px); +} + +.drawer-header { + padding: 4px 2px 0; + display: flex; + align-items: center; + justify-content: space-between; +} + +.control-panel { + margin-top: 0; +} + .asset-settings { background: radial-gradient(circle at 15% 20%, rgba(124, 58, 237, 0.08), transparent 40%), radial-gradient(circle at 85% 0%, rgba(59, 130, 246, 0.06), transparent 45%), @@ -727,9 +926,10 @@ body { .panel-header { display: flex; + align-items: center; justify-content: space-between; - align-items: baseline; gap: 12px; + margin-bottom: 10px; } .panel-header h4 { @@ -756,15 +956,15 @@ body { } .asset-controls-placeholder { - margin-top: 12px; + margin-top: 8px; } .selected-asset-banner { display: grid; grid-template-columns: 1fr auto; - gap: 12px; - padding: 14px; - border-radius: 12px; + gap: 10px; + padding: 10px; + border-radius: 10px; background: rgba(255, 255, 255, 0.02); border: 1px solid rgba(124, 58, 237, 0.2); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04); @@ -774,7 +974,8 @@ body { display: flex; flex-direction: column; gap: 6px; - width: 328px; + width: 100%; + min-width: 0; } .selected-asset-actions { @@ -797,7 +998,7 @@ body { display: flex; align-items: center; gap: 10px; - margin: 12px 0 4px; + margin: 8px 0 2px; } .file-input-field { @@ -921,20 +1122,24 @@ body { .asset-list { display: flex; flex-direction: column; - gap: 8px; - margin-top: 12px; + gap: 6px; + margin-top: 6px; + padding: 0; } .asset-item { display: flex; flex-direction: column; align-items: stretch; - padding: 10px 12px; - border-radius: 10px; + padding: 8px 10px; + border-radius: 9px; background: #111827; border: 1px solid #1f2937; cursor: pointer; - gap: 10px; + gap: 8px; + font-size: 13px; + line-height: 1.35; + height: 60px; } .asset-item.selected { @@ -957,7 +1162,7 @@ body { display: flex; align-items: center; justify-content: space-between; - gap: 12px; + gap: 10px; } .asset-row .meta { @@ -976,7 +1181,7 @@ body { .asset-item .actions { display: flex; - gap: 8px; + gap: 6px; } .asset-inspector .selected-asset-actions .icon-button, @@ -1029,8 +1234,8 @@ body { } .asset-preview { - width: 64px; - height: 64px; + width: 38px; + height: 38px; object-fit: contain; background: #0b1220; border: 1px solid #1f2937; diff --git a/src/main/resources/static/js/admin.js b/src/main/resources/static/js/admin.js index d159bb7..aab72a4 100644 --- a/src/main/resources/static/js/admin.js +++ b/src/main/resources/static/js/admin.js @@ -2,7 +2,6 @@ let stompClient; const canvas = document.getElementById('admin-canvas'); const ctx = canvas.getContext('2d'); const overlay = document.getElementById('admin-overlay'); -const overlayFrame = overlay?.querySelector('iframe'); let canvasSettings = { width: 1920, height: 1080 }; canvas.width = canvasSettings.width; canvas.height = canvasSettings.height; @@ -56,6 +55,8 @@ const selectedAssetIdLabel = document.getElementById('selected-asset-id'); const selectedAssetBadges = document.getElementById('selected-asset-badges'); const selectedVisibilityBtn = document.getElementById('selected-asset-visibility'); const selectedDeleteBtn = document.getElementById('selected-asset-delete'); +const canvasResolutionLabel = document.getElementById('canvas-resolution'); +const canvasScaleLabel = document.getElementById('canvas-scale'); const aspectLockState = new Map(); const commitSizeChange = debounce(() => applyTransformFromInputs(), 180); const audioUnlockEvents = ['pointerdown', 'keydown', 'touchstart']; @@ -308,11 +309,11 @@ function resizeCanvas() { canvas.style.height = `${displayHeight}px`; canvas.style.left = `${(bounds.width - displayWidth) / 2}px`; canvas.style.top = `${(bounds.height - displayHeight) / 2}px`; - if (overlayFrame) { - overlayFrame.style.width = `${displayWidth}px`; - overlayFrame.style.height = `${displayHeight}px`; - overlayFrame.style.left = `${(bounds.width - displayWidth) / 2}px`; - overlayFrame.style.top = `${(bounds.height - displayHeight) / 2}px`; + if (canvasResolutionLabel) { + canvasResolutionLabel.textContent = `${canvasSettings.width} x ${canvasSettings.height}`; + } + if (canvasScaleLabel) { + canvasScaleLabel.textContent = `${Math.round(scale * 100)}%`; } requestDraw(); } diff --git a/src/main/resources/templates/admin.html b/src/main/resources/templates/admin.html index 39931fe..607fd75 100644 --- a/src/main/resources/templates/admin.html +++ b/src/main/resources/templates/admin.html @@ -10,162 +10,198 @@
-