diff --git a/docker/frontend/scripts/mobile-pick-check.mjs b/docker/frontend/scripts/mobile-pick-check.mjs index c8915f0..b65c232 100644 --- a/docker/frontend/scripts/mobile-pick-check.mjs +++ b/docker/frontend/scripts/mobile-pick-check.mjs @@ -217,6 +217,14 @@ const read = await page.evaluate(() => { cells: cells.length, selected: sel.map((c) => c.querySelector('img')?.getAttribute('alt') ?? ''), outline: sel[0] ? getComputedStyle(sel[0]).outlineColor : '', + accent: (() => { + const probe = document.createElement('div'); + probe.style.background = 'var(--accent)'; + document.body.append(probe); + const c = getComputedStyle(probe).backgroundColor; + probe.remove(); + return c; + })(), inView: !!(box && r && r.top >= box.top - 4 && r.bottom <= box.bottom + 4), gridMode: !!document.querySelector('.mob-lib-grid'), singles: document.querySelectorAll('.mob-lib-single-card').length, @@ -226,7 +234,7 @@ step('closing hands the reader to ALL THUMBS', read.gridMode && read.singles === step('exactly one frame is selected', read.selected.length === 1, `${read.selected.length}`); step('the frame swiped to is the selected one', read.selected[0] === swiped, `swiped=${swiped} selected=${read.selected[0]}`); step('the selected frame is on screen', read.inView); -step('the selected frame is marked in CSS', read.outline === 'rgb(245, 158, 11)', read.outline); +step('the selected frame is marked in the accent', read.outline === read.accent && read.accent.startsWith('rgb('), `${read.outline} vs accent ${read.accent}`); step('no page error', errors.length === 0, errors.join(' | ')); await browser.close(); diff --git a/docker/frontend/src/styles/mobile-library.css b/docker/frontend/src/styles/mobile-library.css index 5d051d3..7ad9e3a 100644 --- a/docker/frontend/src/styles/mobile-library.css +++ b/docker/frontend/src/styles/mobile-library.css @@ -2,11 +2,43 @@ .mob-lib-root { display: flex; + /* The phone paints itself from the app's theme: one alias per surface, one + per ink, the rest is colour maths, so Light/Dark and the accent reach the + phone for free — see tokens.css. */ + --ml-bg: var(--bg); + --ml-bg-soft: color-mix(in srgb, var(--bg) 70%, transparent); + --ml-bg-blur: color-mix(in srgb, var(--bg) 92%, transparent); + --ml-sunken: var(--bg-sunken); + --ml-panel: var(--bg-elev); + --ml-panel-2: color-mix(in srgb, var(--text) 8%, var(--bg-elev)); + --ml-popover: color-mix(in srgb, var(--bg-elev) 92%, transparent); + --ml-text: var(--text); + --ml-text-2: color-mix(in srgb, var(--text) 88%, var(--bg)); + --ml-text-3: color-mix(in srgb, var(--text) 80%, var(--bg)); + --ml-dim: var(--text-dim); + --ml-dim-2: color-mix(in srgb, var(--text-dim) 78%, var(--bg)); + --ml-dim-3: color-mix(in srgb, var(--text-dim) 72%, var(--bg)); + --ml-faint: color-mix(in srgb, var(--text) 55%, transparent); + --ml-line-faint: color-mix(in srgb, var(--text) 4%, transparent); + --ml-line-soft: color-mix(in srgb, var(--text) 7%, transparent); + --ml-line: color-mix(in srgb, var(--text) 10%, transparent); + --ml-line-strong: color-mix(in srgb, var(--text) 15%, transparent); + --ml-line-stronger: color-mix(in srgb, var(--text) 22%, transparent); + --ml-fill-faint: color-mix(in srgb, var(--text) 3%, transparent); + --ml-fill: color-mix(in srgb, var(--text) 7%, transparent); + --ml-fill-strong: color-mix(in srgb, var(--text) 13%, transparent); + --ml-fill-active: color-mix(in srgb, var(--text) 22%, transparent); + --ml-grip: color-mix(in srgb, var(--text) 30%, transparent); + --ml-grip-strong: color-mix(in srgb, var(--text) 60%, transparent); + --ml-blue: #60a5fa; + --ml-blue-2: #93c5fd; + --ml-green: #34d399; + --ml-red: #ef4444; flex-direction: column; height: 100%; width: 100%; - background: #101014; - color: #f4f4f5; + background: var(--ml-bg); + color: var(--ml-text); font-family: var(--sans, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif); overflow: hidden; position: relative; @@ -14,6 +46,15 @@ -webkit-user-select: none; } +/* Status inks are the only colours the tokens cannot express, so they get a + darker ink of their own on the light theme. */ +[data-theme="light"] .mob-lib-root { + --ml-blue: #2563eb; + --ml-blue-2: #1d4ed8; + --ml-green: #0f9d63; + --ml-red: #c2402f; +} + /* --- Top Header Bar --- */ .mob-lib-header { position: sticky; @@ -23,10 +64,10 @@ align-items: center; justify-content: space-between; padding: max(10px, env(safe-area-inset-top)) 16px 10px; - background: rgba(16, 16, 20, 0.88); + background: var(--ml-bg-blur); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); - border-bottom: 1px solid rgba(255, 255, 255, 0.06); + border-bottom: 1px solid var(--ml-line-soft); flex-shrink: 0; } @@ -41,7 +82,7 @@ align-items: center; gap: 7px; text-decoration: none; - color: #ffffff; + color: var(--ml-text); } .mob-lib-brand-img { @@ -62,7 +103,7 @@ font-size: 18px; font-weight: 700; letter-spacing: -0.02em; - color: #ffffff; + color: var(--ml-text); line-height: 1; } @@ -75,9 +116,9 @@ .mob-lib-header-title { font-size: 12px; font-weight: 600; - color: rgba(255, 255, 255, 0.55); + color: var(--ml-faint); padding-left: 8px; - border-left: 1px solid rgba(255, 255, 255, 0.15); + border-left: 1px solid var(--ml-line-strong); line-height: 1.2; } @@ -88,7 +129,7 @@ min-width: 0; max-width: 170px; padding-left: 8px; - border-left: 1px solid rgba(255, 255, 255, 0.15); + border-left: 1px solid var(--ml-line-strong); } .mob-lib-header-folder-icon { @@ -101,7 +142,7 @@ .mob-lib-header-folder-name { font-size: 13px; font-weight: 600; - color: #f4f4f5; + color: var(--ml-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -118,7 +159,7 @@ .mob-lib-folder-brand-text { font-size: 14px; font-weight: 700; - color: #f4f4f5; + color: var(--ml-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -130,10 +171,10 @@ align-items: center; justify-content: space-between; padding: 8px 14px; - background: rgba(22, 22, 28, 0.94); + background: var(--ml-popover); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); - border-bottom: 1px solid rgba(255, 255, 255, 0.08); + border-bottom: 1px solid var(--ml-line); flex-shrink: 0; z-index: 25; } @@ -163,7 +204,7 @@ font-size: 15px; font-weight: 700; letter-spacing: -0.02em; - color: #ffffff; + color: var(--ml-text); line-height: 1; } @@ -175,7 +216,7 @@ padding: 1px 6px; border-radius: 999px; background: rgba(66, 133, 244, 0.18); - color: #60a5fa; + color: var(--ml-blue); border: 1px solid rgba(66, 133, 244, 0.35); line-height: 1.4; } @@ -183,7 +224,7 @@ .mob-lib-immich-album-name { font-size: 13px; font-weight: 600; - color: #e4e4e7; + color: var(--ml-text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -198,7 +239,7 @@ .mob-lib-immich-count { font-size: 11px; - color: #a1a1aa; + color: var(--ml-dim); } .mob-lib-header-right { @@ -213,7 +254,7 @@ justify-content: center; background: transparent; border: none; - color: #d4d4d8; + color: var(--ml-text-3); cursor: pointer; padding: 4px; border-radius: 50%; @@ -229,11 +270,11 @@ height: 32px; border-radius: 50%; overflow: hidden; - border: 1.5px solid rgba(255, 255, 255, 0.2); + border: 1.5px solid var(--ml-line-stronger); display: flex; align-items: center; justify-content: center; - background: #27272a; + background: var(--ml-panel-2); } .mob-lib-avatar img { @@ -248,8 +289,8 @@ gap: 4px; padding: 4px 10px; border-radius: 999px; - background: rgba(255, 255, 255, 0.1); - color: #f4f4f5; + background: var(--ml-fill); + color: var(--ml-text); font-size: 11px; font-weight: 600; text-decoration: none; @@ -258,7 +299,7 @@ } .mob-lib-studio-link:active { - background: rgba(255, 255, 255, 0.2); + background: var(--ml-fill-active); } /* --- Main Content Area --- */ @@ -289,7 +330,7 @@ padding: 14px 12px 8px; font-size: 16px; font-weight: 600; - color: #f4f4f5; + color: var(--ml-text); letter-spacing: -0.01em; } @@ -297,7 +338,7 @@ width: 22px; height: 22px; border-radius: 50%; - border: 1.5px solid rgba(255, 255, 255, 0.3); + border: 1.5px solid var(--ml-grip); display: flex; align-items: center; justify-content: center; @@ -311,7 +352,7 @@ .mob-lib-date-check.checked { background: var(--accent, #f59e0b); border-color: var(--accent, #f59e0b); - color: #000; + color: var(--accent-fg); } /* --- 3-Column Photo Grid --- */ @@ -324,7 +365,7 @@ .mob-lib-thumb-cell { position: relative; aspect-ratio: 1; - background: #1c1c22; + background: var(--ml-panel-2); overflow: hidden; cursor: pointer; touch-action: manipulation; @@ -334,7 +375,7 @@ /* The frame the reader stopped at in the preview, lit up in the grid. */ .mob-lib-thumb-cell.selected { - outline: 2px solid #f59e0b; + outline: 2px solid var(--accent); outline-offset: -2px; } @@ -385,7 +426,7 @@ padding: 1px 4px; border-radius: 4px; font-size: 10px; - color: #fbbf24; + color: var(--accent); backdrop-filter: blur(4px); pointer-events: none; } @@ -402,13 +443,13 @@ align-items: center; justify-content: center; gap: 5px; - background: rgba(28, 30, 38, 0.92); + background: var(--ml-popover); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); - border: 1px solid rgba(255, 255, 255, 0.22); + border: 1px solid var(--ml-line-stronger); border-radius: 999px; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.6); - color: #ffffff; + color: var(--ml-text); cursor: grab; user-select: none; -webkit-user-select: none; @@ -426,8 +467,8 @@ .mob-lib-scroll-handle:active { cursor: grabbing; transform: scale(1.08); - background: rgba(45, 48, 62, 0.98); - border-color: rgba(255, 255, 255, 0.4); + background: var(--ml-panel-2); + border-color: var(--ml-grip); } .mob-lib-scroll-arrow { @@ -435,7 +476,7 @@ align-items: center; justify-content: center; pointer-events: none; - color: #f4f4f5; + color: var(--ml-text); opacity: 0.9; } @@ -454,7 +495,7 @@ .mob-lib-search-icon { position: absolute; left: 12px; - color: #71717a; + color: var(--ml-dim-2); pointer-events: none; } @@ -462,9 +503,9 @@ width: 100%; padding: 10px 36px 10px 38px; border-radius: 999px; - border: 1px solid rgba(255, 255, 255, 0.12); - background: #1c1c22; - color: #ffffff; + border: 1px solid var(--ml-line-strong); + background: var(--ml-panel); + color: var(--ml-text); font-size: 14px; outline: none; transition: border-color 0.2s; @@ -479,7 +520,7 @@ right: 12px; background: transparent; border: none; - color: #71717a; + color: var(--ml-dim-2); cursor: pointer; padding: 4px; display: flex; @@ -504,15 +545,15 @@ border-radius: 999px; font-size: 12px; font-weight: 500; - border: 1px solid rgba(255, 255, 255, 0.12); - background: #1c1c22; - color: #d4d4d8; + border: 1px solid var(--ml-line-strong); + background: var(--ml-panel); + color: var(--ml-text-3); cursor: pointer; } .mob-lib-chip.active { background: var(--accent, #f59e0b); - color: #000000; + color: var(--accent-fg); border-color: var(--accent, #f59e0b); font-weight: 600; } @@ -522,10 +563,10 @@ position: sticky; top: 0; z-index: 30; - background: rgba(16, 16, 20, 0.95); + background: var(--ml-bg-blur); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); - border-bottom: 1px solid rgba(255, 255, 255, 0.08); + border-bottom: 1px solid var(--ml-line); padding: 10px 14px; display: flex; flex-direction: column; @@ -534,9 +575,9 @@ } .mob-lib-search-close-btn { - background: rgba(255, 255, 255, 0.1); - border: 1px solid rgba(255, 255, 255, 0.15); - color: #e4e4e7; + background: var(--ml-fill); + border: 1px solid var(--ml-line-strong); + color: var(--ml-text-2); font-size: 13px; font-weight: 600; width: 34px; @@ -553,7 +594,7 @@ } .mob-lib-search-close-btn:active { - background: rgba(255, 255, 255, 0.2); + background: var(--ml-fill-active); } /* --- Search Top Row with Input, View Mode Toggle, and Close --- */ @@ -567,8 +608,8 @@ .mob-lib-view-toggle { display: inline-flex; align-items: center; - background: rgba(255, 255, 255, 0.08); - border: 1px solid rgba(255, 255, 255, 0.12); + background: var(--ml-fill); + border: 1px solid var(--ml-line-strong); border-radius: 8px; padding: 2px; flex-shrink: 0; @@ -584,7 +625,7 @@ border-radius: 6px; border: none; background: transparent; - color: #a1a1aa; + color: var(--ml-dim); cursor: pointer; transition: all 0.15s ease; padding: 0; @@ -595,8 +636,8 @@ } .mob-lib-view-btn.active { - background: rgba(255, 255, 255, 0.22); - color: #ffffff; + background: var(--ml-fill-active); + color: var(--ml-text); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35); } @@ -617,7 +658,7 @@ .mob-lib-filter-scope-label { font-size: 11px; font-weight: 600; - color: #a1a1aa; + color: var(--ml-dim); text-transform: uppercase; letter-spacing: 0.5px; flex-shrink: 0; @@ -632,9 +673,9 @@ border-radius: 9999px; font-size: 12px; font-weight: 500; - color: #a1a1aa; - background: rgba(255, 255, 255, 0.06); - border: 1px solid rgba(255, 255, 255, 0.12); + color: var(--ml-dim); + background: var(--ml-fill); + border: 1px solid var(--ml-line-strong); cursor: pointer; white-space: nowrap; flex-shrink: 0; @@ -648,7 +689,7 @@ .mob-lib-scope-pill.active { background: rgba(59, 130, 246, 0.2); border-color: rgba(59, 130, 246, 0.6); - color: #60a5fa; + color: var(--ml-blue); font-weight: 600; box-shadow: 0 1px 4px rgba(59, 130, 246, 0.2); } @@ -673,13 +714,13 @@ display: inline-flex; align-items: center; flex-shrink: 0; - background: rgba(255, 255, 255, 0.07); - border: 1px solid rgba(255, 255, 255, 0.15); + background: var(--ml-fill); + border: 1px solid var(--ml-line-strong); border-radius: 8px; padding: 0 8px; height: 32px; font-size: 12px; - color: #e4e4e7; + color: var(--ml-text-2); cursor: pointer; transition: all 0.15s ease; white-space: nowrap; @@ -689,7 +730,7 @@ .mob-lib-dropbox-btn.active { background: rgba(245, 158, 11, 0.18); border-color: rgba(245, 158, 11, 0.6); - color: #fbbf24; + color: var(--accent); font-weight: 600; } @@ -699,13 +740,13 @@ align-items: center; gap: 4px; flex-shrink: 0; - background: rgba(255, 255, 255, 0.07); - border: 1px solid rgba(255, 255, 255, 0.15); + background: var(--ml-fill); + border: 1px solid var(--ml-line-strong); border-radius: 8px; padding: 0 10px; height: 32px; font-size: 12px; - color: #e4e4e7; + color: var(--ml-text-2); cursor: pointer; transition: all 0.15s ease; white-space: nowrap; @@ -714,7 +755,7 @@ .mob-lib-dropbox-btn.open { border-color: rgba(96, 165, 250, 0.7); background: rgba(59, 130, 246, 0.18); - color: #93c5fd; + color: var(--ml-blue-2); } .mob-lib-dropbox-select { @@ -732,8 +773,8 @@ } .mob-lib-dropbox-select option { - background: #1c1c24; - color: #ffffff; + background: var(--ml-panel); + color: var(--ml-text); } .mob-lib-dropbox-caret { @@ -746,8 +787,8 @@ /* --- Popover Card for Year/Month/Date & Time --- */ .mob-lib-popover-card { margin-top: 4px; - background: #18181f; - border: 1px solid rgba(255, 255, 255, 0.14); + background: var(--ml-panel); + border: 1px solid var(--ml-line-strong); border-radius: 12px; padding: 12px; display: flex; @@ -777,14 +818,14 @@ .mob-lib-popover-title { font-size: 12px; font-weight: 700; - color: #d4d4d8; + color: var(--ml-text-3); letter-spacing: 0.02em; } .mob-lib-popover-reset-btn { background: transparent; border: none; - color: #ef4444; + color: var(--ml-red); font-size: 11px; font-weight: 600; cursor: pointer; @@ -817,14 +858,14 @@ .mob-lib-popover-label { font-size: 10px; font-weight: 600; - color: #a1a1aa; + color: var(--ml-dim); text-transform: uppercase; } .mob-lib-popover-select { - background: rgba(255, 255, 255, 0.07); - border: 1px solid rgba(255, 255, 255, 0.14); - color: #ffffff; + background: var(--ml-fill); + border: 1px solid var(--ml-line-strong); + color: var(--ml-text); border-radius: 8px; padding: 6px 8px; font-size: 12px; @@ -832,8 +873,8 @@ } .mob-lib-popover-select option { - background: #1c1c24; - color: #ffffff; + background: var(--ml-panel); + color: var(--ml-text); } .mob-lib-popover-footer { @@ -842,9 +883,9 @@ } .mob-lib-popover-done-btn { - background: rgba(255, 255, 255, 0.12); - border: 1px solid rgba(255, 255, 255, 0.18); - color: #ffffff; + background: var(--ml-fill-strong); + border: 1px solid var(--ml-line-stronger); + color: var(--ml-text); font-size: 11px; font-weight: 600; padding: 5px 14px; @@ -853,7 +894,7 @@ } .mob-lib-popover-done-btn:active { - background: rgba(255, 255, 255, 0.24); + background: var(--ml-fill-active); } /* --- Single Photo Mode (1 large card per row) --- */ @@ -865,8 +906,8 @@ } .mob-lib-single-card { - background: rgba(255, 255, 255, 0.035); - border: 1px solid rgba(255, 255, 255, 0.08); + background: var(--ml-fill-faint); + border: 1px solid var(--ml-line); border-radius: 14px; overflow: hidden; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35); @@ -878,14 +919,14 @@ .mob-lib-single-card:active { transform: scale(0.99); - border-color: rgba(255, 255, 255, 0.2); + border-color: var(--ml-line-stronger); } .mob-lib-single-img-wrap { position: relative; width: 100%; aspect-ratio: 4 / 3; - background: #09090b; + background: var(--ml-sunken); display: flex; align-items: center; justify-content: center; @@ -913,13 +954,13 @@ display: flex; flex-direction: column; gap: 4px; - background: rgba(18, 18, 22, 0.7); + background: var(--ml-bg-soft); } .mob-lib-single-name { font-size: 13px; font-weight: 600; - color: #ffffff; + color: var(--ml-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; @@ -927,7 +968,7 @@ .mob-lib-single-date { font-size: 11px; - color: #a1a1aa; + color: var(--ml-dim); } /* --- Album Folder Tree Column (Desktop style on Mobile) --- */ @@ -944,22 +985,22 @@ align-items: center; justify-content: space-between; padding: 8px 12px; - background: rgba(255, 255, 255, 0.03); - border: 1px solid rgba(255, 255, 255, 0.07); + background: var(--ml-fill-faint); + border: 1px solid var(--ml-line-soft); border-radius: 10px; } .mob-lib-tree-toolbar-title { font-size: 13px; font-weight: 700; - color: #f4f4f5; + color: var(--ml-text); } .mob-lib-tree-list { display: flex; flex-direction: column; - background: rgba(255, 255, 255, 0.02); - border: 1px solid rgba(255, 255, 255, 0.07); + background: var(--ml-fill-faint); + border: 1px solid var(--ml-line-soft); border-radius: 12px; overflow: hidden; } @@ -969,11 +1010,11 @@ align-items: center; gap: 8px; padding: 11px 12px; - color: #d4d4d8; + color: var(--ml-text-3); cursor: pointer; user-select: none; -webkit-user-select: none; - border-bottom: 1px solid rgba(255, 255, 255, 0.04); + border-bottom: 1px solid var(--ml-line-faint); transition: background 0.15s, color 0.15s; } @@ -982,12 +1023,12 @@ } .mob-lib-tree-row:active { - background: rgba(255, 255, 255, 0.08); + background: var(--ml-fill); } .mob-lib-tree-row.selected { background: rgba(245, 158, 11, 0.15); - color: #f59e0b; + color: var(--accent); } .mob-lib-tree-caret { @@ -996,7 +1037,7 @@ height: 0; border-top: 5px solid transparent; border-bottom: 5px solid transparent; - border-left: 7px solid rgba(255, 255, 255, 0.6); + border-left: 7px solid var(--ml-grip-strong); transition: transform 0.15s; flex-shrink: 0; cursor: pointer; @@ -1031,8 +1072,8 @@ .mob-lib-tree-count { font-size: 11px; font-family: var(--mono, ui-monospace, monospace); - color: #71717a; - background: rgba(255, 255, 255, 0.06); + color: var(--ml-dim-2); + background: var(--ml-fill); padding: 2px 7px; border-radius: 999px; flex-shrink: 0; @@ -1041,7 +1082,7 @@ .mob-lib-tree-more-btn { background: transparent; border: none; - color: #a1a1aa; + color: var(--ml-dim); font-size: 18px; padding: 4px 8px; cursor: pointer; @@ -1051,8 +1092,8 @@ } .mob-lib-tree-more-btn:active { - background: rgba(255, 255, 255, 0.12); - color: #ffffff; + background: var(--ml-fill-strong); + color: var(--ml-text); } /* --- Context Menu Backdrop & Panel --- */ @@ -1068,8 +1109,8 @@ z-index: 61; min-width: 200px; padding: 6px; - background: #1c1c24; - border: 1px solid rgba(255, 255, 255, 0.15); + background: var(--ml-panel); + border: 1px solid var(--ml-line-strong); border-radius: 12px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.8); display: flex; @@ -1087,10 +1128,10 @@ padding: 6px 10px 6px; font-size: 11px; font-weight: 700; - color: #a1a1aa; + color: var(--ml-dim); text-transform: uppercase; letter-spacing: 0.04em; - border-bottom: 1px solid rgba(255, 255, 255, 0.06); + border-bottom: 1px solid var(--ml-line-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -1110,8 +1151,8 @@ .mob-lib-album-card { display: flex; flex-direction: column; - background: #18181e; - border: 1px solid rgba(255, 255, 255, 0.08); + background: var(--ml-panel); + border: 1px solid var(--ml-line); border-radius: 12px; overflow: hidden; cursor: pointer; @@ -1126,7 +1167,7 @@ .mob-lib-album-cover { width: 100%; aspect-ratio: 1; - background: #23232b; + background: var(--ml-panel-2); position: relative; overflow: hidden; } @@ -1144,7 +1185,7 @@ display: flex; align-items: center; justify-content: center; - color: #71717a; + color: var(--ml-dim-2); } .mob-lib-album-info { @@ -1157,7 +1198,7 @@ .mob-lib-album-title { font-size: 14px; font-weight: 600; - color: #f4f4f5; + color: var(--ml-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -1165,7 +1206,7 @@ .mob-lib-album-count { font-size: 12px; - color: #a1a1aa; + color: var(--ml-dim); } /* --- Library / Cloud Management View --- */ @@ -1177,8 +1218,8 @@ } .mob-lib-card { - background: #18181e; - border: 1px solid rgba(255, 255, 255, 0.08); + background: var(--ml-panel); + border: 1px solid var(--ml-line); border-radius: 14px; padding: 16px; display: flex; @@ -1195,7 +1236,7 @@ .mob-lib-card-title { font-size: 15px; font-weight: 600; - color: #f4f4f5; + color: var(--ml-text); display: flex; align-items: center; gap: 8px; @@ -1207,7 +1248,7 @@ gap: 4px; font-size: 11px; font-weight: 600; - color: #34d399; + color: var(--ml-green); background: rgba(52, 211, 153, 0.12); padding: 2px 8px; border-radius: 999px; @@ -1218,12 +1259,12 @@ width: 6px; height: 6px; border-radius: 50%; - background: #34d399; + background: var(--ml-green); } .mob-lib-card-meta { font-size: 12px; - color: #a1a1aa; + color: var(--ml-dim); display: flex; flex-direction: column; gap: 4px; @@ -1245,9 +1286,9 @@ border-radius: 8px; font-size: 12px; font-weight: 600; - border: 1px solid rgba(255, 255, 255, 0.12); - background: #23232b; - color: #f4f4f5; + border: 1px solid var(--ml-line-strong); + background: var(--ml-panel-2); + color: var(--ml-text); cursor: pointer; transition: all 0.2s; } @@ -1258,13 +1299,13 @@ .mob-lib-btn.primary { background: var(--accent, #f59e0b); - color: #000000; + color: var(--accent-fg); border-color: var(--accent, #f59e0b); } .mob-lib-btn.danger { background: rgba(239, 68, 68, 0.15); - color: #f87171; + color: var(--ml-red); border-color: rgba(239, 68, 68, 0.3); } @@ -1311,19 +1352,19 @@ text-align: center; padding: 48px 24px; gap: 14px; - color: #a1a1aa; + color: var(--ml-dim); } .mob-lib-empty-icon { width: 48px; height: 48px; - color: #52525b; + color: var(--ml-dim-3); } .mob-lib-empty-title { font-size: 16px; font-weight: 600; - color: #e4e4e7; + color: var(--ml-text-2); } .mob-lib-empty-desc { @@ -1341,8 +1382,8 @@ z-index: 40; height: calc(60px + env(safe-area-inset-bottom)); padding-bottom: env(safe-area-inset-bottom); - background: #18181b; - border-top: 1px solid rgba(255, 255, 255, 0.08); + background: var(--ml-panel); + border-top: 1px solid var(--ml-line); display: flex; align-items: center; justify-content: space-around; @@ -1358,7 +1399,7 @@ gap: 3px; background: transparent; border: none; - color: rgba(255, 255, 255, 0.55); + color: var(--ml-faint); cursor: pointer; padding: 6px 0; text-decoration: none; @@ -1375,11 +1416,11 @@ } .mob-lib-tab-item.active .mob-lib-tab-pill { - background: rgba(255, 255, 255, 0.14); + background: var(--ml-fill-strong); } .mob-lib-tab-item.active { - color: #ffffff; + color: var(--ml-text); } .mob-lib-tab-label { @@ -1391,7 +1432,7 @@ .mob-lib-tab-item.active .mob-lib-tab-label { font-weight: 600; - color: #ffffff; + color: var(--ml-text); } /* --- Fullscreen Photo Preview Modal --- */ @@ -1399,7 +1440,7 @@ position: fixed; inset: 0; z-index: 60; - background: #09090b; + background: var(--ml-sunken); display: flex; flex-direction: column; overflow: hidden; @@ -1416,9 +1457,9 @@ align-items: center; justify-content: space-between; padding: max(10px, env(safe-area-inset-top)) 16px 10px; - background: rgba(9, 9, 11, 0.85); + background: var(--ml-bg-blur); backdrop-filter: blur(16px); - border-bottom: 1px solid rgba(255, 255, 255, 0.08); + border-bottom: 1px solid var(--ml-line); flex-shrink: 0; z-index: 10; } @@ -1426,7 +1467,7 @@ .mob-lib-preview-title { font-size: 14px; font-weight: 600; - color: #f4f4f5; + color: var(--ml-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -1456,9 +1497,9 @@ flex-direction: column; gap: 12px; padding: 12px 16px max(14px, env(safe-area-inset-bottom)); - background: rgba(9, 9, 11, 0.9); + background: var(--ml-bg-blur); backdrop-filter: blur(16px); - border-top: 1px solid rgba(255, 255, 255, 0.08); + border-top: 1px solid var(--ml-line); flex-shrink: 0; z-index: 10; } @@ -1478,14 +1519,14 @@ background: transparent; border: none; font-size: 20px; - color: rgba(255, 255, 255, 0.25); + color: var(--ml-dim-3); cursor: pointer; padding: 4px; line-height: 1; } .mob-lib-star-btn.active { - color: #fbbf24; + color: var(--accent); } .mob-lib-preview-rot-btns { @@ -1501,7 +1542,7 @@ font-weight: 700; letter-spacing: 0.03em; background: var(--accent, #f59e0b); - color: #000000; + color: var(--accent-fg); border: none; cursor: pointer; display: flex; @@ -1521,9 +1562,9 @@ flex-direction: column; gap: 3px; font-size: 11.5px; - color: #a1a1aa; - background: rgba(255, 255, 255, 0.03); - border: 1px solid rgba(255, 255, 255, 0.07); + color: var(--ml-dim); + background: var(--ml-fill-faint); + border: 1px solid var(--ml-line-soft); border-radius: 10px; padding: 9px 12px; min-width: 0; @@ -1533,7 +1574,7 @@ } .mob-lib-meta-name { - color: #f4f4f5; + color: var(--ml-text); font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace); font-size: 12.5px; font-weight: 700; @@ -1550,11 +1591,11 @@ } .mob-lib-meta-place { - color: #60a5fa; + color: var(--ml-blue); } .mob-lib-meta-specs { - color: #e4e4e7; + color: var(--ml-text-2); font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace); font-size: 11px; } diff --git a/docker/frontend/src/ui/MobileLibrary.tsx b/docker/frontend/src/ui/MobileLibrary.tsx index d5a1788..72ee49b 100644 --- a/docker/frontend/src/ui/MobileLibrary.tsx +++ b/docker/frontend/src/ui/MobileLibrary.tsx @@ -841,7 +841,7 @@ export function MobileLibrary({ {user?.avatar ? ( User ) : ( - + {(user?.email || 'U').charAt(0).toUpperCase()} )} @@ -869,7 +869,7 @@ export function MobileLibrary({