diff --git a/frontend/src/components/react/admin/AssetManager.tsx b/frontend/src/components/react/admin/AssetManager.tsx index d794d41..dc18a3f 100644 --- a/frontend/src/components/react/admin/AssetManager.tsx +++ b/frontend/src/components/react/admin/AssetManager.tsx @@ -61,13 +61,13 @@ export default function AssetManager({ mode = 'manage', onSelect }: Props) { const isImage = (name: string) => /\.(jpg|jpeg|png|webp|gif|svg)$/i.test(name); return ( -
+
{alert && (
@@ -77,31 +77,31 @@ export default function AssetManager({ mode = 'manage', onSelect }: Props) { {/* Upload Zone */}
fileRef.current?.click()} onDragOver={e => { e.preventDefault(); e.stopPropagation(); }} onDrop={e => { e.preventDefault(); e.stopPropagation(); if (e.dataTransfer.files.length) handleUpload(e.dataTransfer.files); }} > { if (e.target.files?.length) handleUpload(e.target.files); }} /> -
+
-

Click or drag to upload assets

+

Click or drag to upload assets

Any file type ยท up to 50 MB

{/* Grid */} {assets.length === 0 ? ( -
No assets uploaded yet.
+
No assets uploaded yet.
) : ( -
+
{assets.map(asset => (
-
+
{isImage(asset.name) ? ( {asset.name} ) : ( @@ -111,7 +111,7 @@ export default function AssetManager({ mode = 'manage', onSelect }: Props) {
)} {/* Hover overlay */} -
+
{mode === 'select' && onSelect && (
-
{asset.name}
+
{asset.name}
))}
diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css index bd6dccc..0528b16 100644 --- a/frontend/src/styles/global.css +++ b/frontend/src/styles/global.css @@ -2413,6 +2413,21 @@ html.cs-cursor-on.cybersigil .cs-cursor { opacity: 1; } content: "\00a0]"; color: color-mix(in srgb, currentColor 70%, transparent); } +/* Icon-only buttons get no brackets โ€” `[ icon ]` reads odd and overflows + * fixed-width chrome. */ +.cybersigil .btn--icon::before, +.cybersigil .btn--icon::after { content: none; } +/* Asset-tile hover actions: drop brackets + tighten so Insert+Delete fit + * the small square tiles. */ +.cybersigil .asset-actions { gap: 0.4rem; } +.cybersigil .asset-actions .btn::before, +.cybersigil .asset-actions .btn::after { content: none; } +.cybersigil .asset-actions .btn { + letter-spacing: 0.03em; + font-size: 0.66rem; + padding: 0 0.5rem; +} +.cybersigil .asset-actions .btn--icon { padding: 0; } .cybersigil .btn--primary { color: var(--rosewater); border-color: var(--mauve); @@ -2804,6 +2819,135 @@ html.cs-cursor-on.cybersigil .cs-cursor { opacity: 1; } font-family: var(--font-sans) !important; } +/* Asset library โ€” a file-sector readout. Dashed drop-sector, scanline tile + * panels with a thorny sigil growth, `/path` filename bars, log-line alerts. */ +.cybersigil .asset-alert { + border-radius: 0 !important; + font-family: var(--font-sans) !important; + font-style: normal !important; + text-transform: uppercase; + letter-spacing: 0.08em; + font-size: 0.74rem !important; +} +.cybersigil .asset-alert::before { + font-weight: 700; + margin-right: 0.5em; +} +.cybersigil .asset-alert--ok::before { content: ">> "; } +.cybersigil .asset-alert--err::before { content: "!! "; } + +.cybersigil .asset-drop { + border-style: dashed !important; + border-color: color-mix(in srgb, var(--sky) 55%, transparent) !important; + background: + repeating-linear-gradient( + 0deg, + rgba(0, 0, 0, 0) 0 2px, + color-mix(in srgb, var(--sky) 6%, transparent) 2px 3px, + rgba(0, 0, 0, 0) 3px 4px + ), + color-mix(in srgb, var(--surface0) 74%, transparent) !important; +} +.cybersigil .asset-drop:hover { + border-color: var(--mauve) !important; + box-shadow: 0 0 0 1px color-mix(in srgb, var(--mauve) 40%, transparent); +} +.cybersigil .asset-drop svg { stroke-width: 1.5; } +.cybersigil .asset-drop-title { + font-family: var(--font-display) !important; + font-style: normal !important; + text-transform: uppercase; + letter-spacing: 0.04em; + text-shadow: -1px 0 0 var(--sky), 1px 0 0 var(--mauve); +} +.cybersigil .asset-drop-title::before { + content: "> "; + color: var(--sky); +} +.cybersigil .asset-drop-title::after { + content: "_"; + color: var(--mauve); + animation: cs-blink 1.05s steps(1, jump-none) infinite; +} + +.cybersigil .asset-empty { + font-family: var(--font-sans); + font-style: normal; + text-transform: uppercase; + letter-spacing: 0.16em; + color: var(--subtext0); +} +.cybersigil .asset-empty::before { content: "// "; color: var(--sky); opacity: 0.7; } + +.cybersigil .asset-tile { + border-radius: 0 !important; + border-color: color-mix(in srgb, var(--sky) 26%, transparent) !important; + box-shadow: + inset 0 0 0 1px color-mix(in srgb, var(--sky) 16%, transparent), + 0 0 0 1px color-mix(in srgb, var(--sky) 10%, transparent) !important; + transition: border-color 0.16s ease, box-shadow 0.16s ease, transform 0.16s ease; +} +.cybersigil .asset-tile::after { + content: ""; + position: absolute; + top: 3px; + left: 3px; + width: 26px; + height: 26px; + z-index: 2; + background-color: color-mix(in srgb, var(--sky) 70%, transparent); + -webkit-mask: var(--cs-corner) center / contain no-repeat; + mask: var(--cs-corner) center / contain no-repeat; + pointer-events: none; + transition: background-color 0.16s ease; +} +.cybersigil .asset-tile:hover { + border-color: var(--mauve) !important; + transform: translateY(-2px); + box-shadow: + inset 0 0 0 1px color-mix(in srgb, var(--mauve) 36%, transparent), + 4px 4px 0 0 var(--mauve) !important; +} +.cybersigil .asset-tile:hover::after { + background-color: var(--mauve); +} +.cybersigil .asset-thumb { + background: + repeating-linear-gradient( + 0deg, + rgba(0, 0, 0, 0) 0 2px, + color-mix(in srgb, var(--sky) 7%, transparent) 2px 3px, + rgba(0, 0, 0, 0) 3px 4px + ), + var(--mantle); +} +.cybersigil .asset-thumb > div span { + font-family: var(--font-sans) !important; + color: var(--sky); + letter-spacing: 0.1em; +} +.cybersigil .asset-tile:hover .asset-thumb img { + filter: + drop-shadow(-2px 0 0 color-mix(in srgb, var(--mauve) 60%, transparent)) + drop-shadow(2px 0 0 color-mix(in srgb, var(--sky) 60%, transparent)) + saturate(0.92) contrast(1.05); +} +.cybersigil .asset-actions { + background: color-mix(in srgb, var(--crust) 82%, transparent) !important; +} +.cybersigil .asset-name { + font-family: var(--font-sans) !important; + color: var(--sky); + border-top-color: color-mix(in srgb, var(--sky) 30%, transparent) !important; + background: var(--crust) !important; + letter-spacing: 0.02em; +} +.cybersigil .asset-name::before { content: "/"; opacity: 0.55; } +.cybersigil .asset-tile:hover .asset-name { + color: var(--mauve); + border-top-color: color-mix(in srgb, var(--mauve) 45%, transparent) !important; +} + /* Confirm dialog โ€” hard terminal halt prompt. */ .cybersigil .cdialog-panel { border-radius: 0;