diff --git a/build_simple.bat b/build_simple.bat index dee98ab4..ce66d562 100644 --- a/build_simple.bat +++ b/build_simple.bat @@ -42,7 +42,7 @@ if errorlevel 1 ( echo BUILD FAILED! echo ======================================== echo. - echo Install requirements first (two steps): + echo Install requirements first ^(two steps^): echo 1. pip install -r requirements.txt echo 2. pip install steam==1.4.4 --no-deps echo. diff --git a/build_simple_gui.bat b/build_simple_gui.bat index 0660b01f..f6b0bdd3 100644 --- a/build_simple_gui.bat +++ b/build_simple_gui.bat @@ -33,7 +33,7 @@ echo. REM Suppress pkg_resources deprecation from PyInstaller/build deps so log stays clean set PYTHONWARNINGS=ignore::UserWarning -python -m PyInstaller build_sff_gui.spec +python -m PyInstaller build_sff_gui.spec --noconfirm if errorlevel 1 ( echo. @@ -41,7 +41,7 @@ if errorlevel 1 ( echo BUILD FAILED! echo ======================================== echo. - echo Install requirements first (two steps): + echo Install requirements first ^(two steps^): echo 1. pip install -r requirements.txt echo 2. pip install steam==1.4.4 --no-deps echo. @@ -59,9 +59,9 @@ echo Folder: dist\SteaMidra_GUI\ echo Executable: dist\SteaMidra_GUI\SteaMidra_GUI.exe echo. -if exist "dist\SteaMidra_GUI\SteaMidra_GUI.exe" ( - python -c "import os; size = sum(os.path.getsize(os.path.join(r,f)) for r,d,files in os.walk('dist/SteaMidra_GUI') for f in files); print(f'Total size: {size / (1024*1024):.1f} MB')" -) +if not exist "dist\SteaMidra_GUI\SteaMidra_GUI.exe" goto :skipsize +python -c "import os; size = sum(os.path.getsize(os.path.join(r,f)) for r,d,files in os.walk('dist/SteaMidra_GUI') for f in files); print(f'Total size: {size / 1048576:.1f} MB')" +:skipsize echo. echo You can now run: dist\SteaMidra_GUI\SteaMidra_GUI.exe diff --git a/sff/webui/css/animations.css b/sff/webui/css/animations.css deleted file mode 100644 index 23805fe6..00000000 --- a/sff/webui/css/animations.css +++ /dev/null @@ -1,186 +0,0 @@ -/* SteaMidra — Transitions, Skeletons, Toasts */ - -/* ── Page transitions ───────────────────────────────── */ - -@keyframes fadeIn { - from { opacity: 0; } - to { opacity: 1; } -} - -@keyframes slideUp { - from { opacity: 0; transform: translateY(20px); } - to { opacity: 1; transform: translateY(0); } -} - -@keyframes slideDown { - from { opacity: 1; transform: translateY(0); } - to { opacity: 0; transform: translateY(16px); } -} - -@keyframes fadeOut { - from { opacity: 1; } - to { opacity: 0; } -} - -@keyframes slideInRight { - from { transform: translateX(100%); } - to { transform: translateX(0); } -} - -/* ── Loading Skeletons ──────────────────────────────── */ - -.loading-skeleton { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); - gap: 20px; -} - -.skeleton-card { - border: 1px solid var(--border); - border-radius: 10px; - height: 280px; - position: relative; - overflow: hidden; -} - -.skeleton-card::after { - content: ''; - position: absolute; - top: 0; - left: -100%; - width: 100%; - height: 100%; - background: linear-gradient( - 90deg, - transparent, - rgba(255,255,255,0.04), - transparent - ); - animation: shimmer 1.5s infinite; -} - -@keyframes shimmer { - to { left: 100%; } -} - -/* ── Loading Spinner ────────────────────────────────── */ - -.loading-spinner { - display: flex; - align-items: center; - justify-content: center; - padding: 40px; - font-size: 14px; - opacity: 0.6; -} - -.loading-spinner::before { - content: ''; - width: 20px; - height: 20px; - border: 2px solid var(--border); - border-top-color: var(--accent); - border-radius: 50%; - margin-right: 10px; - animation: spin 0.8s linear infinite; -} - -@keyframes spin { - to { transform: rotate(360deg); } -} - -/* ── Toast Notifications ────────────────────────────── */ - -.toast-container { - position: fixed; - bottom: 20px; - right: 20px; - z-index: 2000; - display: flex; - flex-direction: column-reverse; - gap: 8px; - pointer-events: none; -} - -.toast { - padding: 12px 20px; - border-radius: 8px; - font-size: 13px; - font-weight: 500; - color: #fff; - pointer-events: auto; - animation: toastIn 0.3s ease, toastOut 0.3s ease 3.7s forwards; - max-width: 360px; - box-shadow: 0 4px 16px rgba(0,0,0,0.3); - display: flex; - align-items: center; - gap: 8px; -} - -.toast-success { - background: #27ae60; -} - -.toast-error { - background: #e74c3c; -} - -.toast-info { - background: #2980b9; -} - -.toast-warning { - background: #f39c12; -} - -@keyframes toastIn { - from { - opacity: 0; - transform: translateX(40px); - } - to { - opacity: 1; - transform: translateX(0); - } -} - -@keyframes toastOut { - from { - opacity: 1; - transform: translateX(0); - } - to { - opacity: 0; - transform: translateX(40px); - } -} - -/* ── Progress bar animation ─────────────────────────── */ - -.download-progress-fill.indeterminate { - width: 30% !important; - animation: indeterminate 1.5s ease infinite; -} - -@keyframes indeterminate { - 0% { transform: translateX(-100%); } - 100% { transform: translateX(400%); } -} - -/* skeleton cards — shimmer loading placeholder (port from PR#58) */ -.skeleton-card { - height: 300px; - background: linear-gradient(90deg, var(--card-bg, #1e293b) 25%, var(--bg-secondary, #334155) 50%, var(--card-bg, #1e293b) 75%); - background-size: 200% 100%; - border-radius: 8px; - animation: skeleton-loading 2s infinite; -} - -.skeleton-card::after { - content: none; -} - -@keyframes skeleton-loading { - 0% { background-position: 200% 0; } - 100% { background-position: -200% 0; } -} diff --git a/sff/webui/css/app.css b/sff/webui/css/app.css new file mode 100644 index 00000000..3509e1f7 --- /dev/null +++ b/sff/webui/css/app.css @@ -0,0 +1,2237 @@ +:root { + --text: var(--fg); + --text-dim: color-mix(in srgb, var(--fg) 66%, transparent); + --text-faint: color-mix(in srgb, var(--fg) 42%, transparent); + --text-muted: var(--text-dim); + --text-dim-legacy: var(--text-dim); + + --surface: color-mix(in srgb, var(--card-bg) 86%, transparent); + --surface-2: color-mix(in srgb, var(--fg) 5%, transparent); + --surface-3: color-mix(in srgb, var(--fg) 9%, transparent); + --bg-secondary: var(--surface-2); + --hairline: color-mix(in srgb, var(--border) 68%, transparent); + + --accent-ghost: color-mix(in srgb, var(--accent) 10%, var(--surface-2)); + --accent-weak: color-mix(in srgb, var(--accent) 18%, var(--surface-2)); + --accent-line: color-mix(in srgb, var(--accent) 55%, var(--border)); + --accent-ring: color-mix(in srgb, var(--accent) 26%, transparent); + --accent-glow: color-mix(in srgb, var(--accent) 22%, transparent); + + --ok: #3ecf7e; + --warn: #f0b429; + --danger: #ef4a4a; + --ok-weak: color-mix(in srgb, var(--ok) 12%, transparent); + --warn-weak: color-mix(in srgb, var(--warn) 12%, transparent); + --danger-weak: color-mix(in srgb, var(--danger) 12%, transparent); + + --r-1: 6px; + --r-2: 9px; + --r-3: 13px; + --r-4: 18px; + --pill: 999px; + + --sh-1: 0 1px 2px rgba(0, 0, 0, 0.14); + --sh-2: 0 6px 20px rgba(0, 0, 0, 0.16); + --sh-3: 0 18px 48px rgba(0, 0, 0, 0.28); + + --dur: 160ms; + --dur-slow: 260ms; + --ease: cubic-bezier(0.2, 0.7, 0.3, 1); + + --sidebar-w: 212px; + --sidebar-w-mini: 66px; + --gutter: 30px; + + --font: 'Inter var', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Ubuntu, sans-serif; + --font-mono: 'Cascadia Code', 'Fira Code', ui-monospace, Consolas, monospace; +} + +*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; } + +html { -webkit-text-size-adjust: 100%; } + +body { + display: flex; + min-height: 100vh; + overflow: hidden; + background-color: var(--bg); + background-position: center; + background-repeat: no-repeat; + background-size: cover; + color: var(--text); + font-family: var(--font); + font-size: 13px; + font-weight: 450; + line-height: 1.5; + -webkit-font-smoothing: antialiased; +} + +body::before { + content: ''; + position: fixed; + inset: 0; + z-index: 0; + pointer-events: none; + background: + radial-gradient(ellipse 70% 55% at 12% 0%, color-mix(in srgb, var(--accent) 7%, transparent) 0%, transparent 58%), + radial-gradient(ellipse 60% 45% at 95% 100%, color-mix(in srgb, var(--accent) 6%, transparent) 0%, transparent 52%); +} + +h1, h2, h3, h4 { font-weight: 700; letter-spacing: -0.015em; line-height: 1.25; } +h1 { font-size: 21px; } +h2 { font-size: 15px; } +h3 { font-size: 13.5px; } +p { line-height: 1.55; } + +a { color: var(--accent); text-decoration: none; } +a:hover { text-decoration: underline; } + +code, kbd, pre { font-family: var(--font-mono); font-size: 12px; } +code { + padding: 1px 5px; + border-radius: 4px; + background: var(--surface-3); +} +pre { + padding: 11px 13px; + border: 1px solid var(--hairline); + border-radius: var(--r-2); + background: var(--surface-2); + line-height: 1.55; + overflow-x: auto; +} + +::selection { background: var(--accent-ring); } + +:where(button, input, select, textarea, [tabindex="0"]):focus-visible { + outline: 2px solid var(--accent); + outline-offset: 2px; +} + +::-webkit-scrollbar { width: 9px; height: 9px; } +::-webkit-scrollbar-track { background: transparent; } +::-webkit-scrollbar-thumb { + border: 2px solid transparent; + border-radius: var(--pill); + background: color-mix(in srgb, var(--fg) 22%, transparent); + background-clip: padding-box; +} +::-webkit-scrollbar-thumb:hover { + background: color-mix(in srgb, var(--fg) 36%, transparent); + background-clip: padding-box; +} + +.sidebar { + --sfg: var(--sidebar-fg, var(--fg)); + --sdim: color-mix(in srgb, var(--sfg) 66%, transparent); + --sline: color-mix(in srgb, var(--sfg) 16%, transparent); + position: fixed; + inset: 0 auto 0 0; + z-index: 100; + display: flex; + flex-direction: column; + width: var(--sidebar-w); + min-width: var(--sidebar-w); + height: 100vh; + border-right: 1px solid var(--sline); + background: var(--sidebar-bg); + color: var(--sfg); +} + +.sidebar-logo { + display: flex; + align-items: center; + gap: 10px; + padding: 14px 16px; +} + +.sidebar-icon { width: 26px; height: 26px; border-radius: var(--r-1); } + +.sidebar-title { + color: var(--sfg); + font-size: 14px; + font-weight: 700; + letter-spacing: -0.02em; + white-space: nowrap; +} + +.sidebar-nav { + flex: 1; + padding: 4px 10px 12px; + overflow-y: auto; + overscroll-behavior: contain; +} + +.nav-item { + position: relative; + display: flex; + align-items: center; + gap: 11px; + width: 100%; + padding: 8px 11px; + margin-bottom: 1px; + border: 0; + border-radius: var(--r-2); + background: none; + color: var(--sdim); + font: inherit; + font-size: 12.5px; + text-align: left; + white-space: nowrap; + cursor: pointer; + transition: background var(--dur) var(--ease), color var(--dur) var(--ease); +} + +.nav-item:hover { + background: color-mix(in srgb, var(--sfg) 9%, transparent); + color: var(--sfg); +} + +.nav-item.active { + background: var(--accent-weak); + color: var(--accent); + font-weight: 650; +} + +.nav-icon { + width: 17px; + height: 17px; + min-width: 17px; + flex-shrink: 0; + fill: none; + stroke: currentColor; + stroke-width: 1.8; + stroke-linecap: round; + stroke-linejoin: round; +} + +.nav-label { overflow: hidden; text-overflow: ellipsis; } + +.nav-separator { + height: 1px; + margin: 10px 4px; + background: var(--sline); +} + +.sidebar-bottom { + padding: 10px; + border-top: 1px solid var(--sline); +} + +.content { + position: relative; + z-index: 1; + flex: 1; + height: 100vh; + margin-left: var(--sidebar-w); + padding: 26px var(--gutter) 56px; + overflow-y: auto; + overflow-x: hidden; + scrollbar-gutter: stable; +} + +.page { display: none; } +.page.active { display: block; animation: fadeIn var(--dur) var(--ease); } + +.page-header { + position: relative; + display: flex; + flex-wrap: wrap; + align-items: baseline; + gap: 6px 12px; + padding-bottom: 16px; + margin-bottom: 24px; + border-bottom: 1px solid var(--hairline); +} + +.page-header h1 { font-size: 21px; font-weight: 750; } + +.page-subtitle { + flex: 1; + min-width: 160px; + color: var(--text-faint); + font-size: 12.5px; +} + +.discord-corner-link { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 5px 11px; + border: 1px solid var(--hairline); + border-radius: var(--pill); + color: var(--text-dim); + font-size: 12px; + font-weight: 600; + transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease), background var(--dur) var(--ease); +} + +.discord-corner-link:hover { + border-color: var(--accent-line); + background: var(--accent-ghost); + color: var(--accent); + text-decoration: none; +} + +.section-group { margin-bottom: 26px; } + +.section-title { + display: block; + margin-bottom: 12px; + color: var(--text-faint); + font-size: 10.5px; + font-weight: 750; + letter-spacing: 0.12em; + text-transform: uppercase; +} + +.setting-hint { + max-width: 78ch; + color: var(--text-faint); + font-size: 12px; + line-height: 1.55; +} + +.step-desc, +.option-hint { + color: var(--text-faint); + font-size: 12px; + line-height: 1.5; +} + +.step-desc { margin: -4px 0 14px; } +.option-hint { display: block; margin-top: 2px; } + +details.section-group { margin-bottom: 10px; } + +details.section-group > summary { + display: flex; + align-items: center; + gap: 9px; + padding: 9px 12px; + border: 1px solid transparent; + border-radius: var(--r-2); + list-style: none; + cursor: pointer; + user-select: none; + transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease); +} + +details.section-group > summary::-webkit-details-marker { display: none; } + +details.section-group > summary::before { + content: ''; + width: 5px; + height: 5px; + flex-shrink: 0; + border-right: 1.6px solid currentColor; + border-bottom: 1.6px solid currentColor; + transform: rotate(-45deg); + transition: transform var(--dur) var(--ease); +} + +details.section-group[open] > summary::before { transform: rotate(45deg); } + +details.section-group > summary:hover { + border-color: var(--hairline); + background: var(--surface-2); + color: var(--text-dim); +} + +details.section-group > summary .section-title { margin: 0; } + +details.section-group > summary .summary-count { + margin-left: auto; + color: var(--text-faint); + font-size: 11px; + font-variant-numeric: tabular-nums; +} + +details.section-group > :not(summary) { margin-left: 12px; margin-right: 12px; } +details.section-group > summary + * { margin-top: 12px; } +details.section-group > :last-child { margin-bottom: 16px; } + +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 7px; + min-height: 34px; + padding: 7px 15px; + border: 1px solid var(--hairline); + border-radius: var(--r-2); + background: var(--btn-bg); + color: var(--btn-fg, var(--fg)); + font: inherit; + font-size: 12.5px; + font-weight: 600; + white-space: nowrap; + cursor: pointer; + transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease); +} + +.btn:hover { border-color: var(--accent-line); background: var(--btn-hover); } +.btn:active { transform: translateY(0.5px); } +.btn:disabled { opacity: 0.45; cursor: not-allowed; } +.btn:disabled:hover { border-color: var(--hairline); background: var(--btn-bg); } + +.btn-primary { + border-color: transparent; + background: var(--accent); + color: var(--on-accent, #fff); +} +.btn-primary:hover { + border-color: transparent; + background: color-mix(in srgb, var(--accent) 86%, #fff); +} + +.btn-danger { + border-color: transparent; + background: var(--danger); + color: #fff; +} +.btn-danger:hover { + border-color: transparent; + background: color-mix(in srgb, var(--danger) 84%, #000); +} + +.btn-ghost { + border-color: transparent; + background: transparent; + color: var(--text-dim); +} +.btn-ghost:hover { background: var(--surface-2); color: var(--text); } + +.btn-lg { min-height: 42px; padding: 11px 24px; font-size: 14px; } +.btn-sm { min-height: 28px; padding: 4px 11px; font-size: 12px; } + +.btn-icon { + min-height: 30px; + width: 30px; + padding: 0; + border-color: transparent; + background: transparent; + color: var(--text-dim); +} +.btn-icon:hover { background: var(--surface-3); color: var(--text); } +.btn-icon.active { background: var(--accent); border-color: transparent; color: var(--on-accent, #fff); } +.btn-icon svg { width: 15px; height: 15px; } + +.button-row { display: flex; flex-wrap: wrap; gap: 8px; } + +.view-toggle { + display: flex; + gap: 2px; + padding: 3px; + border: 1px solid var(--hairline); + border-radius: var(--r-2); + background: var(--surface-2); +} + +input[type="text"], +input[type="password"], +input[type="number"], +input[type="search"], +textarea, +select { + width: 100%; + min-height: 34px; + padding: 7px 11px; + border: 1px solid var(--hairline); + border-radius: var(--r-2); + background: var(--input-bg); + color: var(--input-fg, var(--fg)); + font: inherit; + font-size: 12.5px; + transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease); +} + +input::placeholder { color: var(--text-faint); } + +input:focus, select:focus, textarea:focus { + outline: none; + border-color: var(--accent); + box-shadow: 0 0 0 3px var(--accent-ghost); +} + +input[readonly] { color: var(--text-dim); } + +input[type="checkbox"], input[type="radio"] { + width: 15px; + height: 15px; + flex-shrink: 0; + accent-color: var(--accent); + cursor: pointer; +} + +input[type="color"] { + flex: 0 0 auto; + width: 64px; + height: 34px; + padding: 3px; + border: 1px solid var(--hairline); + border-radius: var(--r-2); + background: var(--input-bg); + cursor: pointer; +} + +.input-group { margin-bottom: 14px; } + +.input-group > label { + display: block; + margin-bottom: 5px; + color: var(--text-faint); + font-size: 10.5px; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.input-group > label small, +.field-label small { + font-size: inherit; + font-weight: 500; + letter-spacing: normal; + text-transform: none; +} + +.input-row { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 8px; +} + +.input-row > .btn { flex-shrink: 0; } + +.input-with-btn { display: flex; gap: 8px; } +.input-with-btn input, .input-with-btn select { flex: 1; } +.input-with-btn input[type="color"] { flex: 0 0 auto; width: 64px; } + +.radio-group, .checkbox-group { + display: flex; + flex-direction: column; + gap: 3px; + margin-bottom: 12px; +} + +.radio-option, +.checkbox-option, +.setting-checkbox, +.game-source-label { + display: grid; + grid-template-columns: auto minmax(0, 1fr); + align-items: center; + column-gap: 9px; + padding: 7px 10px; + border: 1px solid transparent; + border-radius: var(--r-2); + font-size: 12.5px; + cursor: pointer; + user-select: none; + transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease); +} + +.radio-option > input, +.checkbox-option > input, +.setting-checkbox > input, +.game-source-label > input { grid-column: 1; grid-row: 1; } + +.radio-option > :not(input), +.checkbox-option > :not(input), +.setting-checkbox > :not(input), +.game-source-label > :not(input) { grid-column: 2; } + +.radio-option:hover, +.checkbox-option:hover, +.setting-checkbox:hover, +.game-source-label:hover { + border-color: var(--hairline); + background: var(--surface-2); +} + +.game-source-row { + display: flex; + flex-wrap: wrap; + gap: 4px; + margin-bottom: 6px; +} + +.custom-select { position: relative; flex: 1; min-width: 0; } + +.custom-select-display { + display: flex; + align-items: center; + justify-content: space-between; + min-height: 34px; + padding: 7px 11px; + border: 1px solid var(--hairline); + border-radius: var(--r-2); + background: var(--input-bg); + color: var(--input-fg, var(--fg)); + font-size: 12.5px; + cursor: pointer; + user-select: none; + transition: border-color var(--dur) var(--ease); +} + +.custom-select-display:hover, +.custom-select.open .custom-select-display { border-color: var(--accent-line); } + +.custom-select-text { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.custom-select-arrow { + flex-shrink: 0; + margin-left: 8px; + color: var(--text-faint); + font-size: 10px; + line-height: 1; + transition: transform var(--dur) var(--ease); +} + +.custom-select.open .custom-select-arrow { transform: rotate(180deg); } + +.custom-select-dropdown { + position: absolute; + top: calc(100% + 5px); + left: 0; + right: 0; + z-index: 999; + max-height: 264px; + padding: 4px; + border: 1px solid var(--hairline); + border-radius: var(--r-2); + background: var(--card-bg); + box-shadow: var(--sh-3); + overflow-y: auto; +} + +.custom-select-dropdown.hidden { display: none; } + +.custom-select-option { + padding: 7px 10px; + border-radius: var(--r-1); + color: var(--text-dim); + font-size: 12.5px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + cursor: pointer; +} + +.custom-select-option:hover { background: var(--surface-3); color: var(--text); } +.custom-select-option.selected { background: var(--accent-weak); color: var(--accent); font-weight: 600; } + +.genre-chips, +.rclone-provider-chips { + display: flex; + flex-wrap: wrap; + gap: 6px; + margin-bottom: 14px; +} + +.genre-chip, +.rclone-chip { + padding: 5px 13px; + border: 1px solid var(--hairline); + border-radius: var(--pill); + background: var(--surface-2); + color: var(--text-dim); + font: inherit; + font-size: 12px; + font-weight: 600; + white-space: nowrap; + cursor: pointer; + transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease); +} + +.genre-chip:hover, +.rclone-chip:hover { border-color: var(--accent-line); color: var(--text); } + +.genre-chip.active, +.rclone-chip.active { + border-color: transparent; + background: var(--accent); + color: var(--on-accent, #fff); +} + +.action-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(214px, 1fr)); + gap: 9px; +} + +.action-grid.small { grid-template-columns: repeat(auto-fill, minmax(178px, 1fr)); } + +.action-card { + position: relative; + display: grid; + grid-template-columns: auto minmax(0, 1fr); + align-items: start; + column-gap: 11px; + padding: 13px 14px; + border: 1px solid var(--hairline); + border-radius: var(--r-3); + background: var(--surface-2); + color: var(--text); + font: inherit; + text-align: left; + cursor: pointer; + transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), transform var(--dur) var(--ease); +} + +.action-card:hover { + border-color: var(--accent-line); + background: var(--accent-ghost); + transform: translateY(-1px); +} + +.action-icon { + grid-column: 1; + grid-row: 1 / span 2; + align-self: start; + width: 19px; + height: 19px; + min-width: 19px; + margin-top: 1px; + fill: none; + stroke: currentColor; + stroke-width: 1.7; + stroke-linecap: round; + stroke-linejoin: round; + color: var(--text-faint); + transition: color var(--dur) var(--ease); +} + +.action-card:hover .action-icon { color: var(--accent); } + +.action-card > span { grid-column: 2; display: block; } + +.action-title { font-size: 12.5px; font-weight: 650; line-height: 1.35; } + +.action-desc { + margin-top: 2px; + color: var(--text-faint); + font-size: 11px; + line-height: 1.4; +} + +.action-desc.warn-achievements { color: var(--warn); font-weight: 650; } +.action-desc.safe-achievements { color: var(--ok); font-weight: 650; } + +.action-card.compact { padding: 11px 13px; align-items: center; } +.action-card.compact .action-icon { margin-top: 0; align-self: center; } + +.home-quick-row { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); + gap: 9px; + margin-bottom: 20px; +} + +.home-quick-row .action-card { + align-items: center; + padding: 14px 16px; + border-color: var(--accent-line); + background: var(--accent-ghost); +} + +.home-quick-row .action-card:hover { background: var(--accent-weak); } +.home-quick-row .action-card .action-icon { margin-top: 0; color: var(--accent); } + +.panel, +.tool-card, +.provider-section, +.cloudsaves-setup, +.settings-section, +.fixgame-step { + padding: 18px; + margin-bottom: 14px; + border: 1px solid var(--hairline); + border-radius: var(--r-3); + background: var(--surface); +} + +.panel > h2, +.tool-card > h2, +.provider-section > h2, +.cloudsaves-setup > h2, +.settings-section > h2, +.fixgame-step > h2 { margin-bottom: 12px; } + +.panel > :last-child, +.tool-card > :last-child, +.provider-section > :last-child, +.cloudsaves-setup > :last-child, +.settings-section > :last-child, +.fixgame-step > :last-child { margin-bottom: 0; } + +.tool-desc { + margin: -6px 0 14px; + color: var(--text-faint); + font-size: 12px; +} + +.hint-banner, +.info-callout { + display: flex; + align-items: flex-start; + gap: 11px; + padding: 12px 14px; + margin-bottom: 16px; + border: 1px solid var(--hairline); + border-left: 3px solid var(--accent); + border-radius: var(--r-2); + background: var(--surface-2); + color: var(--text-dim); + font-size: 12.5px; + line-height: 1.55; +} + +.info-callout { display: block; } +.info-callout strong { color: var(--text); } + +.hint-banner .hint-icon { + width: 17px; + height: 17px; + flex-shrink: 0; + margin-top: 2px; + fill: none; + stroke: var(--accent); + stroke-width: 1.8; + stroke-linecap: round; + stroke-linejoin: round; +} + +.hint-banner .hint-text { flex: 1; min-width: 0; } +.hint-banner .hint-text strong { display: block; color: var(--text); font-weight: 650; } +.hint-banner .hint-text em { color: var(--text); font-style: normal; font-weight: 650; } + +.hint-banner.is-warn { border-left-color: var(--warn); background: var(--warn-weak); } +.hint-banner.is-warn .hint-icon { stroke: var(--warn); } +.hint-banner.is-danger { border-left-color: var(--danger); background: var(--danger-weak); } +.hint-banner.is-danger .hint-icon { stroke: var(--danger); } + +.hint-inline-btn { + display: inline-flex; + align-items: center; + padding: 3px 10px; + margin-left: 4px; + border: 1px solid var(--hairline); + border-radius: var(--r-1); + background: var(--btn-bg); + color: var(--text); + font: inherit; + font-size: 11.5px; + font-weight: 600; + cursor: pointer; + transition: background var(--dur) var(--ease), color var(--dur) var(--ease); +} + +.hint-inline-btn:hover { background: var(--accent); border-color: transparent; color: var(--on-accent, #fff); } + +.faq { margin-bottom: 22px; } + +.faq-item { + border-bottom: 1px solid var(--hairline); +} + +.faq-item:first-of-type { border-top: 1px solid var(--hairline); } + +.faq-item > summary { + display: flex; + align-items: center; + gap: 10px; + padding: 11px 4px; + color: var(--text-dim); + font-size: 12.5px; + font-weight: 600; + list-style: none; + cursor: pointer; + transition: color var(--dur) var(--ease); +} + +.faq-item > summary::-webkit-details-marker { display: none; } + +.faq-item > summary::before { + content: ''; + width: 5px; + height: 5px; + flex-shrink: 0; + border-right: 1.6px solid var(--text-faint); + border-bottom: 1.6px solid var(--text-faint); + transform: rotate(-45deg); + transition: transform var(--dur) var(--ease); +} + +.faq-item[open] > summary { color: var(--accent); } +.faq-item[open] > summary::before { border-color: var(--accent); transform: rotate(45deg); } +.faq-item > summary:hover { color: var(--text); } + +.faq-body { + padding: 0 4px 14px 19px; + color: var(--text-faint); + font-size: 12.5px; + line-height: 1.6; +} + +.faq-body em { color: var(--text-dim); font-style: normal; font-weight: 650; } +.faq-body > * + * { margin-top: 8px; } + +.modal { + position: fixed; + inset: 0; + z-index: 1000; + display: flex; + align-items: center; + justify-content: center; + padding: 24px; +} + +.modal.hidden { display: none; } +.modal.modal-hiding { pointer-events: none; animation: fadeOut 140ms var(--ease) forwards; } + +.modal-overlay { + position: absolute; + inset: 0; + background: rgba(0, 0, 0, 0.55); + backdrop-filter: blur(3px); +} + +.modal-content { + position: relative; + display: flex; + flex-direction: column; + width: min(520px, 100%); + max-height: min(86vh, 900px); + border: 1px solid var(--hairline); + border-radius: var(--r-4); + background: var(--card-bg); + box-shadow: var(--sh-3); + overflow: hidden; + animation: slideUp 180ms var(--ease); +} + +.modal.modal-hiding .modal-content { animation: slideDown 140ms var(--ease) forwards; } + +.modal-content.modal-lg { width: min(760px, 100%); } +.modal-content.modal-xl { width: min(920px, 100%); } + +.modal-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + flex-shrink: 0; + padding: 15px 18px; + border-bottom: 1px solid var(--hairline); +} + +.modal-header h2 { font-size: 15px; font-weight: 700; } + +.modal-close { + width: 28px; + height: 28px; + flex-shrink: 0; + border: 0; + border-radius: var(--r-1); + background: none; + color: var(--text-faint); + font-size: 20px; + line-height: 1; + cursor: pointer; + transition: background var(--dur) var(--ease), color var(--dur) var(--ease); +} + +.modal-close:hover { background: var(--surface-3); color: var(--text); } + +.modal-body { + flex: 1; + padding: 18px; + overflow-y: auto; +} + +.modal-body > * + * { margin-top: 12px; } + +.modal-footer { + display: flex; + flex-shrink: 0; + flex-wrap: wrap; + justify-content: flex-end; + gap: 8px; + padding: 13px 18px; + border-top: 1px solid var(--hairline); +} + +.tab-strip { + display: flex; + flex-wrap: wrap; + gap: 5px; + padding-bottom: 14px; + margin-bottom: 4px; + border-bottom: 1px solid var(--hairline); +} + +.eac-tab { + padding: 5px 11px; + border: 1px solid var(--hairline); + border-radius: var(--pill); + background: var(--surface-2); + color: var(--text-dim); + font: inherit; + font-size: 11.5px; + font-weight: 600; + cursor: pointer; + transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease); +} + +.eac-tab:hover { border-color: var(--accent-line); color: var(--text); } +.eac-tab-active { border-color: transparent; background: var(--accent); color: var(--on-accent, #fff); } + +.eac-page > * + * { margin-top: 10px; } +.eac-page h3 { color: var(--text); } +.eac-page ol, .eac-page ul { padding-left: 20px; line-height: 1.75; } +.eac-page li::marker { color: var(--text-faint); } + +.download-option, +.library-option { + display: flex; + align-items: flex-start; + gap: 13px; + width: 100%; + padding: 13px 15px; + border: 1px solid var(--hairline); + border-radius: var(--r-3); + background: var(--surface-2); + color: var(--text); + font: inherit; + text-align: left; + cursor: pointer; + transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease); +} + +.download-option:hover, +.library-option:hover { border-color: var(--accent-line); background: var(--accent-ghost); } + +.library-option { align-items: center; } + +.library-list, .downloads-list { + display: flex; + flex-direction: column; + gap: 7px; +} + +.dl-icon { flex-shrink: 0; font-size: 22px; line-height: 1.2; } +.dl-info { display: flex; flex-direction: column; gap: 3px; } +.dl-title { font-size: 13px; font-weight: 650; } +.dl-desc { color: var(--text-faint); font-size: 11.5px; } + +.dl-source-picker { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 7px; + padding: 9px 11px; + border: 1px solid var(--hairline); + border-radius: var(--r-2); + background: var(--surface-2); +} + +.dl-source-label { + flex-shrink: 0; + margin-right: 2px; + color: var(--text-faint); + font-size: 11px; + font-weight: 700; + letter-spacing: 0.06em; + text-transform: uppercase; +} + +.dl-source-option { + display: flex; + align-items: center; + gap: 6px; + padding: 4px 12px; + border: 1px solid var(--hairline); + border-radius: var(--pill); + color: var(--text-dim); + font-size: 12px; + font-weight: 600; + cursor: pointer; + user-select: none; + transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease), background var(--dur) var(--ease); +} + +.dl-source-option:has(input:checked) { + border-color: var(--accent-line); + background: var(--accent-ghost); + color: var(--accent); +} + +.dl-source-option input[type="radio"] { display: none; } + +.pick-list { + max-height: 320px; + padding: 5px; + border: 1px solid var(--hairline); + border-radius: var(--r-2); + background: var(--surface-2); + overflow-y: auto; +} + +.store-controls { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 9px; + padding: 11px; + margin-bottom: 12px; + border: 1px solid var(--hairline); + border-radius: var(--r-3); + background: var(--surface); +} + +.search-bar { display: flex; flex: 1; gap: 8px; min-width: 250px; } +.search-bar input { flex: 1; min-height: 36px; } + +.store-options { + display: flex; + align-items: center; + gap: 7px; + margin-left: auto; +} + +.store-options .custom-select { flex: 0 0 auto; width: auto; min-width: 152px; } +.profile-controls .custom-select { flex: 0 0 auto; width: auto; min-width: 176px; } +.settings-section .input-group .custom-select { width: auto; max-width: 264px; } + +#store-provider-status { + margin: 0 0 8px; + padding-inline: 2px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +#store-provider-status:empty { display: none; } + +.store-select-bar { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 8px 12px; + padding: 9px 11px; + margin-bottom: 12px; + border: 1px solid var(--accent-line); + border-radius: var(--r-2); + background: var(--accent-ghost); + font-size: 12px; +} + +.store-select-bar.hidden { display: none; } +.store-select-bar > .btn:first-of-type { margin-left: auto; } + +.store-select-sources { + display: inline-flex; + align-items: center; + flex-wrap: wrap; + gap: 4px 10px; +} + +.store-select-sources > span { color: var(--text-faint); } +.store-select-sources label { display: inline-flex; align-items: center; gap: 5px; cursor: pointer; } + +.connect-banner { + padding: 22px; + margin-bottom: 18px; + border: 1px solid var(--accent-line); + border-radius: var(--r-3); + background: var(--accent-ghost); + text-align: center; +} + +.connect-banner p { margin-bottom: 10px; color: var(--text-dim); } +.banner-submsg { color: var(--text-faint); font-size: 12px; } + +.connect-form { + display: flex; + gap: 8px; + max-width: 420px; + margin: 14px auto 0; +} + +.connect-form input { flex: 1; } + +.library-controls { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 8px; + margin-bottom: 16px; +} + +.library-search { flex: 1; min-width: 170px; max-width: 320px; } + +#library-filter-managed.active { + border-color: transparent; + background: var(--accent); + color: var(--on-accent, #fff); +} + +.disk-info-wrap { + display: flex; + align-items: center; + gap: 6px; + margin-left: auto; + white-space: nowrap; +} + +.disk-info-icon { width: 13px; height: 13px; flex-shrink: 0; color: var(--text-faint); } +.disk-info-text { color: var(--text-faint); font-size: 11.5px; white-space: nowrap; } +.disk-drive-custom { flex: 0 0 auto; min-width: 0; } +.disk-drive-custom .custom-select-display { min-height: 26px; padding: 2px 8px; font-size: 11.5px; } +.disk-drive-custom .custom-select-dropdown { min-width: 62px; } + +.pagination { + display: flex; + align-items: center; + justify-content: center; + gap: 14px; + margin-top: 24px; +} + +.page-info { color: var(--text-faint); font-size: 12.5px; font-variant-numeric: tabular-nums; } + +.game-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(212px, 1fr)); + gap: 14px; +} + +.game-card { + position: relative; + display: flex; + flex-direction: column; + border: 1px solid var(--hairline); + border-radius: var(--r-3); + background: var(--surface); + cursor: pointer; + overflow: hidden; + contain: layout style; + transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease); +} + +.game-card:hover { + border-color: var(--accent-line); + box-shadow: 0 10px 28px var(--accent-glow); + transform: translateY(-3px); +} + +.game-card:focus-visible, +.game-list-item:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; } + +.game-card.stagger-in { animation: cardIn 240ms var(--ease) backwards; } + +.game-card-img, +.game-card-img-placeholder { + display: block; + width: 100%; + height: 112px; + background: var(--surface-3); + object-fit: cover; +} + +.game-card-img-placeholder { + display: flex; + align-items: center; + justify-content: center; +} + +.game-card-img-placeholder svg { + width: 34px; + height: 34px; + fill: none; + stroke: var(--text-faint); + stroke-width: 1.5; + stroke-linecap: round; + stroke-linejoin: round; +} + +.game-card-body { flex: 1; padding: 11px 12px 8px; } + +.game-card-name { + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + margin-bottom: 3px; + font-size: 12.5px; + font-weight: 650; + line-height: 1.35; + overflow: hidden; +} + +.game-card-appid { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + color: var(--text-faint); + font-size: 11px; + font-variant-numeric: tabular-nums; +} + +.game-card-meta { margin-top: 2px; color: var(--text-faint); font-size: 11px; } + +.game-card-actions { + display: flex; + flex-wrap: wrap; + gap: 5px; + padding: 0 12px 11px; +} + +.game-card-actions .btn { + flex: 1; + min-width: 0; + min-height: 27px; + padding: 4px 9px; + font-size: 11.5px; +} + +.game-card-badges { + position: absolute; + top: 7px; + right: 7px; + display: flex; + gap: 4px; + z-index: 2; +} + +.badge { + padding: 2px 7px; + border-radius: var(--r-1); + font-size: 9.5px; + font-weight: 800; + letter-spacing: 0.05em; + text-transform: uppercase; + color: #fff; + backdrop-filter: blur(4px); +} + +.badge-available { background: rgba(46, 190, 120, 0.92); } +.badge-downloaded { background: rgba(52, 140, 220, 0.92); } +.badge-nsfw { background: rgba(220, 70, 60, 0.92); } +.badge-drm { + margin-left: auto; + border: 1px solid var(--danger); + background: color-mix(in srgb, var(--danger) 20%, transparent); + color: var(--danger); + backdrop-filter: none; +} + +.steamidra-managed-badge { + position: absolute; + top: 7px; + left: 7px; + z-index: 3; + padding: 2px 7px; + border-radius: var(--r-1); + background: var(--accent); + color: var(--on-accent, #fff); + font-size: 9.5px; + font-weight: 800; + line-height: 1.5; +} + +.update-badge { + position: absolute; + top: 6px; + right: 6px; + z-index: 4; + width: 11px; + height: 11px; + border-radius: 50%; + box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.4); + cursor: pointer; + transition: transform var(--dur) var(--ease); +} + +.update-badge:hover { transform: scale(1.25); } +.update-badge-hidden { display: none; } +.update-badge-green { background: var(--ok); } +.update-badge-amber { background: var(--warn); } + +.update-popover { + width: 224px; + z-index: 1000; + padding: 12px 14px; + border: 1px solid var(--hairline); + border-radius: var(--r-2); + background: var(--card-bg); + box-shadow: var(--sh-3); + color: var(--text); + font-size: 12px; +} + +.update-popover-row { display: flex; justify-content: space-between; gap: 10px; margin-bottom: 5px; } +.update-popover-row b { font-family: var(--font-mono); font-weight: 600; } +.update-popover-check { width: 100%; margin-top: 8px; } + +.game-card.card-selected, +.game-list-item.card-selected { + border-color: var(--accent); + box-shadow: inset 0 0 0 1px var(--accent); +} + +.store-select-marker { + position: absolute; + top: 6px; + left: 6px; + z-index: 3; + display: flex; + align-items: center; + justify-content: center; + width: 19px; + height: 19px; + border-radius: 50%; + background: var(--accent); + color: var(--on-accent, #fff); + font-size: 11px; + font-weight: 700; +} + +.game-list { display: flex; flex-direction: column; gap: 5px; } + +.game-list-item { + position: relative; + display: flex; + align-items: center; + gap: 12px; + padding: 9px 12px; + border: 1px solid transparent; + border-radius: var(--r-2); + background: var(--surface-2); + cursor: pointer; + transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease); +} + +.game-list-item:hover { border-color: var(--accent-line); background: var(--accent-ghost); } + +.game-list-thumb { + width: 64px; + height: 36px; + flex-shrink: 0; + border-radius: var(--r-1); + background: var(--surface-3); + object-fit: cover; +} + +.game-list-info { flex: 1; min-width: 0; } +.game-list-name { font-size: 12.5px; font-weight: 650; } +.game-list-appid { color: var(--text-faint); font-size: 11px; } +.game-list-actions { display: flex; gap: 5px; flex-shrink: 0; } + +#library-grid { grid-template-columns: repeat(auto-fill, minmax(178px, 1fr)); gap: 11px; } +#library-grid .game-card-img, +#library-grid .game-card-img-placeholder { height: 92px; } + +.downloads-section { margin-bottom: 24px; } + +.downloads-section:has(> .downloads-list:empty):not(:has(.empty-state:not(.hidden))) { display: none; } + +.download-item { + display: flex; + align-items: center; + gap: 13px; + padding: 12px 14px; + border: 1px solid var(--hairline); + border-radius: var(--r-2); + background: var(--surface-2); + transition: border-color var(--dur) var(--ease); +} + +.download-item:hover { border-color: var(--accent-line); } +.download-item-info { flex: 1; min-width: 0; } +.download-item-name { margin-bottom: 3px; font-size: 12.5px; font-weight: 650; } +.download-item-status { color: var(--text-faint); font-size: 11.5px; } + +.download-progress-bar, +.backup-progress-track, +.bulk-aggregate-track { + width: 100%; + height: 4px; + border-radius: var(--pill); + background: var(--surface-3); + overflow: hidden; +} + +.download-progress-bar { margin-top: 7px; } + +.download-progress-fill, +.bulk-aggregate-fill, +#all-saves-progress-fill { + height: 100%; + width: 0%; + border-radius: var(--pill); + background: var(--accent); + transition: width var(--dur-slow) var(--ease); +} + +.download-progress-fill.indeterminate { + width: 30% !important; + animation: indeterminate 1.4s var(--ease) infinite; +} + +.queue-state-badge { + display: inline-block; + padding: 1px 7px; + margin-left: 5px; + border-radius: var(--r-1); + font-size: 9.5px; + font-weight: 700; + letter-spacing: 0.05em; + text-transform: uppercase; +} + +.queue-badge-queued { background: var(--surface-3); color: var(--text-dim); } +.queue-badge-downloading { background: var(--accent-weak); color: var(--accent); } +.queue-badge-done { background: var(--ok-weak); color: var(--ok); } +.queue-badge-failed { background: var(--danger-weak); color: var(--danger); } + +.home-layout { + display: grid; + grid-template-columns: minmax(0, 1fr) 290px; + gap: 22px; + align-items: start; +} + +.home-actions { min-width: 0; } + +.home-picker { + padding: 14px 16px; + margin-bottom: 20px; + border: 1px solid var(--hairline); + border-radius: var(--r-3); + background: var(--surface); +} + +.home-picker .section-title { margin-bottom: 10px; } +.home-game-search { max-width: 520px; margin-bottom: 8px; } + +.outside-game-row { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 8px; +} + +.outside-path-input { flex: 1; min-width: 180px; max-width: 340px; } +.outside-name-input { width: 210px; } +.outside-appid-input { width: 96px; } + +.outside-name-label, +.outside-appid-label { + display: flex; + align-items: center; + gap: 7px; + color: var(--text-faint); + font-size: 11.5px; + font-weight: 600; +} + +.home-log { + position: sticky; + top: 0; + display: flex; + flex-direction: column; + max-height: calc(100vh - 132px); + border: 1px solid var(--hairline); + border-radius: var(--r-3); + background: var(--surface); + overflow: hidden; +} + +.home-log-header { + display: flex; + align-items: center; + justify-content: space-between; + flex-shrink: 0; + padding: 9px 11px; + border-bottom: 1px solid var(--hairline); +} + +.home-log-title { + color: var(--text-faint); + font-size: 10px; + font-weight: 750; + letter-spacing: 0.12em; + text-transform: uppercase; +} + +.home-log-btns { display: flex; gap: 5px; } +.home-log-btns .btn { min-height: 24px; padding: 2px 9px; font-size: 11px; } + +.home-log-content { + flex: 1; + padding: 8px 10px; + background: color-mix(in srgb, var(--bg) 55%, transparent); + font-family: var(--font-mono); + font-size: 10.5px; + line-height: 1.55; + overflow-y: auto; +} + +.log-line { padding: 1px 3px; white-space: pre-wrap; word-break: break-word; } +.log-line .log-ts { color: var(--text-faint); } +.log-line .log-tag { font-weight: 700; } +.log-line.log-debug, .log-line.log-debug .log-tag { color: var(--text-faint); } +.log-line.log-info, .log-line.log-info .log-tag { color: var(--text-dim); } +.log-line.log-warning, .log-line.log-warning .log-tag { color: var(--warn); } +.log-line.log-error, .log-line.log-error .log-tag { color: var(--danger); } + +.home-footer { padding: 18px 0 0; text-align: center; } + +.bulk-drop-zone { + padding: 22px 18px; + margin-top: 10px; + border: 1.5px dashed var(--hairline); + border-radius: var(--r-3); + background: var(--surface-2); + color: var(--text-dim); + font-size: 12.5px; + text-align: center; + user-select: none; + transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease); +} + +.bulk-drop-zone:hover, +.bulk-drop-zone.bulk-drop-active { border-color: var(--accent); background: var(--accent-ghost); } + +.bulk-drop-zone-icon { display: block; margin-bottom: 5px; color: var(--text-faint); font-size: 24px; line-height: 1; } + +.bulk-aggregate-progress, +.bulk-results-panel, +.backup-progress { + padding: 11px 13px; + margin-top: 12px; + border: 1px solid var(--hairline); + border-radius: var(--r-2); + background: var(--surface-2); +} + +.backup-progress { display: flex; flex-direction: column; gap: 7px; margin-bottom: 14px; } + +.bulk-aggregate-header, +.backup-progress-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; + margin-bottom: 6px; + font-size: 12px; +} + +.backup-progress-header { margin-bottom: 0; } +.backup-progress-header span:first-child { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; } +.backup-progress-header span:last-child { flex-shrink: 0; color: var(--text-faint); font-size: 11.5px; } + +.backup-progress-stats { display: flex; gap: 14px; color: var(--text-faint); font-size: 11.5px; } +#all-saves-progress-ok { color: var(--ok); } +#all-saves-progress-fail { color: var(--danger); } + +.bulk-results-title { margin-bottom: 7px; color: var(--text-faint); font-size: 11px; font-weight: 750; letter-spacing: 0.1em; text-transform: uppercase; } + +.bulk-results-list { + max-height: 220px; + font-family: var(--font-mono); + font-size: 11px; + line-height: 1.55; + list-style: none; + overflow-y: auto; +} + +.bulk-result-item { padding: 2px 3px; border-bottom: 1px solid var(--hairline); word-break: break-all; } +.bulk-result-item:last-child { border-bottom: none; } +.bulk-result-ok { color: var(--ok); } +.bulk-result-fail { color: var(--danger); } +.bulk-result-skipped { color: var(--warn); } + +.fixgame-layout { max-width: 760px; } +.fixgame-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 4px; } + +.provider-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(128px, 1fr)); + gap: 8px; + margin-bottom: 14px; +} + +.provider-card { + display: flex; + flex-direction: column; + align-items: center; + gap: 3px; + padding: 13px 9px; + border: 1px solid var(--hairline); + border-radius: var(--r-2); + background: var(--surface-2); + color: var(--text); + text-align: center; + cursor: pointer; + user-select: none; + transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease); +} + +.provider-card:hover { border-color: var(--accent-line); background: var(--accent-ghost); } +.provider-card.active { border-color: var(--accent); background: var(--accent-weak); color: var(--accent); } + +.provider-icon { + width: 21px; + height: 21px; + margin-bottom: 3px; + fill: none; + stroke: currentColor; + stroke-width: 1.7; + stroke-linecap: round; + stroke-linejoin: round; +} + +.provider-name { font-size: 12.5px; font-weight: 650; } +.provider-desc { color: var(--text-faint); font-size: 10.5px; } +.provider-card.active .provider-desc { color: inherit; opacity: 0.8; } +.provider-config { margin-top: 4px; animation: fadeIn var(--dur) var(--ease); } + +.cloudsaves-actions, +.all-saves-actions { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 14px; +} + +.all-saves-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 12px; } +.cloudsaves-allsaves { margin-top: 24px; } +.restore-panel { margin-top: 14px; } + +.settings-grid { + columns: 2; + column-gap: 16px; +} + +.settings-grid > .settings-section { + break-inside: avoid; + display: inline-block; + width: 100%; + margin: 0 0 16px; +} + +.settings-grid > .settings-wide { + column-span: all; + display: block; +} + +.settings-section > h2 { + margin-bottom: 2px; + color: var(--text); + font-size: 14px; + font-weight: 700; + letter-spacing: -0.01em; + text-transform: none; + opacity: 1; +} + +.settings-blurb { + margin-bottom: 16px; + color: var(--text-faint); + font-size: 11.5px; +} + +.settings-wide .checkbox-grid, +.settings-wide .checkbox-group { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 4px 12px; +} + +.theme-grid { display: block; margin-bottom: 18px; } + +.theme-studio { + display: grid; + grid-template-columns: minmax(190px, 0.5fr) minmax(320px, 2fr); + align-items: start; + gap: 16px; +} + +.theme-current { + display: flex; + flex-direction: column; + min-width: 0; + padding: 11px; + border: 1px solid var(--hairline); + border-radius: var(--r-3); + background: var(--surface-2); +} + +.theme-current-preview { + --theme-preview-bg: #2d2d2d; + --theme-preview-accent: #4a9eff; + position: relative; + display: flex; + height: 142px; + border-radius: var(--r-2); + background-color: var(--theme-preview-bg); + background-position: center; + background-size: cover; + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08); + overflow: hidden; +} + +.theme-current-preview::after { + content: ''; + position: absolute; + inset: 0; + background: linear-gradient(125deg, transparent 38%, color-mix(in srgb, var(--theme-preview-accent) 24%, transparent)); + pointer-events: none; +} + +.theme-preview-sidebar { width: 24%; border-right: 1px solid rgba(255, 255, 255, 0.08); background: rgba(0, 0, 0, 0.42); } + +.theme-preview-window { + z-index: 1; + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + align-content: center; + flex: 1; + gap: 8px; + padding: 20px; +} + +.theme-preview-window i { + height: 36px; + border: 1px solid rgba(255, 255, 255, 0.12); + border-radius: 6px; + background: rgba(0, 0, 0, 0.26); +} + +.theme-preview-window i:first-child { + grid-column: 1 / -1; + height: 16px; + background: var(--theme-preview-accent); +} + +.theme-current-copy { display: grid; gap: 3px; padding: 12px 3px 2px; } + +.theme-eyebrow, +.theme-card-kind { + color: var(--text-faint); + font-size: 9px; + font-weight: 750; + letter-spacing: 0.11em; + text-transform: uppercase; +} + +#theme-current-name { font-size: 14.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +#theme-current-kind { color: var(--text-faint); font-size: 11px; } + +.theme-browser { min-width: 0; } +.theme-toolbar { display: flex; gap: 8px; margin-bottom: 9px; } +#theme-search { min-width: 120px; } + +.theme-filters { + display: flex; + align-items: center; + gap: 2px; + flex-shrink: 0; + padding: 3px; + border: 1px solid var(--hairline); + border-radius: var(--r-2); +} + +.theme-filter { + padding: 5px 9px; + border: 0; + border-radius: var(--r-1); + background: transparent; + color: var(--text-faint); + font: inherit; + font-size: 10.5px; + font-weight: 600; + cursor: pointer; + transition: background var(--dur) var(--ease), color var(--dur) var(--ease); +} + +.theme-filter:hover { color: var(--text); } +.theme-filter.active { background: var(--accent); color: var(--on-accent, #fff); } + +.theme-options { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(176px, 1fr)); + gap: 6px; + max-height: 302px; + padding: 2px 5px 2px 2px; + overflow-y: auto; +} + +.theme-card { + --theme-card-bg: #222; + --theme-card-accent: #4a9eff; + display: grid; + grid-template-columns: 36px minmax(0, 1fr); + grid-template-rows: auto auto; + column-gap: 9px; + min-width: 0; + padding: 7px; + border: 1px solid var(--hairline); + border-radius: var(--r-2); + background: var(--surface-2); + color: var(--text); + font: inherit; + text-align: left; + cursor: pointer; + transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease), transform var(--dur) var(--ease); +} + +.theme-card:hover { + border-color: color-mix(in srgb, var(--theme-card-accent) 70%, var(--hairline)); + background: var(--surface-3); + transform: translateY(-1px); +} + +.theme-card.active { + border-color: var(--theme-card-accent); + background: color-mix(in srgb, var(--theme-card-accent) 10%, transparent); + box-shadow: 0 0 0 1px color-mix(in srgb, var(--theme-card-accent) 34%, transparent); +} + +.theme-card-visual { + grid-row: 1 / 3; + display: grid; + grid-template-columns: 9px 1fr; + gap: 3px; + width: 36px; + height: 33px; + padding: 4px; + border-radius: 5px; + background: var(--theme-card-bg); + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1); + overflow: hidden; +} + +.theme-card-visual i:first-child { grid-row: 1 / 3; background: rgba(0, 0, 0, 0.3); } +.theme-card-visual i:nth-child(2) { background: var(--theme-card-accent); } +.theme-card-visual i:nth-child(3) { background: rgba(255, 255, 255, 0.16); } + +.theme-card-label { + align-self: end; + font-size: 11px; + font-weight: 650; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.theme-empty { padding: 26px; color: var(--text-faint); text-align: center; } + +.profile-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; } +.profile-controls select { width: auto; min-width: 176px; } + +.data-table { margin-top: 14px; overflow-x: auto; } +.data-table table { width: 100%; border-collapse: collapse; } + +.data-table th, .data-table td { + padding: 9px 12px; + border-bottom: 1px solid var(--hairline); + font-size: 12.5px; + text-align: left; +} + +.data-table th { + color: var(--text-faint); + font-size: 10px; + font-weight: 750; + letter-spacing: 0.1em; + text-transform: uppercase; +} + +.data-table tbody tr:hover td { background: var(--surface-2); } + +.log-output { + margin-top: 14px; + border: 1px solid var(--hairline); + border-radius: var(--r-2); + background: var(--surface-2); + overflow: hidden; +} + +.log-output h3 { + padding: 8px 12px; + border-bottom: 1px solid var(--hairline); + color: var(--text-faint); + font-size: 10px; + font-weight: 750; + letter-spacing: 0.1em; + text-transform: uppercase; +} + +.log-output pre { + max-height: 250px; + padding: 11px 12px; + border: 0; + border-radius: 0; + background: none; + font-size: 11.5px; + white-space: pre-wrap; + word-break: break-word; + overflow-y: auto; +} + +.empty-state { + padding: 44px 20px; + color: var(--text-faint); + text-align: center; +} + +.empty-state.small { padding: 20px; } +.empty-icon { display: block; margin-bottom: 10px; opacity: 0.7; } + +.loading-skeleton { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(212px, 1fr)); + gap: 14px; +} + +.loading-skeleton.hidden { display: none; } + +.skeleton-card { + height: 218px; + border-radius: var(--r-3); + background: linear-gradient(100deg, var(--surface-2) 30%, var(--surface-3) 50%, var(--surface-2) 70%); + background-size: 220% 100%; + animation: skeleton 1.6s linear infinite; +} + +.loading-spinner { + display: flex; + align-items: center; + justify-content: center; + padding: 36px; + color: var(--text-faint); + font-size: 13px; +} + +.loading-spinner::before { + content: ''; + width: 17px; + height: 17px; + margin-right: 10px; + border: 2px solid var(--hairline); + border-top-color: var(--accent); + border-radius: 50%; + animation: spin 0.7s linear infinite; +} + +.spinner { display: inline-block; vertical-align: middle; color: currentColor; animation: spin 0.8s linear infinite; } + +.toast-container { + position: fixed; + right: 20px; + bottom: 20px; + z-index: 2000; + display: flex; + flex-direction: column-reverse; + gap: 8px; + pointer-events: none; +} + +.toast { + display: flex; + align-items: center; + gap: 9px; + max-width: 380px; + padding: 11px 16px; + border: 1px solid var(--hairline); + border-left: 3px solid var(--accent); + border-radius: var(--r-2); + background: var(--card-bg); + box-shadow: var(--sh-3); + color: var(--text); + font-size: 12.5px; + font-weight: 550; + pointer-events: auto; + animation: toastIn 240ms var(--ease), toastOut 300ms var(--ease) 3.7s forwards; +} + +.toast-success { border-left-color: var(--ok); } +.toast-error { border-left-color: var(--danger); } +.toast-info { border-left-color: var(--accent); } +.toast-warning { border-left-color: var(--warn); } + +.hidden { display: none !important; } + +.row { display: flex; align-items: center; gap: 8px; } +.row-top { display: flex; align-items: flex-start; gap: 8px; } +.row-wrap { flex-wrap: wrap; } +.col { display: flex; flex-direction: column; gap: 8px; } +.gap-lg { gap: 16px; } +.grow { flex: 1; min-width: 0; } +.no-shrink { flex-shrink: 0; } +.push { margin-left: auto; } + +.muted { color: var(--text-dim); } +.faint { color: var(--text-faint); } +.tiny { font-size: 11.5px; } +.mono { font-family: var(--font-mono); } +.center { text-align: center; } +.prewrap { white-space: pre-wrap; } +.nowrap { white-space: nowrap; } + +.mt-0 { margin-top: 0; } +.mt-1 { margin-top: 8px; } +.mt-2 { margin-top: 14px; } +.mb-0 { margin-bottom: 0; } +.mb-1 { margin-bottom: 8px; } +.mb-2 { margin-bottom: 14px; } +.flush { margin: 0; } + +.w-narrow { max-width: 500px; } +.w-mid { max-width: 640px; } +.w-xs { width: 104px; flex: 0 0 auto; } +.w-2xs { width: 46px; flex: 0 0 auto; } +.scroll-y { max-height: 320px; overflow-y: auto; } + +.status-line { min-height: 18px; color: var(--text-faint); font-size: 11.5px; } +.divider-top { padding-top: 12px; margin-top: 14px; border-top: 1px solid var(--hairline); } +.footer-split { justify-content: space-between; } + +.field-label { + flex-shrink: 0; + min-width: 88px; + color: var(--text-faint); + font-size: 11px; + font-weight: 700; + letter-spacing: 0.06em; + text-transform: uppercase; +} + +.field-hint, +.section-desc { + margin-bottom: 5px; + color: var(--text-faint); + font-size: 11.5px; + line-height: 1.5; +} + +.field-static { + min-height: 34px; + padding: 7px 11px; + border: 1px solid var(--hairline); + border-radius: var(--r-2); + background: var(--input-bg); + color: var(--text-dim); + font-size: 12.5px; +} + +.inline-banner { + padding: 9px 11px; + border: 1px solid var(--accent-line); + border-radius: var(--r-2); + background: var(--accent-ghost); + font-size: 12px; +} + +.warn-text { color: var(--warn); } + +.panel-warn { border-color: color-mix(in srgb, var(--warn) 55%, var(--hairline)); } +.panel-warn-title { color: var(--warn); font-weight: 700; } + +.panel ol, .panel ul, +.modal-body ol, .modal-body ul { padding-left: 20px; line-height: 1.7; } +.panel li + li, .modal-body li + li { margin-top: 6px; } +.panel li::marker, .modal-body li::marker { color: var(--text-faint); } + +.kbd { + padding: 2px 7px; + border: 1px solid var(--hairline); + border-radius: 4px; + background: var(--btn-bg); + font-family: var(--font-mono); + font-size: 11.5px; +} + +.kbd-ok { border-color: transparent; background: var(--ok); color: #fff; } +.kbd-block { display: inline-block; margin: 4px 0; padding: 4px 9px; } + +.btn-block { justify-content: flex-start; flex-direction: column; align-items: flex-start; gap: 2px; padding: 11px 15px; text-align: left; } +.btn-sub { display: block; color: inherit; font-size: 11.5px; font-weight: 450; opacity: 0.75; } + +.avatar-box { + display: flex; + align-items: center; + justify-content: center; + width: 80px; + height: 80px; + border: 1px solid var(--hairline); + border-radius: var(--r-2); + background: var(--surface-3); + color: var(--text-faint); + object-fit: cover; +} + +body:not(.platform-win32) .platform-win, +body:not(.platform-linux) .platform-linux { display: none !important; } + +@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } +@keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } +@keyframes slideUp { from { opacity: 0; transform: translateY(12px) scale(0.99); } to { opacity: 1; transform: none; } } +@keyframes slideDown { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(10px); } } +@keyframes spin { to { transform: rotate(360deg); } } +@keyframes cardIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } } +@keyframes skeleton { from { background-position: 200% 0; } to { background-position: -20% 0; } } +@keyframes indeterminate { from { transform: translateX(-100%); } to { transform: translateX(400%); } } +@keyframes toastIn { from { opacity: 0; transform: translateX(28px); } to { opacity: 1; transform: none; } } +@keyframes toastOut { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateX(28px); } } + +@media (max-width: 1180px) { + .home-layout { grid-template-columns: minmax(0, 1fr); } + .home-log { position: static; max-height: 220px; } +} + +@media (max-width: 1040px) { + .theme-studio { grid-template-columns: 1fr; } + .theme-current { display: grid; grid-template-columns: minmax(170px, 0.8fr) 1fr; align-items: center; } + .theme-current-preview { height: 118px; } +} + +@media (max-width: 860px) { + :root { --gutter: 20px; } + .sidebar { width: var(--sidebar-w-mini); min-width: var(--sidebar-w-mini); } + .sidebar-title { display: none; } + .sidebar-logo, .nav-item { justify-content: center; padding-inline: 10px; } + .nav-label { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + border: 0; + clip: rect(0, 0, 0, 0); + overflow: hidden; + white-space: nowrap; + } + .content { margin-left: var(--sidebar-w-mini); } + .settings-grid { columns: 1; } + .theme-options { grid-template-columns: repeat(2, minmax(0, 1fr)); } + .store-options { width: 100%; margin-left: 0; } + .store-options .custom-select { flex: 1; } + .cloudsaves-actions { grid-template-columns: 1fr; } +} + +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } +} diff --git a/sff/webui/css/cards.css b/sff/webui/css/cards.css deleted file mode 100644 index fdaed214..00000000 --- a/sff/webui/css/cards.css +++ /dev/null @@ -1,283 +0,0 @@ -/* SteaMidra — Game Card Grid + Hover Effects */ - -.game-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); - gap: 20px; - padding: 0; -} - -.game-card { - background: var(--card-bg); - border: 1px solid var(--border); - border-radius: 10px; - overflow: hidden; - cursor: pointer; - transition: transform 0.25s ease, box-shadow 0.25s ease; - position: relative; - will-change: transform; - contain: layout style; -} - -.game-card:hover { - transform: translateY(-4px) scale(1.02); - box-shadow: 0 12px 30px rgba(0, 0, 0, 0.4); -} - -.game-card-img { - width: 100%; - height: 160px; - object-fit: cover; - background: var(--bg); - display: block; -} - -.game-card-img-placeholder { - width: 100%; - height: 160px; - background: var(--bg); - display: flex; - align-items: center; - justify-content: center; - opacity: 0.3; -} - -.game-card-img-placeholder svg { - width: 48px; - height: 48px; - stroke: var(--fg); - fill: none; - stroke-width: 1.5; - stroke-linecap: round; - stroke-linejoin: round; -} - -.game-card-badges { - position: absolute; - top: 8px; - right: 8px; - display: flex; - gap: 4px; -} - -.badge { - padding: 2px 8px; - border-radius: 4px; - font-size: 10px; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.5px; -} - -.badge-available { - background: rgba(46, 204, 113, 0.9); - color: #fff; -} - -.badge-downloaded { - background: rgba(52, 152, 219, 0.9); - color: #fff; -} - -.badge-nsfw { - background: rgba(231, 76, 60, 0.9); - color: #fff; -} - -.badge-drm { - background: rgba(30, 30, 30, 0.95); - color: #ff5555; - border: 1px solid #ff4444; - border-radius: 3px; - font-size: 12px; - font-weight: 800; - padding: 3px 9px; - letter-spacing: 0.4px; - margin-left: auto; -} - -.game-card-body { - padding: 12px 14px; -} - -.game-card-name { - font-size: 14px; - font-weight: 600; - line-height: 1.3; - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; - margin-bottom: 4px; -} - -.game-card-appid { - font-size: 11px; - opacity: 0.5; - display: flex; - align-items: center; - justify-content: space-between; - gap: 8px; -} - -.game-card-meta { - font-size: 11px; - opacity: 0.5; - margin-top: 2px; -} - -.game-card-actions { - display: flex; - gap: 6px; - padding: 8px 14px 12px; -} - -.game-card-actions .btn { - flex: 1; - padding: 6px 10px; - font-size: 12px; - text-align: center; -} - -/* ── Library Grid — prevent button overflow ─────────── */ - -#library-grid .game-card-actions { - flex-wrap: wrap; -} - -#library-grid .game-card-actions .btn { - flex: 0 0 auto; -} - -/* ── List View ──────────────────────────────────────── */ - -.game-list { - display: flex; - flex-direction: column; - gap: 6px; -} - -.game-list-item { - display: flex; - align-items: center; - gap: 14px; - padding: 10px 14px; - background: var(--card-bg); - border: 1px solid var(--border); - border-radius: 8px; - cursor: pointer; - transition: background 0.15s; -} - -.game-list-item:hover { - background: var(--btn-bg); -} - -.game-list-thumb { - width: 80px; - height: 45px; - object-fit: cover; - border-radius: 4px; - background: var(--bg); - flex-shrink: 0; -} - -.game-list-info { - flex: 1; -} - -.game-list-name { - font-size: 13px; - font-weight: 600; -} - -.game-list-appid { - font-size: 11px; - opacity: 0.5; -} - -.game-list-actions { - display: flex; - gap: 6px; -} - -/* ── Card stagger animation ─────────────────────────── */ - -.game-card.stagger-in { - animation: cardStaggerIn 0.3s ease forwards; - opacity: 0; -} - -@keyframes cardStaggerIn { - from { - opacity: 0; - transform: translateY(12px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -/* ── 6.2.5: per-game update-available badge ─────────── */ - -.game-card { - position: relative; -} - -.update-badge { - position: absolute; - top: 6px; - right: 6px; - width: 12px; - height: 12px; - border-radius: 50%; - box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.45); - cursor: pointer; - z-index: 4; - transition: transform 0.15s ease; -} - -.update-badge:hover { - transform: scale(1.2); -} - -.update-badge-hidden { - display: none; -} - -.update-badge-green { - background: #4caf50; -} - -.update-badge-amber { - background: #ffb300; -} - -.update-popover { - background: var(--card-bg, #1c1f24); - border: 1px solid var(--border, #2c313a); - border-radius: 8px; - box-shadow: 0 12px 30px rgba(0, 0, 0, 0.4); - padding: 12px 14px; - width: 220px; - z-index: 1000; - font-size: 12px; - color: var(--text, #e6e8ec); -} - -.update-popover-row { - display: flex; - justify-content: space-between; - margin-bottom: 6px; -} - -.update-popover-row b { - font-family: ui-monospace, SFMono-Regular, monospace; - font-weight: 600; -} - -.update-popover-check { - margin-top: 8px; - width: 100%; -} diff --git a/sff/webui/css/main.css b/sff/webui/css/main.css deleted file mode 100644 index 49557ea6..00000000 --- a/sff/webui/css/main.css +++ /dev/null @@ -1,1824 +0,0 @@ -/* SteaMidra Web UI — Core Layout */ - -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -body { - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif; - background-color: var(--bg, #141414); - background-size: cover; - background-position: center; - background-repeat: no-repeat; - color: var(--fg); - display: flex; - min-height: 100vh; - overflow: hidden; -} - -a { color: var(--accent); text-decoration: none; } -a:hover { text-decoration: underline; } - -/* ── Sidebar ────────────────────────────────────────── */ - -.sidebar { - width: 200px; - min-width: 200px; - background: var(--sidebar-bg); - display: flex; - flex-direction: column; - border-right: 1px solid var(--border); - height: 100vh; - position: fixed; - left: 0; - top: 0; - z-index: 100; - transition: width 0.25s ease; -} - -.sidebar-logo { - display: flex; - align-items: center; - gap: 10px; - padding: 10px 14px; - border-bottom: 1px solid var(--border); -} - -.sidebar-icon { - width: 32px; - height: 32px; - border-radius: 6px; -} - -.sidebar-title { - font-size: 16px; - font-weight: 700; - color: var(--fg); - white-space: nowrap; -} - -.sidebar-nav { - flex: 1; - padding: 8px 0; - overflow-y: auto; -} - -.nav-item { - display: flex; - align-items: center; - gap: 10px; - width: 100%; - padding: 10px 16px; - border: none; - background: none; - color: var(--fg); - font-size: 13px; - cursor: pointer; - transition: background 0.15s, color 0.15s; - text-align: left; - position: relative; - white-space: nowrap; -} - -.nav-item:hover { - background: var(--btn-hover); -} - -.nav-item.active { - background: var(--btn-bg); - color: var(--accent); - font-weight: 600; -} - -.nav-item.active::before { - content: ''; - position: absolute; - left: 0; - top: 4px; - bottom: 4px; - width: 3px; - background: var(--accent); - border-radius: 0 3px 3px 0; -} - -.nav-icon { - width: 18px; - height: 18px; - min-width: 18px; - display: inline-block; - vertical-align: middle; - fill: none; - stroke: currentColor; - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; - flex-shrink: 0; -} - -.nav-label { - overflow: hidden; - text-overflow: ellipsis; -} - -.nav-separator { - height: 1px; - background: var(--border); - margin: 8px 12px; -} - -.sidebar-bottom { - padding: 8px 0; - border-top: 1px solid var(--border); -} - -/* ── Content Area ───────────────────────────────────── */ - -.content { - flex: 1; - margin-left: 200px; - height: 100vh; - overflow-y: auto; - overflow-x: hidden; - padding: 24px 32px 48px 32px; -} - -/* ── Pages ──────────────────────────────────────────── */ - -.page { - display: none; -} - -.page.active { - display: block; - animation: fadeIn 0.2s ease; -} - -.page-header { - margin-bottom: 24px; -} - -.page-header h1 { - font-size: 24px; - font-weight: 700; - margin-bottom: 4px; -} - -.page-subtitle { - font-size: 13px; - color: var(--fg); - opacity: 0.6; -} - -.steamidra-managed-badge { - position: absolute; - top: 8px; - left: 8px; - z-index: 3; - padding: 3px 6px; - border-radius: 6px; - background: var(--accent); - color: #fff; - font-size: 11px; - font-weight: 700; - line-height: 1; - box-shadow: 0 2px 8px rgba(0,0,0,0.28); -} - -#library-filter-managed.active { - background: var(--accent); - color: #fff; - border-color: var(--accent); -} - -/* ── Section Groups ─────────────────────────────────── */ - -.section-group { - margin-bottom: 28px; -} - -.section-title { - font-size: 15px; - font-weight: 600; - margin-bottom: 12px; - color: var(--fg); - opacity: 0.85; -} - -/* ── Action Cards ───────────────────────────────────── */ - -.action-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); - gap: 12px; -} - -.action-grid.small { - grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); - gap: 10px; -} - -.action-card { - display: flex; - flex-direction: column; - align-items: center; - gap: 6px; - padding: 18px 14px; - background: var(--card-bg); - border: 1px solid var(--border); - border-radius: 10px; - cursor: pointer; - transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease; - text-align: center; - color: var(--fg); -} - -.action-card:hover { - transform: translateY(-2px); - box-shadow: 0 6px 20px rgba(0,0,0,0.25); - border-color: var(--accent); -} - -.action-card.compact { - padding: 12px 10px; -} - -.action-icon { - width: 24px; - height: 24px; - min-width: 24px; - display: inline-block; - vertical-align: middle; - fill: none; - stroke: currentColor; - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; -} - -.action-card.compact .action-icon { - width: 20px; - height: 20px; - min-width: 20px; -} - -.action-title { - font-size: 13px; - font-weight: 600; -} - -.action-desc { - font-size: 11px; - opacity: 0.6; -} - -.action-desc.warn-achievements { - opacity: 1; - color: #f0c040; - font-weight: 600; -} - -/* Home page LC shortcut row — sits between the LumaCore notice and Select Game. - Keeps the two most-used Quick Tools shortcuts above the fold so users do not - have to scroll past the game picker to reach them. */ -.home-quick-row { - display: flex; - gap: 12px; - margin: 0 0 18px 0; - flex-wrap: wrap; -} - -.home-quick-row .action-card { - flex: 1 1 220px; - min-height: 64px; - flex-direction: row; - align-items: center; - justify-content: center; - gap: 10px; - padding: 14px 18px; -} - -.home-quick-row .action-card .action-icon { - width: 22px; - height: 22px; - min-width: 22px; -} - -.home-quick-row .action-card .action-title { - font-size: 14px; -} - -.action-desc.safe-achievements { - opacity: 1; - color: #4caf50; - font-weight: 600; -} - -/* ── Home tab hint banner (error 54 etc.) ──────────── */ - -.hint-banner { - display: flex; - align-items: flex-start; - gap: 12px; - padding: 12px 14px; - margin: 0 0 16px 0; - border: 1px solid rgba(240, 192, 64, 0.45); - border-left: 3px solid #f0c040; - border-radius: 6px; - background: rgba(240, 192, 64, 0.08); - font-size: 13px; - line-height: 1.5; -} - -.hint-banner .hint-icon { - flex-shrink: 0; - width: 20px; - height: 20px; - fill: none; - stroke: #f0c040; - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; - margin-top: 2px; -} - -.hint-banner .hint-text { - flex: 1; - color: var(--fg); - opacity: 0.92; -} - -.hint-banner .hint-text strong { - display: block; - color: #f0c040; - margin-bottom: 2px; - font-weight: 600; -} - -.hint-banner .hint-text em { - font-style: normal; - font-weight: 600; - color: var(--fg); -} - -.hint-banner .hint-inline-btn { - margin-left: 6px; - padding: 3px 10px; - border: 1px solid var(--border); - border-radius: 4px; - background: var(--btn-bg); - color: var(--fg); - font-size: 12px; - cursor: pointer; -} - -.hint-banner .hint-inline-btn:hover { - background: var(--accent); - color: #fff; -} - -.hint-toggle-btn { - flex-shrink: 0; - width: 22px; - height: 22px; - padding: 0; - border: 1px solid rgba(240, 192, 64, 0.3); - border-radius: 4px; - background: transparent; - color: #f0c040; - font-size: 14px; - line-height: 1; - cursor: pointer; - transition: transform 0.2s; - margin-top: 2px; -} - -.hint-toggle-btn:hover { - background: rgba(240, 192, 64, 0.15); -} - -.hint-banner.collapsed .hint-text { - display: none; -} - -.hint-banner.collapsed .hint-toggle-btn { - transform: rotate(180deg); -} - -/* ── EAC fix modal tabs ─────────────────────────────── */ - -#eac-guide-modal { - align-items: flex-start; - overflow-y: auto; - padding: 24px 0; -} -#eac-guide-modal .modal-content { - max-width: min(760px, 95vw); - max-height: none; - margin: auto; -} - -.eac-tab { - padding: 6px 11px; - border: 1px solid var(--border); - border-radius: 5px; - background: var(--btn-bg); - color: var(--fg); - font-size: 12px; - cursor: pointer; - transition: background 0.12s, color 0.12s, border-color 0.12s; -} - -.eac-tab:hover { - border-color: var(--accent); -} - -.eac-tab-active { - background: var(--accent); - color: #fff; - border-color: var(--accent); -} - -#eac-guide-modal .eac-page pre { - color: var(--fg); - font-family: ui-monospace, Consolas, "Courier New", monospace; - font-size: 12.5px; - overflow-x: auto; -} - -#eac-guide-modal .eac-page code { - background: rgba(0,0,0,0.25); - padding: 1px 5px; - border-radius: 3px; - font-family: ui-monospace, Consolas, "Courier New", monospace; - font-size: 12.5px; -} - -/* ── Buttons ────────────────────────────────────────── */ - -.btn { - padding: 8px 16px; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--btn-bg); - color: var(--fg); - font-size: 13px; - cursor: pointer; - transition: background 0.15s, border-color 0.15s; - white-space: nowrap; -} - -.btn:hover { - background: var(--btn-hover); -} - -.btn-primary { - background: var(--accent); - color: #fff; - border-color: var(--accent); -} - -.btn-primary:hover { - opacity: 0.85; -} - -.btn-danger { - background: #e74c3c; - color: #fff; - border-color: #c0392b; -} - -.btn-danger:hover { - background: #c0392b; -} - -.btn-lg { - padding: 12px 28px; - font-size: 15px; -} - -.btn-sm { - padding: 4px 10px; - font-size: 12px; -} - -.btn-icon { - padding: 6px 10px; - font-size: 16px; - line-height: 1; -} - -.btn-icon.active { - background: var(--accent); - color: #fff; - border-color: var(--accent); -} - -/* ── Inputs ─────────────────────────────────────────── */ - -input[type="text"], -input[type="password"], -input[type="number"], -select { - padding: 8px 12px; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--input-bg); - color: var(--fg); - font-size: 13px; - width: 100%; - transition: border-color 0.15s; -} - -input:focus, select:focus { - outline: none; - border-color: var(--accent); -} - -.input-group { - margin-bottom: 12px; -} - -.input-group label { - display: block; - font-size: 12px; - font-weight: 600; - margin-bottom: 4px; - opacity: 0.8; -} - -.input-with-btn { - display: flex; - gap: 8px; -} - -.input-with-btn input, .input-with-btn select { - flex: 1; -} - -/* ── Radio & Checkbox ───────────────────────────────── */ - -.radio-group, .checkbox-group { - display: flex; - flex-direction: column; - gap: 6px; - margin-bottom: 12px; -} - -.radio-option, .checkbox-option { - display: flex; - align-items: center; - gap: 8px; - padding: 6px 10px; - border-radius: 6px; - cursor: pointer; - font-size: 13px; - transition: background 0.15s; -} - -.radio-option:hover, .checkbox-option:hover { - background: var(--btn-bg); -} - -/* ── Custom Select Dropdown ─────────────────────────── */ - -.custom-select { - position: relative; - flex: 1; - min-width: 0; -} - -.custom-select-display { - display: flex; - align-items: center; - justify-content: space-between; - padding: 8px 12px; - background: var(--input-bg); - border: 1px solid var(--border); - border-radius: 6px; - cursor: pointer; - font-size: 13px; - color: var(--fg); - user-select: none; - transition: border-color 0.15s; -} - -.custom-select-display:hover, -.custom-select.open .custom-select-display { - border-color: var(--accent); -} - -.custom-select-text { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - flex: 1; -} - -.custom-select-arrow { - margin-left: 8px; - font-size: 11px; - line-height: 1; - opacity: 0.6; - flex-shrink: 0; - transition: transform 0.15s; -} - -.custom-select.open .custom-select-arrow { - transform: rotate(180deg); -} - -.custom-select-dropdown { - position: absolute; - top: calc(100% + 4px); - left: 0; - right: 0; - background: var(--input-bg); - border: 1px solid var(--border); - border-radius: 6px; - max-height: 260px; - overflow-y: auto; - z-index: 999; - box-shadow: 0 4px 16px rgba(0,0,0,0.35); -} - -.custom-select-dropdown.hidden { - display: none; -} - -.custom-select-option { - padding: 8px 12px; - font-size: 13px; - color: var(--fg); - cursor: pointer; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.custom-select-option:hover { - background: var(--btn-hover, rgba(255,255,255,0.08)); - color: var(--accent); -} - -.custom-select-option.selected { - color: var(--accent); - font-weight: 500; -} - -/* ── Modals ─────────────────────────────────────────── */ - -.modal { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - z-index: 1000; - display: flex; - align-items: center; - justify-content: center; -} - -.modal.hidden { - display: none; -} - -.modal.modal-hiding { - pointer-events: none; - animation: fadeOut 0.15s ease forwards; -} - -.modal-overlay { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: rgba(0,0,0,0.6); -} - -.modal-content { - position: relative; - background: var(--card-bg); - border: 1px solid var(--border); - border-radius: 12px; - max-width: 480px; - width: 90%; - max-height: 80vh; - overflow-y: auto; - animation: slideUp 0.2s ease; -} - -.modal.modal-hiding .modal-content { - animation: slideDown 0.15s ease forwards; -} - -.modal-content.modal-lg { - max-width: 700px; -} - -.modal-header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 16px 20px; - border-bottom: 1px solid var(--border); -} - -.modal-header h2 { - font-size: 17px; - font-weight: 600; -} - -.modal-close { - background: none; - border: none; - color: var(--fg); - font-size: 22px; - cursor: pointer; - opacity: 0.6; - padding: 0 4px; -} - -.modal-close:hover { opacity: 1; } - -.modal-body { - padding: 20px; -} - -.modal-footer { - padding: 12px 20px; - border-top: 1px solid var(--border); - display: flex; - justify-content: flex-end; - gap: 8px; - flex-wrap: wrap; -} - -/* ── Download Options ───────────────────────────────── */ - -.download-option { - display: flex; - align-items: flex-start; - gap: 14px; - width: 100%; - padding: 16px; - margin-bottom: 10px; - background: var(--bg); - border: 1px solid var(--border); - border-radius: 10px; - cursor: pointer; - text-align: left; - color: var(--fg); - transition: border-color 0.2s, transform 0.15s; -} - -.download-option:hover { - border-color: var(--accent); - transform: translateX(4px); -} - -.dl-icon { - font-size: 28px; - flex-shrink: 0; - margin-top: 2px; -} - -.dl-info { - display: flex; - flex-direction: column; - gap: 4px; -} - -.dl-title { - font-size: 14px; - font-weight: 600; -} - -.dl-desc { - font-size: 12px; - opacity: 0.6; -} - -/* ── Download Source Picker ─────────────────────────── */ - -.dl-source-picker { - display: flex; - align-items: center; - gap: 10px; - padding: 10px 14px; - margin-bottom: 12px; - background: var(--bg); - border: 1px solid var(--border); - border-radius: 8px; - flex-wrap: wrap; -} - -.dl-source-label { - font-size: 12px; - opacity: 0.65; - flex-shrink: 0; - margin-right: 4px; -} - -.dl-source-option { - display: flex; - align-items: center; - gap: 6px; - font-size: 13px; - font-weight: 500; - cursor: pointer; - padding: 5px 14px; - border-radius: 20px; - border: 1.5px solid var(--border); - transition: border-color 0.15s, color 0.15s; - user-select: none; -} - -.dl-source-option:has(input:checked) { - border-color: var(--accent); - color: var(--accent); -} - -.dl-source-option input[type="radio"] { - display: none; -} - -/* ── Library Selection ──────────────────────────────── */ - -.library-list { - display: flex; - flex-direction: column; - gap: 6px; -} - -.library-option { - display: flex; - align-items: center; - gap: 10px; - padding: 12px 16px; - background: var(--bg); - border: 1px solid var(--border); - border-radius: 8px; - cursor: pointer; - color: var(--fg); - transition: border-color 0.15s; -} - -.library-option:hover { - border-color: var(--accent); -} - -/* ── Store Controls ─────────────────────────────────── */ - -.store-controls { - display: flex; - gap: 12px; - margin-bottom: 20px; - flex-wrap: wrap; - align-items: center; -} - -.search-bar { - display: flex; - gap: 8px; - flex: 1; - min-width: 260px; -} - -.search-bar input { - flex: 1; -} - -.store-options { - display: flex; - gap: 8px; - align-items: center; -} - -.store-options select { - width: auto; - min-width: 160px; -} - -.store-options .custom-select { - flex: 0 0 auto; - width: auto; - min-width: 150px; -} - -.profile-controls .custom-select { - flex: 0 0 auto; - width: auto; - min-width: 180px; -} - -.settings-section .input-group .custom-select { - width: auto; - max-width: 260px; -} - -.view-toggle { - display: flex; - gap: 4px; - align-self: stretch; -} - -.view-toggle .btn { - height: 100%; -} - -.genre-chips { - display: flex; - flex-wrap: wrap; - gap: 6px; - margin-bottom: 14px; -} - -.genre-chip { - padding: 5px 14px; - border-radius: 20px; - border: 1px solid var(--border); - background: var(--card-bg); - color: var(--fg); - font-size: 12px; - cursor: pointer; - transition: background 0.15s, border-color 0.15s, color 0.15s; - white-space: nowrap; -} - -.genre-chip:hover { - border-color: var(--accent); - color: var(--accent); -} - -.genre-chip.active { - background: var(--accent); - border-color: var(--accent); - color: #fff; -} - -.connect-banner { - background: var(--card-bg); - border: 1px solid var(--accent); - border-radius: 10px; - padding: 20px; - margin-bottom: 20px; - text-align: center; -} - -.connect-banner p { - margin-bottom: 12px; - opacity: 0.8; -} - -.connect-form { - display: flex; - gap: 8px; - max-width: 400px; - margin: 0 auto; -} - -.connect-form input { flex: 1; } - -/* ── Pagination ─────────────────────────────────────── */ - -.pagination { - display: flex; - align-items: center; - justify-content: center; - gap: 16px; - margin-top: 20px; - padding: 16px 0; -} - -.page-info { - font-size: 13px; - opacity: 0.7; -} - -/* ── Data Tables ────────────────────────────────────── */ - -.data-table { - margin-top: 16px; - overflow-x: auto; -} - -.data-table table { - width: 100%; - border-collapse: collapse; -} - -.data-table th, .data-table td { - padding: 8px 12px; - text-align: left; - border-bottom: 1px solid var(--border); - font-size: 13px; -} - -.data-table th { - font-weight: 600; - opacity: 0.7; - font-size: 11px; - text-transform: uppercase; -} - -.data-table tr:hover { - background: var(--btn-bg); -} - -/* ── Log Output ─────────────────────────────────────── */ - -.log-output { - margin-top: 16px; - background: var(--bg); - border: 1px solid var(--border); - border-radius: 8px; - overflow: hidden; -} - -.log-output h3 { - font-size: 12px; - padding: 8px 12px; - border-bottom: 1px solid var(--border); - opacity: 0.7; -} - -.log-output pre { - padding: 12px; - font-family: 'Cascadia Code', 'Fira Code', Consolas, monospace; - font-size: 12px; - line-height: 1.5; - max-height: 250px; - overflow-y: auto; - white-space: pre-wrap; - word-break: break-word; -} - -/* ── Game source toggle ─────────────────────────────── */ - -.game-source-row { - display: flex; - gap: 20px; - align-items: center; - margin-bottom: 4px; -} - -.game-source-label { - display: flex; - align-items: center; - gap: 6px; - font-size: 13px; - cursor: pointer; - user-select: none; -} - -.game-source-label input[type="radio"] { - accent-color: var(--accent, #e94560); - width: 14px; - height: 14px; - cursor: pointer; -} - -.outside-game-row { - display: flex; - align-items: center; - gap: 8px; - flex-wrap: wrap; -} - -.outside-path-input { - flex: 1; - min-width: 180px; - max-width: 340px; - background: var(--bg); - color: var(--fg); - border: 1px solid var(--border); - border-radius: 6px; - padding: 6px 10px; - font-size: 13px; - opacity: 0.85; -} - -.outside-appid-label { - display: flex; - align-items: center; - gap: 6px; - font-size: 12px; - opacity: 0.8; -} - -.outside-name-label { - display: flex; - align-items: center; - gap: 6px; - font-size: 12px; - opacity: 0.9; -} - -.outside-name-input { - width: 210px; - background: var(--bg); - color: var(--fg); - border: 1px solid var(--border); - border-radius: 6px; - padding: 6px 8px; - font-size: 13px; -} - -.outside-appid-input { - width: 80px; - background: var(--bg); - color: var(--fg); - border: 1px solid var(--border); - border-radius: 6px; - padding: 6px 8px; - font-size: 13px; -} - -/* ── Home two-column layout ─────────────────────────── */ - -.home-layout { - display: flex; - gap: 20px; - align-items: flex-start; - min-height: 0; -} - -.home-actions { - flex: 1; - min-width: 0; -} - -/* ── Home mini-log panel ────────────────────────────── */ - -.home-log { - width: 300px; - flex-shrink: 0; - position: sticky; - top: 0; - background: var(--card-bg); - border: 1px solid var(--border); - border-radius: 10px; - display: flex; - flex-direction: column; - max-height: calc(100vh - 120px); - overflow: hidden; -} - -.home-log-header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 8px 12px; - border-bottom: 1px solid var(--border); - flex-shrink: 0; -} - -.home-log-title { - font-size: 12px; - font-weight: 600; - opacity: 0.8; - text-transform: uppercase; - letter-spacing: 0.05em; -} - -.home-log-btns { - display: flex; - gap: 6px; -} - -.home-log-content { - flex: 1; - overflow-y: auto; - padding: 8px 10px; - font-family: 'Cascadia Code', 'Fira Code', Consolas, monospace; - font-size: 10px; - line-height: 1.5; - background: var(--bg); -} - -.home-log-content .log-line { - padding: 0 2px; - white-space: pre-wrap; - word-break: break-all; -} - -@media (max-width: 900px) { - .home-layout { flex-direction: column; } - .home-log { width: 100%; position: static; max-height: 200px; } -} - -.log-line { - padding: 1px 4px; - white-space: pre-wrap; - word-break: break-word; -} - -.log-line .log-ts { color: #666; } -.log-line .log-tag { font-weight: bold; } -.log-line.log-debug { color: #888; } -.log-line.log-debug .log-tag { color: #888; } -.log-line.log-info { color: #e0e0e0; } -.log-line.log-info .log-tag { color: #e0e0e0; } -.log-line.log-warning { color: #f0c040; } -.log-line.log-warning .log-tag { color: #f0c040; } -.log-line.log-error { color: #f06060; } -.log-line.log-error .log-tag { color: #f06060; } - -/* ── Tool Cards ─────────────────────────────────────── */ - -.tool-card { - background: var(--card-bg); - border: 1px solid var(--border); - border-radius: 10px; - padding: 20px; - margin-bottom: 16px; -} - -.tool-card h2, .tool-card h3 { - margin-bottom: 8px; -} - -.tool-desc { - font-size: 13px; - opacity: 0.7; - margin-bottom: 16px; -} - -/* ── Fix Game ───────────────────────────────────────── */ - -.fixgame-layout { - max-width: 700px; -} - -.fixgame-step { - background: var(--card-bg); - border: 1px solid var(--border); - border-radius: 10px; - padding: 20px; - margin-bottom: 16px; -} - -.fixgame-actions { - display: flex; - gap: 12px; - margin-top: 8px; -} - -/* ── Cloud Saves ────────────────────────────────────── */ - -.provider-section { - background: var(--card-bg); - border: 1px solid var(--border); - border-radius: 10px; - padding: 20px; - margin-bottom: 16px; -} - -.provider-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); - gap: 10px; - margin-bottom: 14px; -} - -.provider-card { - background: var(--btn-bg); - border: 2px solid var(--border); - border-radius: 8px; - padding: 12px 8px; - cursor: pointer; - text-align: center; - transition: border-color 0.15s, background 0.15s; - display: flex; - flex-direction: column; - align-items: center; - gap: 4px; - user-select: none; -} - -.provider-card:hover { - border-color: var(--accent); -} - -.provider-card.active { - border-color: var(--accent); - background: var(--accent); - color: #fff; -} - -.provider-icon { - width: 24px; - height: 24px; - min-width: 24px; - display: block; - fill: none; - stroke: currentColor; - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; - margin-bottom: 4px; -} - -.provider-name { - font-size: 13px; - font-weight: 600; -} - -.provider-desc { - font-size: 11px; - opacity: 0.75; -} - -.provider-card.active .provider-desc { - opacity: 0.9; -} - -.provider-config { - margin-top: 4px; - animation: fadeIn 0.15s ease; -} - -.rclone-provider-chips { - display: flex; - flex-wrap: wrap; - gap: 6px; - margin-top: 4px; -} - -.rclone-chip { - font-size: 0.78rem; - padding: 4px 10px; - border-radius: 14px; - border: 1px solid var(--border); - background: var(--btn-bg); - color: var(--text); - cursor: pointer; - transition: border-color 0.15s, background 0.15s; - white-space: nowrap; -} - -.rclone-chip:hover { - border-color: var(--accent); - background: var(--accent); - color: #fff; -} - -.rclone-chip.active { - border-color: var(--accent); - background: var(--accent); - color: #fff; -} - -.cloudsaves-setup { - background: var(--card-bg); - border: 1px solid var(--border); - border-radius: 10px; - padding: 20px; - margin-bottom: 16px; -} - -.cloudsaves-actions { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 16px; -} - -/* ── Settings ───────────────────────────────────────── */ - -.settings-section { - background: var(--card-bg); - border: 1px solid var(--border); - border-radius: 10px; - padding: 20px; - margin-bottom: 16px; -} - -.settings-section h2 { - margin-bottom: 12px; -} - -.theme-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); - gap: 10px; -} - -.theme-swatch { - padding: 12px 8px; - border: 2px solid var(--border); - border-radius: 8px; - cursor: pointer; - text-align: center; - font-size: 12px; - font-weight: 600; - transition: border-color 0.15s, transform 0.15s; -} - -.theme-swatch:hover { - transform: scale(1.05); -} - -.theme-swatch.active { - border-color: var(--accent); -} - -.theme-swatch-photo { - text-shadow: 0 1px 4px rgba(0,0,0,0.9); -} - -.profile-controls { - display: flex; - gap: 8px; - flex-wrap: wrap; - align-items: center; -} - -.profile-controls select { - width: auto; - min-width: 180px; -} - -/* ── Downloads Page ─────────────────────────────────── */ - -.downloads-section { - margin-bottom: 24px; -} - -.downloads-list { - display: flex; - flex-direction: column; - gap: 8px; -} - -.download-item { - display: flex; - align-items: center; - gap: 14px; - padding: 14px 16px; - background: var(--card-bg); - border: 1px solid var(--border); - border-radius: 10px; -} - -.download-item-info { - flex: 1; -} - -.download-item-name { - font-size: 14px; - font-weight: 600; - margin-bottom: 4px; -} - -.download-item-status { - font-size: 12px; - opacity: 0.6; -} - -.download-progress-bar { - width: 100%; - height: 4px; - background: var(--border); - border-radius: 2px; - margin-top: 6px; - overflow: hidden; -} - -.download-progress-fill { - height: 100%; - background: var(--accent); - border-radius: 2px; - transition: width 0.3s ease; -} - -/* ── Empty States ───────────────────────────────────── */ - -.empty-state { - text-align: center; - padding: 40px 20px; - opacity: 0.5; -} - -.empty-state.small { - padding: 20px; -} - -.empty-icon { - font-size: 48px; - display: block; - margin-bottom: 12px; -} - -/* ── Home Game Search ────────────────────────────────── */ - -.home-game-search { - width: 100%; - max-width: 500px; - padding: 7px 12px; - border: 1px solid var(--border, rgba(255,255,255,0.15)); - border-radius: 6px; - background: var(--surface2, rgba(255,255,255,0.06)); - color: var(--text, #fff); - font-size: 13px; - margin-bottom: 8px; - box-sizing: border-box; -} - -.home-game-search:focus { - outline: none; - border-color: var(--accent, #e94560); -} - -/* ── Library Controls ───────────────────────────────── */ - -.library-controls { - margin-bottom: 16px; - display: flex; - align-items: center; - gap: 10px; - flex-wrap: wrap; -} - -.library-search { - flex: 1; - min-width: 160px; - max-width: 320px; - padding: 6px 12px; - border: 1px solid var(--border, rgba(255,255,255,0.15)); - border-radius: 6px; - background: var(--surface2, rgba(255,255,255,0.06)); - color: var(--text, #fff); - font-size: 13px; -} - -.library-search:focus { - outline: none; - border-color: var(--accent, #e94560); -} - -.disk-info-wrap { - display: flex; - align-items: center; - gap: 5px; - white-space: nowrap; -} - -.disk-info-icon { - width: 13px; - height: 13px; - flex-shrink: 0; - opacity: 0.65; -} - -.disk-drive-custom { - flex: 0 0 auto; - min-width: 0; -} - -.disk-drive-custom .custom-select-display { - padding: 2px 7px; - font-size: 12px; -} - -.disk-drive-custom .custom-select-dropdown { - min-width: 55px; -} - -.disk-info-text { - font-size: 12px; - opacity: 0.65; - white-space: nowrap; -} - -/* ── Backup Progress Bar ─────────────────────────────── */ - -.backup-progress { - display: flex; - flex-direction: column; - gap: 6px; - padding: 12px 14px; - background: var(--surface2, rgba(255,255,255,0.05)); - border: 1px solid var(--border, rgba(255,255,255,0.12)); - border-radius: 8px; - margin-bottom: 14px; -} - -.backup-progress-header { - display: flex; - justify-content: space-between; - align-items: center; - font-size: 13px; -} - -.backup-progress-header span:first-child { - font-weight: 500; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - max-width: 70%; -} - -.backup-progress-header span:last-child { - font-size: 12px; - opacity: 0.65; - flex-shrink: 0; -} - -.backup-progress-track { - width: 100%; - height: 8px; - background: var(--border, rgba(255,255,255,0.12)); - border-radius: 4px; - overflow: hidden; -} - -#all-saves-progress-fill { - height: 100%; - width: 0%; - background: var(--accent, #e94560); - border-radius: 4px; - transition: width 0.35s ease; -} - -.backup-progress-stats { - display: flex; - gap: 16px; - font-size: 12px; - opacity: 0.75; -} - -#all-saves-progress-ok { - color: #4ade80; -} - -#all-saves-progress-fail { - color: #f87171; -} - -.info-callout { - background: var(--surface2, rgba(255,255,255,0.05)); - border-left: 3px solid var(--accent, #4fa3e0); - border-radius: 6px; - padding: 10px 14px; - margin-bottom: 16px; - font-size: 0.85rem; - color: var(--text-muted, rgba(255,255,255,0.7)); - line-height: 1.5; -} - -.info-callout strong { - color: var(--text, #fff); -} - -/* ── Hidden ─────────────────────────────────────────── */ - -.hidden { - display: none !important; -} - -/* ── Platform ───────────────────────────────────────── */ - -body:not(.platform-win32) .platform-win { display: none; } -body.platform-win32 .platform-win { display: flex; } -body.platform-win32 .settings-section.platform-win { display: block; } -body.platform-linux .platform-win { display: none; } - -body:not(.platform-linux) .platform-linux { display: none; } -body.platform-linux .platform-linux { display: flex; } -body.platform-linux .settings-section.platform-linux { display: block; } -body.platform-win32 .platform-linux { display: none; } - -/* ── Scrollbar ──────────────────────────────────────── */ - -::-webkit-scrollbar { - width: 8px; -} - -::-webkit-scrollbar-track { - background: var(--bg); -} - -::-webkit-scrollbar-thumb { - background: var(--border); - border-radius: 4px; -} - -::-webkit-scrollbar-thumb:hover { - background: var(--btn-hover); -} - -/* ── A5 Update button spinner ───────────────────────── */ -/* Tiny inline SVG spinner used by the Settings Update button. - Reuses the existing @keyframes spin in animations.css. */ -.spinner { - display: inline-block; - vertical-align: middle; - animation: spin 0.8s linear infinite; - color: currentColor; -} - - -/* ── A12 Bulk Import (Folder Scan + Drag-and-Drop) ──────────────── */ - -.bulk-drop-zone { - margin-top: 12px; - padding: 24px 18px; - border: 2px dashed var(--border, rgba(255,255,255,0.25)); - border-radius: 10px; - background: var(--surface2, rgba(255,255,255,0.04)); - color: var(--fg); - text-align: center; - font-size: 13px; - transition: border-color 0.15s ease, background 0.15s ease; - user-select: none; -} - -.bulk-drop-zone .bulk-drop-zone-icon { - display: block; - font-size: 28px; - line-height: 1; - opacity: 0.6; - margin-bottom: 6px; -} - -.bulk-drop-zone .bulk-drop-zone-text { - opacity: 0.85; -} - -.bulk-drop-zone:hover, -.bulk-drop-zone.bulk-drop-active { - border-color: var(--accent, #e94560); - background: rgba(233, 69, 96, 0.08); -} - -.bulk-aggregate-progress { - margin-top: 14px; - padding: 10px 12px; - background: var(--card-bg, rgba(255,255,255,0.04)); - border: 1px solid var(--border, rgba(255,255,255,0.12)); - border-radius: 8px; -} - -.bulk-aggregate-header { - display: flex; - justify-content: space-between; - align-items: center; - font-size: 12px; - margin-bottom: 6px; -} - -.bulk-aggregate-track { - width: 100%; - height: 6px; - background: var(--border, rgba(255,255,255,0.12)); - border-radius: 3px; - overflow: hidden; -} - -.bulk-aggregate-fill { - height: 100%; - width: 0%; - background: var(--accent, #e94560); - transition: width 0.25s ease; -} - -.bulk-results-panel { - margin-top: 14px; - padding: 12px 14px; - background: var(--card-bg, rgba(255,255,255,0.04)); - border: 1px solid var(--border, rgba(255,255,255,0.12)); - border-radius: 8px; -} - -.bulk-results-title { - font-size: 13px; - font-weight: 600; - margin-bottom: 8px; - opacity: 0.85; -} - -.bulk-results-list { - list-style: none; - margin: 0; - padding: 0; - max-height: 220px; - overflow-y: auto; - font-family: 'Cascadia Code', 'Fira Code', Consolas, monospace; - font-size: 11px; - line-height: 1.5; -} - -.bulk-result-item { - padding: 3px 4px; - border-bottom: 1px solid var(--border, rgba(255,255,255,0.06)); - word-break: break-all; -} - -.bulk-result-item:last-child { border-bottom: none; } -.bulk-result-ok { color: #4ade80; } -.bulk-result-fail { color: #f87171; } -.bulk-result-skipped { color: #f0c040; opacity: 0.85; } diff --git a/sff/webui/css/premium.css b/sff/webui/css/premium.css deleted file mode 100644 index 4cf0521b..00000000 --- a/sff/webui/css/premium.css +++ /dev/null @@ -1,1426 +0,0 @@ -/* SteaMidra — Premium Layer v3 */ -/* Soft ambient sections, no cards, just content + glow */ - -/* ── Background Atmosphere ─────────────────── */ - -body { - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; - font-weight: 500; - -webkit-font-smoothing: antialiased; -} - -body::before { - content: ''; - position: fixed; - inset: 0; - background: - radial-gradient(ellipse 80% 60% at 10% 10%, rgba(74, 158, 255, 0.05) 0%, transparent 55%), - radial-gradient(ellipse 70% 50% at 90% 90%, rgba(140, 100, 255, 0.04) 0%, transparent 50%), - radial-gradient(ellipse 50% 40% at 85% 15%, rgba(255, 120, 80, 0.03) 0%, transparent 45%), - radial-gradient(ellipse 40% 30% at 15% 85%, rgba(80, 200, 150, 0.025) 0%, transparent 40%); - pointer-events: none; - z-index: 0; -} - -.content { - position: relative; - z-index: 1; - padding: 32px 32px; -} - -/* ── Typography ─────────────────────────────── */ - -h1, h2, h3, h4 { - font-family: 'Outfit', -apple-system, BlinkMacSystemFont, sans-serif; - font-weight: 700; - letter-spacing: -0.02em; - line-height: 1.2; -} - -h1 { font-size: 26px; font-weight: 800; } -h2 { font-size: 18px; font-weight: 700; } -h3 { font-size: 15px; font-weight: 600; } - -.page-header { - margin-bottom: 32px; - padding-bottom: 20px; - border-bottom: 1px solid var(--border); -} - -.page-header h1 { - font-size: 22px; - font-weight: 800; - margin-bottom: 4px; -} - -.page-subtitle { - font-size: 13.5px; - opacity: 0.45; -} - -.section-group { - margin-bottom: 36px; -} - -.section-title { - font-family: 'Manrope', sans-serif; - font-size: 10px; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.14em; - opacity: 0.35; - margin-bottom: 16px; - display: block; -} - -/* ── Action Grid — No Cards, Just Hover Zones ─────── */ - -.action-grid { - display: flex; - flex-wrap: wrap; - gap: 10px; -} - -.action-card { - flex: 1; - min-width: 180px; - display: flex; - align-items: center; - gap: 12px; - padding: 16px 18px; - border-radius: 14px; - border: 1px solid transparent; - transition: all 0.25s ease; - background: rgba(255, 255, 255, 0.02); - position: relative; -} - -.action-card::before { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 0; - height: 100%; - background: linear-gradient(90deg, rgba(74, 158, 255, 0.1), rgba(74, 158, 255, 0.05)); - transition: width 0.3s ease; - border-radius: 14px 0 0 14px; -} - -.action-card:hover { - background: rgba(74, 158, 255, 0.06); - border-color: rgba(74, 158, 255, 0.2); -} - -.action-card:hover::before { - width: 100%; -} - -.action-icon { - width: 38px; - height: 38px; - min-width: 38px; - display: flex; - align-items: center; - justify-content: center; - background: transparent; - border-radius: 0; - transition: all 0.25s ease; - position: relative; - z-index: 1; -} - -.action-icon svg { - width: 18px; - height: 18px; - stroke-width: 1.75; - position: relative; - z-index: 1; -} - -.action-card:hover .action-icon { - background: transparent; - box-shadow: none; -} - -.action-card:hover .action-icon svg { - stroke: #fff; -} - -.action-title { - font-size: 13px; - font-weight: 600; -} - -.action-desc { - display: block; - font-size: 11.5px; - opacity: 0.45; - line-height: 1.4; -} - -.action-desc.warn-achievements { - opacity: 1; - color: #f0c040; - font-weight: 600; -} - -.action-desc.safe-achievements { - opacity: 1; - color: #4caf50; - font-weight: 600; -} - -/* ── Action Cards Grid ─────────────────────────── */ - -.action-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); - gap: 12px; -} - -.action-card { - display: flex; - flex-direction: column; - align-items: center; - gap: 8px; - padding: 20px 16px; - border-radius: 14px; - border: 1px solid var(--border); - background: rgba(255, 255, 255, 0.02); - position: relative; - overflow: hidden; - transition: all 0.25s ease; - text-align: center; -} - -.action-card::before { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 0; - height: 100%; - background: linear-gradient(90deg, rgba(74, 158, 255, 0.08), transparent); - transition: width 0.3s ease; - border-radius: 14px 0 0 14px; -} - -.action-card:hover { - background: rgba(74, 158, 255, 0.06); - border-color: rgba(74, 158, 255, 0.2); -} - -.action-card:hover::before { - width: 100%; -} - -.action-icon { - width: 40px; - height: 40px; - display: flex; - align-items: center; - justify-content: center; - background: transparent; - border-radius: 0; - transition: all 0.25s ease; - position: relative; - z-index: 1; -} - -.action-icon svg { - width: 20px; - height: 20px; - stroke-width: 1.75; - position: relative; - z-index: 1; -} - -.action-card:hover .action-icon { - background: transparent; - box-shadow: none; -} - -.action-card:hover .action-icon svg { - stroke: #fff; -} - -.action-title { - font-size: 13px; - font-weight: 600; - position: relative; - z-index: 1; -} - -.action-chevron { - display: none; -} - -/* Compact cards */ -.action-grid.small .action-card { - flex-direction: column; - padding: 18px 14px; -} - -/* Compact buttons in grid */ -.action-grid.small .action-card { - min-width: 140px; - padding: 14px 14px; - gap: 10px; -} - -.action-grid.small .action-icon { - width: 32px; - height: 32px; - min-width: 32px; - border-radius: 8px; -} - -.action-grid.small .action-icon svg { - width: 16px; - height: 16px; -} - -/* ── Fix Game — Step Descriptions ─────────────────── */ - -.step-desc { - font-size: 12.5px; - opacity: 0.5; - margin: 4px 0 14px; - line-height: 1.5; -} - -.option-hint { - display: block; - font-size: 11.5px; - opacity: 0.45; - line-height: 1.4; - margin-left: 26px; - margin-top: 2px; - margin-bottom: 6px; -} - -/* ── Game Grid — Vertical Card Grid ─────────────────── */ - -.game-card { - border-radius: 14px; - overflow: hidden; - position: relative; - transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease; - border: 1px solid var(--border); - background: var(--card-bg); -} - -.game-card:hover { - transform: translateY(-4px) scale(1.02); - box-shadow: 0 8px 28px rgba(74, 158, 255, 0.18); - border-color: rgba(74, 158, 255, 0.3); -} -.game-card:focus-visible, -.game-list-item:focus-visible { - outline: 2px solid #4a9eff; - outline-offset: 2px; -} - -.game-card-img { - width: 100%; - height: 130px; - object-fit: cover; - border-radius: 0; - background: var(--bg); - flex-shrink: unset; - display: block; -} - -.game-card-body { - padding: 12px 14px; -} - -.game-card-name { - font-size: 13.5px; - font-weight: 600; - margin-bottom: 4px; -} - -.game-card-appid { - font-size: 11px; - opacity: 0.4; -} - -.game-card-actions { - display: flex; - align-items: center; - gap: 6px; - padding: 8px 14px 12px; - position: relative; - z-index: 1; -} - -/* List view */ -.game-list { - display: flex; - flex-direction: column; - gap: 8px; -} - -.game-list-item { - display: flex; - align-items: center; - gap: 14px; - padding: 14px 18px; - border-radius: 14px; - border: 1px solid transparent; - background: rgba(255, 255, 255, 0.02); - position: relative; - transition: all 0.25s ease; -} - -.game-list-item::before { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 0; - height: 100%; - background: linear-gradient(90deg, rgba(74, 158, 255, 0.1), transparent); - transition: width 0.3s ease; - border-radius: 14px 0 0 14px; -} - -.game-list-item:hover { - background: rgba(74, 158, 255, 0.06); - border-color: rgba(74, 158, 255, 0.2); -} - -.game-list-item:hover::before { - width: 100%; -} - -.game-list-thumb { - width: 64px; - height: 36px; - object-fit: cover; - border-radius: 8px; - flex-shrink: 0; -} - -.game-list-info { - flex: 1; -} - -.game-list-name { - font-size: 13.5px; - font-weight: 600; -} - -.game-list-actions { - display: flex; - align-items: center; - position: relative; - z-index: 1; -} - -/* ── Buttons ─────────────────────────────── */ - -.btn { - border-radius: 10px; - font-weight: 600; - padding: 10px 20px; - transition: all 0.2s ease; - font-family: 'Manrope', sans-serif; - font-size: 13px; -} - -.btn-primary { - background: var(--accent); - color: #fff; - border-color: var(--accent); - box-shadow: 0 4px 16px rgba(74, 158, 255, 0.2); -} - -.btn-primary:hover { - opacity: 0.88; - transform: translateY(-2px); - box-shadow: 0 8px 24px rgba(74, 158, 255, 0.3); -} - -/* ── Inputs ─────────────────────────────── */ - -input[type="text"], -input[type="password"], -input[type="number"], -select { - border-radius: 10px; - font-weight: 500; - font-family: 'Manrope', sans-serif; - font-size: 13.5px; -} - -input:focus, select:focus { - border-color: var(--accent); - box-shadow: 0 0 0 3px rgba(74, 158, 255, 0.1); -} - -.input-group { - margin-bottom: 14px; -} - -.input-group label { - font-size: 11px; - font-weight: 600; - opacity: 0.4; - text-transform: uppercase; - letter-spacing: 0.08em; - margin-bottom: 6px; -} - -/* ── Store Controls ─────────────────────────────── */ - -.store-controls { - margin-bottom: 28px; - display: flex; - gap: 12px; - flex-wrap: wrap; - align-items: center; -} - -.search-bar { - display: flex; - gap: 10px; - flex: 1; - min-width: 260px; -} - -.search-bar input { - border-radius: 10px; - flex: 1; -} - -.connect-banner { - border-radius: 16px; - padding: 28px; - border: 1px solid rgba(74, 158, 255, 0.15); - background: rgba(74, 158, 255, 0.04); - margin-bottom: 24px; -} - -.view-toggle { - display: flex; - gap: 4px; - background: rgba(255, 255, 255, 0.02); - border: 1px solid var(--border); - border-radius: 8px; - padding: 4px; -} - -/* ── Tool Cards — No Card Look ─────────────────────── */ - -.tool-card { - padding: 0; - border: none; - background: none; - margin-bottom: 28px; -} - -.tool-card h2 { - font-size: 16px; - margin-bottom: 8px; -} - -.tool-desc { - font-size: 13px; - opacity: 0.5; - margin-bottom: 16px; -} - -/* ── Fix Game — Sections Without Boxes ─────────────── */ - -.fixgame-layout { - max-width: 700px; -} - -.fixgame-step { - padding: 0; - margin-bottom: 24px; - border: none; - background: none; -} - -.fixgame-step .section-title { - margin-bottom: 12px; -} - -.fixgame-actions { - display: flex; - gap: 12px; - margin-top: 16px; -} - -/* ── Settings — Sections Without Boxes ────────────── */ - -.settings-section { - padding: 0; - margin-bottom: 28px; - border: none; - background: none; -} - -.settings-section h2 { - margin-bottom: 16px; -} - -.theme-grid { - display: flex; - flex-wrap: wrap; - gap: 8px; -} - -.theme-swatch { - padding: 10px 16px; - border-radius: 10px; - font-size: 12px; - font-weight: 600; - transition: all 0.2s ease; -} - -.theme-swatch:hover { - transform: scale(1.04); -} - -.theme-swatch.active { - box-shadow: 0 0 16px rgba(74, 158, 255, 0.25); -} - -/* ── Data Tables — Minimal ─────────────────────── */ - -.data-table { - border: none; - background: none; - margin-top: 16px; -} - -.data-table table { - width: 100%; -} - -.data-table th, -.data-table td { - padding: 10px 14px; - border-bottom: 1px solid var(--border); -} - -.data-table th { - font-size: 10px; - font-weight: 700; - letter-spacing: 0.1em; - opacity: 0.35; - text-transform: uppercase; -} - -.data-table tr:hover td { - background: rgba(255, 255, 255, 0.02); -} - -/* ── Log Output ─────────────────────────────── */ - -.log-output { - background: rgba(255, 255, 255, 0.02); - border: 1px solid var(--border); - border-radius: 12px; -} - -/* ── UI refinement & responsive polish ─────────────────────── */ - -.content { - scrollbar-gutter: stable; -} - -button:focus-visible, -input:focus-visible, -select:focus-visible, -[tabindex="0"]:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; -} - -.btn { - min-height: 38px; -} - -.page.active { - animation-duration: 140ms; -} - -/* Store: keep the controls visually together and reduce layout churn. */ -#page-store .page-header { - margin-bottom: 20px; -} - -#page-store .store-controls { - padding: 14px; - margin-bottom: 10px; - border: 1px solid var(--border); - border-radius: 16px; - background: color-mix(in srgb, var(--card-bg) 88%, transparent); - box-shadow: 0 14px 40px rgba(0, 0, 0, 0.08); -} - -#page-store .search-bar input { - min-height: 42px; - padding-inline: 14px; -} - -#page-store .genre-chips { - flex-wrap: nowrap; - overflow-x: auto; - padding: 8px 2px 10px; - margin: 2px 0 12px; - scrollbar-width: thin; -} - -#page-store .genre-chip { - min-height: 32px; - padding: 6px 13px; - background: color-mix(in srgb, var(--card-bg) 88%, transparent); -} - -#store-provider-status:empty { - display: none; -} - -#store-provider-status { - padding-inline: 4px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.loading-skeleton { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); - gap: 16px; -} - -.loading-skeleton.hidden { - display: none; -} - -/* Settings: an in-page index replaces the very long unstructured column. */ -.settings-shell { - display: grid; - grid-template-columns: 176px minmax(0, 1fr); - gap: 28px; - align-items: start; -} - -.settings-index { - position: sticky; - top: 0; - max-height: calc(100vh - 64px); - overflow-y: auto; - padding: 14px 10px; - border: 1px solid var(--border); - border-radius: 14px; - background: color-mix(in srgb, var(--card-bg) 92%, transparent); - box-shadow: 0 12px 36px rgba(0, 0, 0, 0.08); -} - -.settings-index-title { - padding: 2px 9px; - font-size: 13px; - font-weight: 750; -} - -.settings-index-hint { - padding: 1px 9px 10px; - font-size: 10px; - opacity: 0.46; -} - -.settings-index-item { - position: relative; - display: block; - width: 100%; - padding: 8px 10px; - border: 0; - border-radius: 8px; - background: transparent; - color: var(--fg); - font: inherit; - font-size: 11.5px; - text-align: left; - cursor: pointer; - opacity: 0.62; - transition: background 140ms ease, color 140ms ease, opacity 140ms ease; -} - -.settings-index-item:hover { - opacity: 1; - background: var(--btn-hover); -} - -.settings-index-item.active { - opacity: 1; - color: var(--accent); - background: color-mix(in srgb, var(--accent) 12%, transparent); -} - -.settings-main { - min-width: 0; -} - -.settings-main .settings-section { - scroll-margin-top: 22px; - padding: 20px; - margin-bottom: 18px; - border: 1px solid color-mix(in srgb, var(--border) 86%, transparent); - border-radius: 16px; - background: color-mix(in srgb, var(--card-bg) 76%, transparent); - box-shadow: 0 12px 42px rgba(0, 0, 0, 0.055); -} - -.settings-main .settings-section > h2 { - margin-bottom: 16px; - font-size: 14px; - text-transform: none; - letter-spacing: -0.01em; - opacity: 0.96; -} - -.settings-main .checkbox-grid { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 8px; -} - -.settings-main .checkbox-option { - min-height: 42px; - padding: 10px 12px; - border: 1px solid transparent; - border-radius: 10px; - background: rgba(255, 255, 255, 0.022); -} - -.settings-main .checkbox-option:hover { - border-color: var(--border); -} - -/* Theme studio: one real photo is decoded (the active preview), while the - grid uses lightweight palette previews instead of loading six large JPGs. */ -.theme-grid { - display: block; - margin-bottom: 20px; -} - -.theme-studio { - display: grid; - grid-template-columns: minmax(190px, 0.72fr) minmax(300px, 1.65fr); - gap: 18px; -} - -.theme-current { - display: flex; - flex-direction: column; - min-width: 0; - padding: 12px; - border: 1px solid var(--border); - border-radius: 14px; - background: rgba(255, 255, 255, 0.022); -} - -.theme-current-preview { - --theme-preview-bg: #2d2d2d; - --theme-preview-accent: #4a9eff; - position: relative; - display: flex; - height: 150px; - overflow: hidden; - border-radius: 10px; - background-color: var(--theme-preview-bg); - background-position: center; - background-size: cover; - box-shadow: inset 0 0 0 1px rgba(255,255,255,.08), 0 12px 28px rgba(0,0,0,.18); -} - -.theme-current-preview::after { - content: ''; - position: absolute; - inset: 0; - background: linear-gradient(125deg, transparent 35%, color-mix(in srgb, var(--theme-preview-accent) 26%, transparent)); - pointer-events: none; -} - -.theme-preview-sidebar { - width: 24%; - background: rgba(0, 0, 0, 0.42); - border-right: 1px solid rgba(255,255,255,.08); -} - -.theme-preview-window { - z-index: 1; - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 8px; - flex: 1; - align-content: center; - padding: 20px; -} - -.theme-preview-window i { - height: 38px; - border: 1px solid rgba(255,255,255,.12); - border-radius: 7px; - background: rgba(0,0,0,.26); -} - -.theme-preview-window i:first-child { - grid-column: 1 / -1; - height: 18px; - background: var(--theme-preview-accent); - opacity: .88; -} - -.theme-current-copy { - display: grid; - gap: 3px; - padding: 13px 3px 2px; -} - -.theme-eyebrow, -.theme-card-kind { - font-size: 9px; - text-transform: uppercase; - letter-spacing: .11em; - opacity: .42; -} - -#theme-current-name { - overflow: hidden; - font-size: 15px; - text-overflow: ellipsis; - white-space: nowrap; -} - -#theme-current-kind { - font-size: 11px; - opacity: .5; -} - -.theme-browser { - min-width: 0; -} - -.theme-toolbar { - display: flex; - gap: 8px; - margin-bottom: 10px; -} - -#theme-search { - min-width: 120px; - min-height: 36px; - padding: 8px 11px; -} - -.theme-filters { - display: flex; - align-items: center; - gap: 3px; - padding: 3px; - border: 1px solid var(--border); - border-radius: 9px; -} - -.theme-filter { - padding: 6px 8px; - border: 0; - border-radius: 6px; - background: transparent; - color: var(--fg); - font-size: 10px; - cursor: pointer; - opacity: .55; -} - -.theme-filter.active { - color: #fff; - background: var(--accent); - opacity: 1; -} - -.theme-options { - display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: 7px; - max-height: 296px; - overflow-y: auto; - padding: 2px 5px 2px 2px; - scrollbar-width: thin; -} - -.theme-card { - --theme-card-bg: #222; - --theme-card-accent: #4a9eff; - display: grid; - grid-template-columns: 38px minmax(0, 1fr); - grid-template-rows: auto auto; - column-gap: 9px; - min-width: 0; - padding: 7px; - border: 1px solid var(--border); - border-radius: 10px; - background: rgba(255,255,255,.018); - color: var(--fg); - text-align: left; - cursor: pointer; - transition: border-color 130ms ease, background 130ms ease, transform 130ms ease; -} - -.theme-card:hover { - transform: translateY(-1px); - border-color: color-mix(in srgb, var(--theme-card-accent) 70%, var(--border)); - background: rgba(255,255,255,.04); -} - -.theme-card.active { - border-color: var(--theme-card-accent); - background: color-mix(in srgb, var(--theme-card-accent) 10%, transparent); - box-shadow: 0 0 0 1px color-mix(in srgb, var(--theme-card-accent) 34%, transparent); -} - -.theme-card-visual { - grid-row: 1 / 3; - display: grid; - grid-template-columns: 9px 1fr; - gap: 3px; - width: 38px; - height: 34px; - padding: 4px; - overflow: hidden; - border-radius: 6px; - background: var(--theme-card-bg); - box-shadow: inset 0 0 0 1px rgba(255,255,255,.1); -} - -.theme-card-visual i:first-child { - grid-row: 1 / 3; - background: rgba(0,0,0,.3); -} - -.theme-card-visual i:nth-child(2) { - background: var(--theme-card-accent); -} - -.theme-card-visual i:nth-child(3) { - background: rgba(255,255,255,.16); -} - -.theme-card-label { - align-self: end; - overflow: hidden; - font-size: 11px; - font-weight: 650; - text-overflow: ellipsis; - white-space: nowrap; -} - -.theme-empty { - padding: 28px; - text-align: center; - opacity: .48; -} - -@media (max-width: 1040px) { - .settings-shell { - grid-template-columns: 1fr; - } - - .settings-index { - position: static; - z-index: 5; - top: -1px; - display: grid; - grid-template-columns: repeat(4, minmax(0, 1fr)); - gap: 4px; - max-height: none; - overflow: visible; - padding: 7px; - } - - .settings-index-title, - .settings-index-hint { - display: none; - } - - .settings-index-item { - width: 100%; - min-width: 0; - white-space: normal; - text-align: center; - line-height: 1.2; - } - - .theme-studio { - grid-template-columns: 1fr; - } - - .theme-current { - display: grid; - grid-template-columns: minmax(180px, .8fr) 1fr; - align-items: center; - } - - .theme-current-preview { - height: 120px; - } -} - -@media (max-width: 720px) { - .settings-index { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } -} - -@media (max-width: 820px) { - .sidebar { - width: 68px; - min-width: 68px; - } - - .sidebar-title { - display: none; - } - - .nav-label { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border: 0; - } - - .sidebar-logo, - .nav-item { - justify-content: center; - padding-inline: 12px; - } - - .content { - margin-left: 68px; - padding: 22px 20px 40px; - } - - .settings-main .checkbox-grid, - .theme-options { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - .store-options, - .store-options .custom-select { - width: 100%; - } -} - -@media (prefers-reduced-motion: reduce) { - *, *::before, *::after { - scroll-behavior: auto !important; - animation-duration: 0.01ms !important; - animation-iteration-count: 1 !important; - transition-duration: 0.01ms !important; - } -} - -.log-output h3 { - font-size: 10px; - opacity: 0.4; -} - -/* ── Log Panel ─────────────────────────────── */ - -.log-panel-dialog { - border-radius: 18px; - border: 1px solid var(--border); -} - -/* ── Modals ─────────────────────────────── */ - -.modal-content { - border-radius: 18px; - border: 1px solid var(--border); -} - -.modal-header { - border-radius: 18px 18px 0 0; -} - -/* ── Cloud Saves ─────────────────────────────── */ - -.cloudsaves-setup { - padding: 0; - border: none; - background: none; - margin-bottom: 24px; -} - -.cloudsaves-actions { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 16px; -} - -/* ── Downloads ─────────────────────────────── */ - -.downloads-section { - margin-bottom: 28px; -} - -.downloads-list { - display: flex; - flex-direction: column; - gap: 8px; -} - -.download-item { - display: flex; - align-items: center; - gap: 14px; - padding: 14px 16px; - border-radius: 12px; - border: 1px solid transparent; - background: rgba(255, 255, 255, 0.02); - position: relative; - transition: all 0.25s ease; -} - -.download-item::before { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 0; - height: 100%; - background: linear-gradient(90deg, rgba(74, 158, 255, 0.1), transparent); - transition: width 0.3s ease; - border-radius: 12px 0 0 12px; -} - -.download-item:hover { - background: rgba(74, 158, 255, 0.06); - border-color: rgba(74, 158, 255, 0.2); -} - -.download-item:hover::before { - width: 100%; -} - -.download-item-name { - font-weight: 600; - font-size: 13.5px; - margin-bottom: 4px; -} - -.download-item-status { - font-size: 12px; - opacity: 0.4; -} - -.download-progress-bar { - height: 3px; - background: var(--border); - border-radius: 2px; - margin-top: 8px; -} - -.download-progress-fill { - height: 100%; - background: var(--accent); - border-radius: 2px; -} - -/* ── Library ─────────────────────────────── */ - -.library-list { - display: flex; - flex-direction: column; - gap: 8px; -} - -.library-option { - padding: 12px 16px; - border-radius: 12px; - border: 1px solid transparent; - background: rgba(255, 255, 255, 0.02); - transition: all 0.2s ease; -} - -.library-option:hover { - background: rgba(74, 158, 255, 0.06); - border-color: rgba(74, 158, 255, 0.2); -} - -.library-controls { - margin-bottom: 16px; -} - -/* ── Empty State ─────────────────────────────── */ - -.empty-state { - padding: 48px 24px; - opacity: 0.4; -} - -/* ── Loading ─────────────────────────────── */ - -.loading-skeleton { - display: flex; - flex-wrap: wrap; - gap: 10px; -} - -.skeleton-card { - flex: 1; - min-width: 180px; - height: 60px; - border-radius: 14px; -} - -/* ── Pagination ─────────────────────────────── */ - -.pagination { - margin-top: 28px; -} - -/* ── Profile Controls ─────────────────────────────── */ - -.profile-controls { - display: flex; - gap: 8px; - flex-wrap: wrap; - align-items: center; -} - -.profile-controls select { - min-width: 160px; -} - -/* ── Scrollbar ─────────────────────────────── */ - -::-webkit-scrollbar { - width: 5px; -} - -::-webkit-scrollbar-thumb { - border-radius: 3px; - background: var(--border); -} - -/* ── Library Grid — Compact Overrides ─────────────────── */ - -#library-grid { - grid-template-columns: repeat(auto-fill, minmax(175px, 1fr)); - gap: 12px; -} - -#library-grid .game-card-img { - height: 98px; -} - -#library-grid .game-card-img-placeholder { - height: 98px; -} - -#library-grid .game-card-body { - padding: 8px 10px; -} - -#library-grid .game-card-name { - font-size: 12px; -} - -#library-grid .game-card-actions { - padding: 4px 10px 8px; -} - -#library-grid .game-card-actions .btn { - padding: 4px 8px; - font-size: 11px; -} - -/* ── Store multi-select + download queue ─────────────────────── */ -#store-select-bar { - display: flex; - align-items: center; - gap: 8px; - flex-wrap: wrap; - margin: 8px 0 0; - padding: 8px 10px; - border: 1px solid var(--border, rgba(255,255,255,0.12)); - border-radius: 6px; - font-size: 12px; -} -.game-card.card-selected, .game-list-item.card-selected { - outline: 2px solid var(--accent, #4a9eff); - outline-offset: -2px; - position: relative; -} -.store-select-marker { - position: absolute; - top: 6px; - left: 6px; - width: 20px; - height: 20px; - border-radius: 50%; - background: var(--accent, #4a9eff); - color: #fff; - font-size: 12px; - display: flex; - align-items: center; - justify-content: center; - z-index: 3; -} -.queue-state-badge { - display: inline-block; - font-size: 10px; - padding: 1px 6px; - border-radius: 4px; - margin-left: 4px; - text-transform: uppercase; -} -.queue-badge-queued { background: rgba(255,255,255,0.12); } -.queue-badge-downloading { background: rgba(74,158,255,0.25); } -.queue-badge-done { background: rgba(40,167,69,0.25); } -.queue-badge-failed { background: rgba(220,53,69,0.25); } - -/* ── Discord corner links ─────────────────────────────────────── */ -.discord-corner-link { - position: absolute; - top: 4px; - right: 8px; - display: inline-flex; - align-items: center; - gap: 6px; - font-size: 12px; - color: var(--text-dim, #9aa4b2); - text-decoration: none; - padding: 4px 8px; - border-radius: 6px; -} -.discord-corner-link:hover { - color: var(--accent, #4a9eff); - background: rgba(255,255,255,0.06); -} -.page-header { position: relative; } - -/* ── Modal scrollbar: keep it inside the rounded corners ───────── */ -.modal-content::-webkit-scrollbar { width: 8px; } -.modal-content::-webkit-scrollbar-track { background: transparent; } -.modal-content::-webkit-scrollbar-thumb { - background: rgba(255,255,255,0.22); - border-radius: 4px; - border: 2px solid transparent; - background-clip: padding-box; -} -.modal-content::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.35); background-clip: padding-box; } diff --git a/sff/webui/css/themes.css b/sff/webui/css/themes.css index 7017f7c3..1d5eee01 100644 --- a/sff/webui/css/themes.css +++ b/sff/webui/css/themes.css @@ -58,6 +58,7 @@ --fg: #c0f0c0; --card-bg: #102d10; --accent: #40e840; + --on-accent: #14140a; --border: #205a20; --btn-bg: #102d10; --btn-hover: #184a18; @@ -162,8 +163,10 @@ [data-theme="bee"] { --bg: #fcdd6a; --fg: #1b1b1b; + --sidebar-fg: #fcdd6a; --card-bg: #f8c600; --accent: #fff200; + --on-accent: #14140a; --border: #aa8100; --btn-bg: #aa8100; --btn-hover: #ba972a; @@ -187,9 +190,13 @@ [data-theme="crystalmeth"] { --bg: #69a1cf; - --fg: #c5f5ff; + --fg: #0b1f2e; + --sidebar-fg: #c5f5ff; --card-bg: #4a7a9d; --accent: #68d8ff; + --btn-fg: #ffffff; + --input-fg: #ffffff; + --on-accent: #14140a; --border: #0017ff; --btn-bg: #005fc0; --btn-hover: #2881dc; @@ -304,9 +311,12 @@ [data-theme="gld-midnight"] { --bg: #9aa6ee; - --fg: #d9dafd; + --fg: #15173d; + --sidebar-fg: #d9dafd; --card-bg: #7b8adb; --accent: #8789fa; + --btn-fg: #ffffff; + --input-fg: #ffffff; --border: #5060cc; --btn-bg: #222e85; --btn-hover: #3644aa; @@ -317,9 +327,12 @@ [data-theme="neon-rider"] { --bg: #66d1c2; - --fg: #ffffff; + --fg: #10222b; + --sidebar-fg: #ffffff; --card-bg: #4bb5a5; --accent: #f000ff; + --btn-fg: #ffffff; + --input-fg: #ffffff; --border: #6b6b6b; --btn-bg: #7d1e70; --btn-hover: #ac2199; @@ -343,9 +356,11 @@ [data-theme="real-madrid"] { --bg: #ababab; - --fg: #ffffff; + --fg: #1a1a1a; + --sidebar-fg: #ffffff; --card-bg: #c8c8c8; --accent: #fabc01; + --on-accent: #14140a; --border: #6b6b6b; --btn-bg: #c09414; --btn-hover: #deb02d; @@ -359,6 +374,8 @@ --fg: #ffffff; --card-bg: #1e252b; --accent: #00ff86; + --btn-fg: #111111; + --on-accent: #14140a; --border: #7e97a1; --btn-bg: #7e97a1; --btn-hover: #99becc; @@ -400,6 +417,7 @@ --fg: #dbdbdb; --card-bg: rgba(39, 41, 59, 0.82); --accent: #979ffb; + --btn-fg: #ffffff; --border: #6b6b6b; --btn-bg: rgba(150, 140, 186, 0.8); --btn-hover: rgba(173, 161, 219, 0.85); @@ -428,6 +446,7 @@ --fg: #c5f5ff; --card-bg: rgba(0, 74, 132, 0.82); --accent: #68d8ff; + --on-accent: #14140a; --border: #0017ff; --btn-bg: rgba(0, 95, 192, 0.8); --btn-hover: rgba(40, 129, 220, 0.85); @@ -470,6 +489,7 @@ --fg: #000000; --card-bg: rgba(107, 159, 231, 0.82); --accent: #00eeff; + --on-accent: #14140a; --border: #4a80c0; --btn-bg: rgba(195, 254, 255, 0.8); --btn-hover: rgba(178, 253, 254, 0.85); diff --git a/sff/webui/index.html b/sff/webui/index.html index a7a1a505..77f74c65 100644 --- a/sff/webui/index.html +++ b/sff/webui/index.html @@ -4,11 +4,8 @@