b96e8c5747
The download progress "peers" chip previously rendered as
`[icon] from N peers` — a full mini-sentence sitting between the speed
and ETA stats. With four groups already separated by middots, the extra
preposition and unit made the row read as prose rather than a stat
strip, and the singular/plural switch added a second source of layout
jitter on top of the digit-width change.
Update the design reference (README, components.jsx, styles.css) so the
chip shows just the users glyph and the count, matching the visual
weight of the other stat groups. The full sentence
("Downloading from N peers on the LAN") moves to the `title` tooltip,
which keeps the affordance discoverable without spending row width on
it. The count adopts `var(--t-1)` + 600 + tabular-nums directly on
`.dl-peers` (no inner `<strong>` needed), so the chip is a single span.
Also tighten the container-query breakpoints. Removing the prose makes
the chip much narrower, so the previous 300px cutoff for hiding peers
and 380px cutoff for hiding ETA were over-eager — both stats now fit
comfortably in narrower modals. Drop them to 240px (peers) and 320px
(ETA). The pct/cancel column still never collapses.
Test Plan
- Visual review of the design reference HTML at component widths
240px / 320px / 380px to confirm peers and ETA drop at the new
thresholds rather than the old ones.
- Confirm the chip's tooltip still spells out the full sentence.
1138 lines
30 KiB
CSS
1138 lines
30 KiB
CSS
/* SoftLAN Launcher — styles
|
|
Steam-like dark UI, blue accent (configurable). System sans for UI,
|
|
Bebas Neue for cover-art display type.
|
|
*/
|
|
|
|
@import url('https://fonts.googleapis.com/css2?family=Bebas+Neue&display=swap');
|
|
|
|
:root {
|
|
--accent: #3b82f6;
|
|
--bg-0: #0a0e13;
|
|
--bg-1: #0f151c;
|
|
--bg-2: #131b25;
|
|
--bg-3: #1a2330;
|
|
--bg-4: #232f3e;
|
|
--bd-1: rgba(255,255,255,0.06);
|
|
--bd-2: rgba(255,255,255,0.10);
|
|
--bd-3: rgba(255,255,255,0.16);
|
|
--t-1: #e6edf3;
|
|
--t-2: #9aa6b4;
|
|
--t-3: #6b7785;
|
|
--t-4: #4a5663;
|
|
--ok: #22c55e;
|
|
--warn: #f59e0b;
|
|
--danger: #ef4444;
|
|
--font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI Variable", "Segoe UI", Inter, system-ui, sans-serif;
|
|
--font-display: "Bebas Neue", "Oswald", Impact, "Arial Narrow Bold", sans-serif;
|
|
--radius-sm: 6px;
|
|
--radius-md: 10px;
|
|
--radius-lg: 14px;
|
|
}
|
|
|
|
* { box-sizing: border-box; }
|
|
|
|
/* ─── Launcher root ─── */
|
|
.launcher {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
background: var(--bg-0);
|
|
color: var(--t-1);
|
|
font-family: var(--font-ui);
|
|
font-size: 13px;
|
|
line-height: 1.4;
|
|
overflow: hidden;
|
|
position: relative;
|
|
isolation: isolate;
|
|
}
|
|
|
|
/* Background variants */
|
|
.bg-flat { background: var(--bg-0); }
|
|
.bg-gradient {
|
|
background:
|
|
radial-gradient(ellipse 80% 50% at 50% -10%, color-mix(in srgb, var(--accent) 22%, transparent) 0%, transparent 60%),
|
|
linear-gradient(180deg, #0c1218 0%, var(--bg-0) 100%);
|
|
}
|
|
.bg-animated {
|
|
background:
|
|
radial-gradient(ellipse 60% 40% at 20% 0%, color-mix(in srgb, var(--accent) 24%, transparent) 0%, transparent 55%),
|
|
radial-gradient(ellipse 55% 40% at 85% 8%, color-mix(in srgb, var(--accent) 16%, transparent) 0%, transparent 55%),
|
|
linear-gradient(180deg, #0c1218 0%, var(--bg-0) 100%);
|
|
background-size: 100% 100%;
|
|
animation: bgshift 18s ease-in-out infinite alternate;
|
|
}
|
|
@keyframes bgshift {
|
|
0% { background-position: 0% 0%, 0% 0%, 0% 0%; }
|
|
100% { background-position: 10% 4%, -6% 2%, 0% 0%; }
|
|
}
|
|
|
|
/* ─── Top bar — shared ─── */
|
|
.topbar {
|
|
position: relative;
|
|
z-index: 10;
|
|
background: rgba(10,14,19,0.65);
|
|
-webkit-backdrop-filter: blur(20px) saturate(140%);
|
|
backdrop-filter: blur(20px) saturate(140%);
|
|
border-bottom: 1px solid var(--bd-1);
|
|
}
|
|
|
|
/* Variant 1: single row */
|
|
.topbar-single {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 18px;
|
|
padding: 14px 24px;
|
|
flex-wrap: nowrap;
|
|
}
|
|
|
|
/* Variant 2: two row */
|
|
.topbar-two .topbar-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 16px;
|
|
padding: 12px 24px;
|
|
}
|
|
.topbar-two .topbar-row1 {
|
|
border-bottom: 1px solid var(--bd-1);
|
|
}
|
|
.topbar-two .topbar-row1-right { margin-left: auto; display: flex; align-items: center; gap: 16px; }
|
|
.topbar-two .topbar-row2 { padding-top: 4px; padding-bottom: 4px; }
|
|
.topbar-two .topbar-row2-right { margin-left: auto; display: flex; align-items: center; gap: 12px; }
|
|
|
|
/* ─── Brand ─── */
|
|
.brand {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
flex-shrink: 0;
|
|
}
|
|
.brand-mark {
|
|
width: 28px; height: 28px;
|
|
border-radius: 7px;
|
|
display: grid; place-items: center;
|
|
font-family: var(--font-display);
|
|
font-size: 20px;
|
|
letter-spacing: 0.02em;
|
|
color: white;
|
|
box-shadow: 0 6px 20px -6px color-mix(in srgb, var(--accent) 60%, black), inset 0 1px 0 rgba(255,255,255,0.22);
|
|
}
|
|
.brand-name {
|
|
font-weight: 700;
|
|
font-size: 15px;
|
|
letter-spacing: -0.005em;
|
|
color: var(--t-1);
|
|
}
|
|
.brand-name-soft { color: var(--t-3); font-weight: 500; margin-left: 4px; }
|
|
|
|
/* ─── Segmented filters (variant 1) ─── */
|
|
.seg {
|
|
position: relative;
|
|
display: inline-flex;
|
|
background: var(--bg-2);
|
|
border: 1px solid var(--bd-1);
|
|
border-radius: 999px;
|
|
padding: 4px;
|
|
flex-shrink: 0;
|
|
}
|
|
.seg-thumb {
|
|
position: absolute;
|
|
top: 4px; bottom: 4px;
|
|
border-radius: 999px;
|
|
transition: left .22s cubic-bezier(.4,1.2,.5,1), width .22s cubic-bezier(.4,1.2,.5,1), background .15s;
|
|
box-shadow: 0 4px 14px -4px color-mix(in srgb, var(--accent) 60%, black);
|
|
}
|
|
.seg-btn {
|
|
position: relative;
|
|
z-index: 1;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 8px 16px;
|
|
background: transparent;
|
|
color: var(--t-2);
|
|
border: 0;
|
|
border-radius: 999px;
|
|
font: inherit;
|
|
font-weight: 600;
|
|
font-size: 12.5px;
|
|
cursor: pointer;
|
|
white-space: nowrap;
|
|
transition: color .15s;
|
|
}
|
|
.seg-btn:hover { color: var(--t-1); }
|
|
.seg-btn.is-active { color: white; }
|
|
.seg-count {
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
padding: 1px 6px;
|
|
border-radius: 999px;
|
|
background: rgba(255,255,255,0.08);
|
|
color: inherit;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
.seg-btn.is-active .seg-count { background: rgba(0,0,0,0.25); color: white; }
|
|
|
|
/* ─── Underline filters (variant 2) ─── */
|
|
.utabs {
|
|
display: flex;
|
|
align-items: stretch;
|
|
gap: 4px;
|
|
}
|
|
.utab {
|
|
position: relative;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 10px 14px 12px;
|
|
background: transparent;
|
|
border: 0;
|
|
color: var(--t-2);
|
|
font: inherit;
|
|
font-weight: 600;
|
|
font-size: 13.5px;
|
|
cursor: pointer;
|
|
transition: color .15s;
|
|
}
|
|
.utab:hover { color: var(--t-1); }
|
|
.utab.is-active { color: var(--t-1); }
|
|
.utab-count {
|
|
font-size: 11.5px;
|
|
font-weight: 600;
|
|
padding: 1px 7px;
|
|
border-radius: 999px;
|
|
background: rgba(255,255,255,0.06);
|
|
color: var(--t-3);
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
.utab.is-active .utab-count { color: var(--t-1); background: rgba(255,255,255,0.10); }
|
|
.utab-underline {
|
|
position: absolute;
|
|
left: 12px; right: 12px;
|
|
bottom: 0;
|
|
height: 2px;
|
|
border-radius: 2px 2px 0 0;
|
|
opacity: 0;
|
|
transform: scaleX(0.4);
|
|
transform-origin: center;
|
|
transition: opacity .2s, transform .25s cubic-bezier(.4,1.2,.5,1);
|
|
}
|
|
.utab.is-active .utab-underline { opacity: 1; transform: scaleX(1); }
|
|
|
|
/* ─── Search ─── */
|
|
.search {
|
|
position: relative;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 0 12px;
|
|
background: var(--bg-2);
|
|
border: 1px solid var(--bd-1);
|
|
border-radius: 8px;
|
|
height: 36px;
|
|
min-width: 220px;
|
|
color: var(--t-3);
|
|
transition: border-color .15s, background .15s, box-shadow .15s;
|
|
}
|
|
.search-wide { min-width: 320px; flex: 0 1 380px; }
|
|
.search:focus-within {
|
|
border-color: color-mix(in srgb, var(--accent) 60%, var(--bd-2));
|
|
background: var(--bg-1);
|
|
box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 16%, transparent);
|
|
}
|
|
.search:focus-within { color: var(--t-1); }
|
|
.search input {
|
|
flex: 1; min-width: 0;
|
|
background: transparent; border: 0; outline: 0;
|
|
color: var(--t-1);
|
|
font: inherit;
|
|
font-size: 13px;
|
|
}
|
|
.search input::placeholder { color: var(--t-3); }
|
|
.search-kbd {
|
|
display: inline-grid; place-items: center;
|
|
min-width: 18px;
|
|
height: 18px;
|
|
padding: 0 5px;
|
|
border-radius: 4px;
|
|
background: rgba(255,255,255,0.06);
|
|
border: 1px solid var(--bd-1);
|
|
font-size: 11px;
|
|
color: var(--t-3);
|
|
font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
|
|
}
|
|
.search:focus-within .search-kbd { opacity: 0.4; }
|
|
|
|
/* ─── Sort menu ─── */
|
|
.sort { position: relative; flex-shrink: 0; }
|
|
.sort-btn {
|
|
display: inline-flex; align-items: center; gap: 8px;
|
|
height: 36px; padding: 0 12px;
|
|
background: var(--bg-2);
|
|
border: 1px solid var(--bd-1);
|
|
border-radius: 8px;
|
|
color: var(--t-2);
|
|
font: inherit; font-size: 12.5px;
|
|
cursor: pointer;
|
|
transition: border-color .15s, color .15s;
|
|
}
|
|
.sort-btn:hover { color: var(--t-1); border-color: var(--bd-2); }
|
|
.sort-btn strong { color: var(--t-1); font-weight: 600; }
|
|
.sort-menu {
|
|
position: absolute;
|
|
top: calc(100% + 6px);
|
|
right: 0;
|
|
z-index: 50;
|
|
min-width: 200px;
|
|
padding: 4px;
|
|
background: var(--bg-3);
|
|
border: 1px solid var(--bd-2);
|
|
border-radius: 10px;
|
|
box-shadow: 0 16px 40px -8px rgba(0,0,0,0.5), 0 0 0 1px rgba(255,255,255,0.04);
|
|
}
|
|
.sort-menu button {
|
|
display: flex; align-items: center; gap: 8px;
|
|
width: 100%;
|
|
padding: 8px 10px;
|
|
background: transparent;
|
|
border: 0;
|
|
border-radius: 6px;
|
|
color: var(--t-1);
|
|
font: inherit; font-size: 12.5px;
|
|
text-align: left;
|
|
cursor: pointer;
|
|
}
|
|
.sort-menu button:hover { background: rgba(255,255,255,0.06); }
|
|
.sort-check { width: 14px; display: inline-grid; place-items: center; color: var(--accent); }
|
|
|
|
/* ─── Directory button ─── */
|
|
.dirbtn {
|
|
display: inline-flex; align-items: center; gap: 8px;
|
|
height: 36px; padding: 0 12px;
|
|
background: var(--bg-2);
|
|
border: 1px solid var(--bd-1);
|
|
border-radius: 8px;
|
|
color: var(--t-2);
|
|
font: inherit; font-size: 12.5px;
|
|
cursor: pointer;
|
|
max-width: 360px;
|
|
transition: border-color .15s, color .15s;
|
|
flex-shrink: 1;
|
|
min-width: 0;
|
|
}
|
|
.dirbtn:hover { border-color: var(--bd-2); color: var(--t-1); }
|
|
.dirbtn-label { color: var(--t-1); font-weight: 600; flex-shrink: 0; }
|
|
.dirbtn-path {
|
|
color: var(--t-3);
|
|
font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
|
|
font-size: 11.5px;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
min-width: 0;
|
|
}
|
|
|
|
/* ─── Kebab menu ─── */
|
|
.kebab { position: relative; }
|
|
.kebab-btn {
|
|
width: 36px; height: 36px;
|
|
display: grid; place-items: center;
|
|
background: var(--bg-2);
|
|
border: 1px solid var(--bd-1);
|
|
border-radius: 8px;
|
|
color: var(--t-2);
|
|
cursor: pointer;
|
|
transition: color .15s, border-color .15s;
|
|
}
|
|
.kebab-btn:hover { color: var(--t-1); border-color: var(--bd-2); }
|
|
.kebab-menu {
|
|
position: absolute;
|
|
top: calc(100% + 6px);
|
|
right: 0;
|
|
z-index: 50;
|
|
min-width: 180px;
|
|
padding: 4px;
|
|
background: var(--bg-3);
|
|
border: 1px solid var(--bd-2);
|
|
border-radius: 10px;
|
|
box-shadow: 0 16px 40px -8px rgba(0,0,0,0.5);
|
|
}
|
|
.kebab-menu button {
|
|
display: block;
|
|
width: 100%;
|
|
padding: 8px 10px;
|
|
background: transparent;
|
|
border: 0;
|
|
border-radius: 6px;
|
|
color: var(--t-1);
|
|
font: inherit; font-size: 12.5px;
|
|
text-align: left;
|
|
cursor: pointer;
|
|
}
|
|
.kebab-menu button:hover { background: rgba(255,255,255,0.06); }
|
|
.kebab-sep { height: 1px; background: var(--bd-1); margin: 4px 0; }
|
|
|
|
/* ─── Storage meter ─── */
|
|
.storage {
|
|
display: flex; flex-direction: column;
|
|
gap: 6px;
|
|
min-width: 240px;
|
|
}
|
|
.storage-compact { min-width: 200px; }
|
|
.storage-bar {
|
|
position: relative;
|
|
height: 6px;
|
|
background: rgba(255,255,255,0.06);
|
|
border-radius: 3px;
|
|
overflow: hidden;
|
|
}
|
|
.storage-i { position: absolute; top: 0; left: 0; bottom: 0; }
|
|
.storage-l {
|
|
position: absolute; top: 0; bottom: 0;
|
|
left: calc((var(--installed-pct, 15.3)) * 1%);
|
|
}
|
|
.storage-compact .storage-bar { height: 4px; }
|
|
.storage-text {
|
|
display: flex; align-items: center;
|
|
gap: 10px;
|
|
font-size: 11px;
|
|
color: var(--t-3);
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
.storage-text > span { display: inline-flex; align-items: center; gap: 5px; }
|
|
.storage-sq {
|
|
width: 8px; height: 8px;
|
|
border-radius: 2px;
|
|
}
|
|
.storage-free { margin-left: auto; color: var(--t-2); }
|
|
|
|
/* ─── Grid wrapper / results bar ─── */
|
|
.grid-wrap {
|
|
flex: 1;
|
|
overflow: auto;
|
|
padding: 18px 24px 32px;
|
|
scrollbar-width: thin;
|
|
scrollbar-color: var(--bd-3) transparent;
|
|
}
|
|
.grid-wrap::-webkit-scrollbar { width: 10px; }
|
|
.grid-wrap::-webkit-scrollbar-thumb { background: var(--bd-3); border-radius: 5px; border: 2px solid transparent; background-clip: content-box; }
|
|
|
|
.results-bar {
|
|
display: flex; align-items: center; justify-content: space-between;
|
|
padding: 4px 4px 16px;
|
|
gap: 16px;
|
|
}
|
|
.results-count { color: var(--t-2); font-size: 12.5px; }
|
|
.results-count strong { color: var(--t-1); font-weight: 700; }
|
|
|
|
/* ─── Grid ─── */
|
|
.grid {
|
|
display: grid;
|
|
gap: var(--card-gap, 16px);
|
|
grid-template-columns: repeat(auto-fill, minmax(var(--card-min, 188px), 1fr));
|
|
}
|
|
.density-compact { --card-min: 148px; --card-gap: 12px; }
|
|
.density-normal { --card-min: 188px; --card-gap: 16px; }
|
|
.density-large { --card-min: 244px; --card-gap: 20px; }
|
|
|
|
/* ─── Card ─── */
|
|
.card {
|
|
position: relative;
|
|
display: flex;
|
|
flex-direction: column;
|
|
background: linear-gradient(180deg, var(--bg-2) 0%, var(--bg-1) 100%);
|
|
border: 1px solid var(--bd-1);
|
|
border-radius: var(--radius-md);
|
|
cursor: pointer;
|
|
overflow: hidden;
|
|
transition: transform .18s cubic-bezier(.4,1.2,.5,1), border-color .18s, box-shadow .18s;
|
|
outline: 0;
|
|
}
|
|
.card:hover, .card:focus-visible {
|
|
transform: translateY(-2px);
|
|
border-color: color-mix(in srgb, var(--accent) 45%, var(--bd-2));
|
|
box-shadow:
|
|
0 14px 30px -16px color-mix(in srgb, var(--accent) 50%, black),
|
|
0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent);
|
|
}
|
|
.card:focus-visible {
|
|
box-shadow:
|
|
0 14px 30px -16px color-mix(in srgb, var(--accent) 50%, black),
|
|
0 0 0 2px var(--accent);
|
|
}
|
|
|
|
/* ─── Cover ─── */
|
|
.card-cover-wrap {
|
|
position: relative;
|
|
width: 100%;
|
|
overflow: hidden;
|
|
background: var(--bg-3);
|
|
}
|
|
.card-cover-wrap[data-aspect="box"] { aspect-ratio: 2 / 3; }
|
|
.card-cover-wrap[data-aspect="square"] { aspect-ratio: 1 / 1; }
|
|
.card-cover-wrap[data-aspect="banner"] { aspect-ratio: 16 / 9; }
|
|
|
|
.cover {
|
|
position: absolute; inset: 0;
|
|
overflow: hidden;
|
|
transition: transform .35s cubic-bezier(.4,1.2,.5,1);
|
|
}
|
|
.card:hover .cover { transform: scale(1.03); }
|
|
.cover-base, .cover-blob, .cover-grain, .cover-vignette, .cover-mark { position: absolute; inset: 0; pointer-events: none; }
|
|
.cover-grain {
|
|
background-image:
|
|
repeating-linear-gradient(0deg, rgba(255,255,255,0.018) 0 1px, transparent 1px 3px),
|
|
repeating-linear-gradient(90deg, rgba(0,0,0,0.04) 0 1px, transparent 1px 3px);
|
|
mix-blend-mode: overlay;
|
|
opacity: 0.7;
|
|
}
|
|
.cover-vignette {
|
|
background: linear-gradient(180deg, transparent 30%, rgba(0,0,0,0.62) 100%);
|
|
}
|
|
.cover-mark { width: 100%; height: 100%; }
|
|
.cover-titlewrap {
|
|
position: absolute;
|
|
left: 0; right: 0; bottom: 0;
|
|
z-index: 2;
|
|
padding: 14px 14px 14px;
|
|
}
|
|
.cover-title {
|
|
font-family: var(--font-display);
|
|
font-weight: 400;
|
|
letter-spacing: 0.018em;
|
|
line-height: 1.02;
|
|
text-transform: uppercase;
|
|
color: white;
|
|
overflow-wrap: normal;
|
|
word-break: normal;
|
|
}
|
|
.cover-sub {
|
|
font-family: var(--font-ui);
|
|
font-size: 10px;
|
|
font-weight: 700;
|
|
letter-spacing: 0.18em;
|
|
text-transform: uppercase;
|
|
opacity: 0.85;
|
|
}
|
|
|
|
/* banner mode: title centered + smaller padding */
|
|
.card-cover-wrap[data-aspect="banner"] .cover-titlewrap {
|
|
padding: 14px 18px;
|
|
}
|
|
|
|
/* ─── State chip ─── */
|
|
.state-chip {
|
|
position: absolute;
|
|
top: 10px; right: 10px;
|
|
z-index: 3;
|
|
display: inline-flex; align-items: center; gap: 6px;
|
|
padding: 4px 9px;
|
|
border-radius: 999px;
|
|
background: rgba(8,12,16,0.78);
|
|
-webkit-backdrop-filter: blur(8px);
|
|
backdrop-filter: blur(8px);
|
|
border: 1px solid rgba(255,255,255,0.08);
|
|
font-size: 10.5px;
|
|
font-weight: 600;
|
|
color: var(--t-1);
|
|
letter-spacing: 0.01em;
|
|
}
|
|
.state-dot { width: 6px; height: 6px; border-radius: 999px; box-shadow: 0 0 8px currentColor; }
|
|
.state-chip[data-state="installed"] .state-dot { box-shadow: 0 0 8px var(--ok); }
|
|
.state-chip[data-state="local"] .state-dot { box-shadow: 0 0 8px var(--warn); }
|
|
|
|
/* Multiplayer badge */
|
|
.card-mp {
|
|
position: absolute;
|
|
top: 10px; left: 10px;
|
|
z-index: 3;
|
|
display: inline-flex; align-items: center; gap: 4px;
|
|
padding: 4px 8px;
|
|
border-radius: 999px;
|
|
background: rgba(8,12,16,0.65);
|
|
-webkit-backdrop-filter: blur(8px);
|
|
backdrop-filter: blur(8px);
|
|
border: 1px solid rgba(255,255,255,0.06);
|
|
font-size: 10.5px;
|
|
font-weight: 600;
|
|
color: var(--t-1);
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
|
|
/* ─── Card body ─── */
|
|
.card-body {
|
|
padding: 11px 12px 12px;
|
|
display: flex; flex-direction: column;
|
|
gap: 8px;
|
|
}
|
|
.card-title {
|
|
font-weight: 600;
|
|
font-size: 13.5px;
|
|
color: var(--t-1);
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
letter-spacing: -0.005em;
|
|
}
|
|
.card-meta {
|
|
display: flex; align-items: center; gap: 6px;
|
|
font-size: 11.5px;
|
|
color: var(--t-3);
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
.card-meta .card-dot { opacity: 0.5; }
|
|
|
|
.density-compact .card-body { padding: 9px 10px 10px; gap: 6px; }
|
|
.density-compact .card-title { font-size: 12.5px; }
|
|
.density-compact .card-meta { font-size: 11px; }
|
|
.density-large .card-body { padding: 14px 14px 14px; gap: 10px; }
|
|
.density-large .card-title { font-size: 15px; }
|
|
|
|
/* ─── Action buttons ─── */
|
|
.act-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 6px;
|
|
height: 32px;
|
|
padding: 0 14px;
|
|
border-radius: 7px;
|
|
border: 0;
|
|
font: inherit;
|
|
font-weight: 600;
|
|
font-size: 12.5px;
|
|
letter-spacing: 0.005em;
|
|
cursor: pointer;
|
|
transition: transform .12s, filter .12s, background .15s;
|
|
white-space: nowrap;
|
|
}
|
|
.act-btn:hover { filter: brightness(1.12); }
|
|
.act-btn:active { transform: scale(0.98); }
|
|
.act-full { width: 100%; }
|
|
.act-lg { height: 44px; padding: 0 22px; font-size: 14px; gap: 8px; }
|
|
.act-lg svg { width: 14px; height: 14px; }
|
|
|
|
.act-play {
|
|
color: white;
|
|
background: linear-gradient(180deg, #2bd07f 0%, #1aa460 100%);
|
|
box-shadow: 0 6px 16px -8px #1aa460, inset 0 1px 0 rgba(255,255,255,0.25);
|
|
}
|
|
.act-install {
|
|
color: white;
|
|
background: var(--accent);
|
|
box-shadow: 0 6px 16px -8px color-mix(in srgb, var(--accent) 80%, black), inset 0 1px 0 rgba(255,255,255,0.22);
|
|
}
|
|
.act-download {
|
|
color: var(--t-1);
|
|
background: rgba(255,255,255,0.08);
|
|
border: 1px solid var(--bd-2);
|
|
box-shadow: inset 0 1px 0 rgba(255,255,255,0.04);
|
|
}
|
|
.act-download:hover { background: rgba(255,255,255,0.12); border-color: var(--bd-3); }
|
|
|
|
/* ─── Download progress (in place of action button when state === 'downloading') ─── */
|
|
.dl {
|
|
position: relative;
|
|
overflow: hidden;
|
|
border-radius: 7px;
|
|
border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--bd-2));
|
|
background: rgba(255,255,255,0.04);
|
|
color: var(--t-1);
|
|
font: inherit;
|
|
font-variant-numeric: tabular-nums;
|
|
container-type: inline-size;
|
|
isolation: isolate;
|
|
box-shadow: inset 0 1px 0 rgba(255,255,255,0.04),
|
|
0 0 0 1px color-mix(in srgb, var(--accent) 16%, transparent);
|
|
}
|
|
.dl-full { width: 100%; }
|
|
.dl-fill {
|
|
position: absolute; inset: 0 auto 0 0;
|
|
width: 0%;
|
|
background:
|
|
linear-gradient(180deg,
|
|
color-mix(in srgb, var(--accent) 38%, transparent) 0%,
|
|
color-mix(in srgb, var(--accent) 26%, transparent) 100%);
|
|
border-right: 1px solid color-mix(in srgb, var(--accent) 75%, transparent);
|
|
box-shadow: 2px 0 8px color-mix(in srgb, var(--accent) 35%, transparent);
|
|
transition: width 480ms cubic-bezier(.4,0,.2,1);
|
|
z-index: 0;
|
|
}
|
|
/* shimmering scanline on top of the fill so it reads as 'live' */
|
|
.dl-fill::after {
|
|
content: '';
|
|
position: absolute; inset: 0;
|
|
background:
|
|
repeating-linear-gradient(115deg,
|
|
transparent 0 14px,
|
|
rgba(255,255,255,0.05) 14px 22px);
|
|
background-size: 200% 100%;
|
|
animation: dl-stripe 1.4s linear infinite;
|
|
mix-blend-mode: screen;
|
|
opacity: 0.85;
|
|
}
|
|
@keyframes dl-stripe {
|
|
from { background-position: 0% 0%; }
|
|
to { background-position: -36px 0%; }
|
|
}
|
|
|
|
/* live pulse dot */
|
|
.dl-pulse {
|
|
width: 7px; height: 7px; border-radius: 99px;
|
|
background: var(--accent);
|
|
box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 70%, transparent);
|
|
animation: dl-pulse 1.4s ease-out infinite;
|
|
flex: 0 0 auto;
|
|
}
|
|
@keyframes dl-pulse {
|
|
0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 70%, transparent); }
|
|
70% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent) 0%, transparent); }
|
|
100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 0%, transparent); }
|
|
}
|
|
|
|
/* ── md (card tile) ── */
|
|
.dl-md {
|
|
height: 32px;
|
|
padding: 0 10px;
|
|
}
|
|
.dl-md-row {
|
|
position: relative; z-index: 1;
|
|
display: flex; align-items: center; justify-content: space-between;
|
|
width: 100%; height: 100%;
|
|
gap: 8px;
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
letter-spacing: 0.005em;
|
|
}
|
|
.dl-md .dl-pct {
|
|
display: inline-flex; align-items: center;
|
|
color: var(--t-1);
|
|
}
|
|
.dl-md .dl-pulse { margin-right: 6px; }
|
|
.dl-md .dl-pct-sym { opacity: 0.55; font-weight: 600; margin-left: 1px; }
|
|
.dl-md .dl-speed {
|
|
color: var(--t-2);
|
|
font-size: 11px;
|
|
font-weight: 500;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
|
|
/* Container-query graceful degradation: when the tile is narrow,
|
|
drop the speed and centre the percentage so nothing truncates. */
|
|
@container (max-width: 132px) {
|
|
.dl-md .dl-speed { display: none; }
|
|
.dl-md-row { justify-content: center; gap: 6px; }
|
|
}
|
|
@container (max-width: 96px) {
|
|
.dl-md .dl-pulse { display: none; }
|
|
}
|
|
|
|
/* Density tuning — match the existing button heights */
|
|
.density-compact .dl-md { height: 30px; padding: 0 9px; }
|
|
.density-compact .dl-md-row { font-size: 11.5px; }
|
|
.density-compact .dl-md .dl-speed { font-size: 10.5px; }
|
|
.density-large .dl-md { height: 34px; padding: 0 12px; }
|
|
.density-large .dl-md-row { font-size: 13px; }
|
|
.density-large .dl-md .dl-speed { font-size: 11.5px; }
|
|
|
|
/* ── lg (detail overlay) ── */
|
|
.dl-lg {
|
|
height: 56px;
|
|
padding: 0;
|
|
border-radius: 9px;
|
|
flex: 1 1 auto;
|
|
min-width: 260px;
|
|
}
|
|
.dl-lg-grid {
|
|
position: relative; z-index: 1;
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 1fr) auto auto;
|
|
grid-template-rows: auto auto;
|
|
grid-template-areas:
|
|
"primary pct cancel"
|
|
"secondary pct cancel";
|
|
align-items: center;
|
|
height: 100%;
|
|
padding: 0 14px 0 16px;
|
|
column-gap: 14px;
|
|
row-gap: 2px;
|
|
}
|
|
.dl-lg-primary {
|
|
grid-area: primary;
|
|
display: flex; align-items: center; gap: 8px;
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
letter-spacing: 0.02em;
|
|
text-transform: uppercase;
|
|
color: color-mix(in srgb, var(--accent) 80%, white);
|
|
min-width: 0;
|
|
}
|
|
.dl-lg-primary .dl-label { white-space: nowrap; }
|
|
.dl-lg-secondary {
|
|
grid-area: secondary;
|
|
display: flex; align-items: center; gap: 7px;
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
color: var(--t-2);
|
|
min-width: 0;
|
|
overflow: hidden;
|
|
}
|
|
.dl-lg-secondary .dl-bytes {
|
|
color: var(--t-1);
|
|
font-weight: 600;
|
|
white-space: nowrap;
|
|
}
|
|
.dl-lg-secondary .dl-bytes .dl-of { color: var(--t-2); font-weight: 500; }
|
|
.dl-lg-secondary .dl-speed { color: var(--t-1); font-weight: 600; white-space: nowrap; }
|
|
.dl-lg-secondary .dl-peers {
|
|
display: inline-flex; align-items: center; gap: 4px;
|
|
color: var(--t-1); font-weight: 600; font-variant-numeric: tabular-nums;
|
|
white-space: nowrap;
|
|
}
|
|
.dl-lg-secondary .dl-peers svg { opacity: 0.7; }
|
|
.dl-lg-secondary .dl-eta { white-space: nowrap; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
.dl-sep { opacity: 0.45; }
|
|
|
|
/* Gracefully drop the ETA when the modal is narrow */
|
|
@container (max-width: 320px) {
|
|
.dl-lg-secondary .dl-eta,
|
|
.dl-lg-secondary .dl-sep-eta { display: none; }
|
|
}
|
|
/* Even narrower: drop peers too, keep size + speed */
|
|
@container (max-width: 240px) {
|
|
.dl-lg-secondary .dl-peers,
|
|
.dl-lg-secondary .dl-sep-peers { display: none; }
|
|
}
|
|
|
|
.dl-lg-pct {
|
|
grid-area: pct;
|
|
font-size: 20px;
|
|
font-weight: 700;
|
|
letter-spacing: -0.01em;
|
|
color: var(--t-1);
|
|
font-variant-numeric: tabular-nums;
|
|
line-height: 1;
|
|
}
|
|
.dl-lg-pct .dl-pct-sym {
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
opacity: 0.55;
|
|
margin-left: 1px;
|
|
}
|
|
.dl-cancel {
|
|
grid-area: cancel;
|
|
display: inline-flex; align-items: center; justify-content: center;
|
|
width: 28px; height: 28px;
|
|
border-radius: 6px;
|
|
border: 1px solid var(--bd-2);
|
|
background: rgba(255,255,255,0.04);
|
|
color: var(--t-2);
|
|
cursor: pointer;
|
|
transition: background .15s, border-color .15s, color .15s;
|
|
}
|
|
.dl-cancel:hover {
|
|
background: rgba(239,68,68,0.12);
|
|
border-color: rgba(239,68,68,0.40);
|
|
color: #fca5a5;
|
|
}
|
|
|
|
/* Ghost / secondary */
|
|
.ghost-btn {
|
|
display: inline-flex; align-items: center; gap: 7px;
|
|
height: 44px; padding: 0 18px;
|
|
background: rgba(255,255,255,0.04);
|
|
border: 1px solid var(--bd-2);
|
|
border-radius: 8px;
|
|
color: var(--t-1);
|
|
font: inherit; font-size: 13.5px; font-weight: 600;
|
|
cursor: pointer;
|
|
transition: background .15s, border-color .15s, color .15s;
|
|
}
|
|
.ghost-btn:hover { background: rgba(255,255,255,0.08); border-color: var(--bd-3); }
|
|
.ghost-danger { color: #f87171; }
|
|
.ghost-danger:hover { background: rgba(239,68,68,0.10); border-color: rgba(239,68,68,0.40); color: #fca5a5; }
|
|
|
|
/* ─── Modal ─── */
|
|
.modal-scrim {
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 100;
|
|
background: rgba(4,7,11,0.7);
|
|
-webkit-backdrop-filter: blur(8px);
|
|
backdrop-filter: blur(8px);
|
|
display: grid;
|
|
place-items: center;
|
|
padding: 32px;
|
|
animation: fadein .18s ease;
|
|
}
|
|
@keyframes fadein { from { opacity: 0 } to { opacity: 1 } }
|
|
.modal {
|
|
width: min(880px, 100%);
|
|
max-height: 100%;
|
|
background: linear-gradient(180deg, var(--bg-2) 0%, var(--bg-1) 100%);
|
|
border: 1px solid var(--bd-2);
|
|
border-radius: 14px;
|
|
overflow: hidden;
|
|
position: relative;
|
|
box-shadow: 0 30px 80px -10px rgba(0,0,0,0.7), 0 0 0 1px rgba(255,255,255,0.04);
|
|
display: flex; flex-direction: column;
|
|
animation: modalin .25s cubic-bezier(.3,1.3,.4,1);
|
|
}
|
|
@keyframes modalin { from { transform: scale(.96) translateY(8px); opacity: 0 } to { transform: scale(1) translateY(0); opacity: 1 } }
|
|
.modal-close {
|
|
position: absolute;
|
|
top: 14px; right: 14px;
|
|
z-index: 5;
|
|
width: 32px; height: 32px;
|
|
display: grid; place-items: center;
|
|
background: rgba(8,12,16,0.7);
|
|
border: 1px solid var(--bd-2);
|
|
border-radius: 8px;
|
|
color: var(--t-1);
|
|
cursor: pointer;
|
|
-webkit-backdrop-filter: blur(8px);
|
|
backdrop-filter: blur(8px);
|
|
transition: background .15s, border-color .15s;
|
|
}
|
|
.modal-close:hover { background: rgba(255,255,255,0.10); border-color: var(--bd-3); }
|
|
.modal-hero {
|
|
position: relative;
|
|
aspect-ratio: 16 / 7;
|
|
overflow: hidden;
|
|
}
|
|
.modal-hero .cover { transform: none !important; }
|
|
.modal-hero-fade {
|
|
position: absolute; inset: 0;
|
|
background: linear-gradient(180deg, transparent 40%, var(--bg-2) 100%);
|
|
pointer-events: none;
|
|
}
|
|
.modal-hero-text {
|
|
position: absolute;
|
|
left: 28px; right: 28px; bottom: 22px;
|
|
z-index: 2;
|
|
}
|
|
.modal-hero-text .modal-title {
|
|
font-family: var(--font-ui);
|
|
font-size: 32px;
|
|
font-weight: 700;
|
|
letter-spacing: -0.015em;
|
|
color: white;
|
|
margin: 6px 0 0;
|
|
text-shadow: 0 4px 24px rgba(0,0,0,0.6);
|
|
}
|
|
.modal-tags { display: flex; gap: 6px; flex-wrap: wrap; }
|
|
.modal-tag {
|
|
display: inline-block;
|
|
padding: 3px 8px;
|
|
background: rgba(8,12,16,0.6);
|
|
-webkit-backdrop-filter: blur(8px);
|
|
backdrop-filter: blur(8px);
|
|
border: 1px solid var(--bd-2);
|
|
border-radius: 4px;
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
letter-spacing: 0.04em;
|
|
text-transform: uppercase;
|
|
color: var(--t-1);
|
|
}
|
|
.modal-state {
|
|
position: absolute;
|
|
top: 18px;
|
|
left: 24px;
|
|
z-index: 3;
|
|
}
|
|
.modal-state .state-chip {
|
|
position: static;
|
|
font-size: 11.5px;
|
|
padding: 5px 11px;
|
|
}
|
|
|
|
/* Banner cover treatment inside modal: hide the cover's own title (we show our own h2) */
|
|
.modal-hero .cover-titlewrap { opacity: 0.14; }
|
|
|
|
.modal-body {
|
|
padding: 22px 28px 26px;
|
|
display: flex; flex-direction: column; gap: 18px;
|
|
}
|
|
.modal-meta {
|
|
display: grid;
|
|
grid-template-columns: repeat(4, 1fr);
|
|
gap: 12px;
|
|
}
|
|
.meta-cell {
|
|
padding: 10px 12px;
|
|
background: rgba(255,255,255,0.025);
|
|
border: 1px solid var(--bd-1);
|
|
border-radius: 8px;
|
|
}
|
|
.meta-label {
|
|
font-size: 10.5px;
|
|
font-weight: 700;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
color: var(--t-3);
|
|
}
|
|
.meta-value {
|
|
margin-top: 4px;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
color: var(--t-1);
|
|
display: flex; align-items: center; gap: 6px;
|
|
}
|
|
.meta-mono { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 13px; }
|
|
|
|
.modal-desc {
|
|
margin: 0;
|
|
font-size: 14px;
|
|
line-height: 1.55;
|
|
color: var(--t-2);
|
|
text-wrap: pretty;
|
|
max-width: 64ch;
|
|
}
|
|
.modal-actions {
|
|
display: flex; align-items: center; gap: 10px;
|
|
padding-top: 4px;
|
|
}
|
|
.modal-actions-spacer { flex: 1; }
|
|
|
|
/* ─── Settings dialog ─── */
|
|
.settings-modal {
|
|
width: min(640px, 100%);
|
|
background: var(--bg-2);
|
|
}
|
|
.settings-head {
|
|
position: relative;
|
|
padding: 22px 28px 18px;
|
|
border-bottom: 1px solid var(--bd-1);
|
|
}
|
|
.settings-head h2 {
|
|
margin: 0;
|
|
font-size: 20px;
|
|
font-weight: 700;
|
|
letter-spacing: -0.01em;
|
|
color: var(--t-1);
|
|
}
|
|
.settings-close {
|
|
position: absolute;
|
|
top: 18px;
|
|
right: 18px;
|
|
background: transparent;
|
|
}
|
|
.settings-close:hover { background: rgba(255,255,255,0.06); }
|
|
.settings-body {
|
|
padding: 22px 28px 26px;
|
|
display: flex; flex-direction: column;
|
|
gap: 26px;
|
|
max-height: 70vh;
|
|
overflow: auto;
|
|
}
|
|
.settings-section {
|
|
display: flex; flex-direction: column;
|
|
gap: 14px;
|
|
}
|
|
.settings-section-title {
|
|
font-size: 10.5px;
|
|
font-weight: 700;
|
|
letter-spacing: 0.12em;
|
|
text-transform: uppercase;
|
|
color: var(--t-3);
|
|
}
|
|
.settings-row {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 24px;
|
|
}
|
|
.settings-row-info { min-width: 0; flex: 1; }
|
|
.settings-row-label {
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
color: var(--t-1);
|
|
}
|
|
.settings-row-hint {
|
|
margin-top: 3px;
|
|
font-size: 12px;
|
|
color: var(--t-3);
|
|
}
|
|
.settings-row-control { flex-shrink: 0; }
|
|
.settings-foot {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
padding: 14px 22px 18px;
|
|
border-top: 1px solid var(--bd-1);
|
|
gap: 10px;
|
|
}
|
|
.settings-done {
|
|
height: 36px;
|
|
padding: 0 22px;
|
|
font-size: 13.5px;
|
|
}
|
|
.settings-done:hover {
|
|
filter: brightness(1.1);
|
|
border-color: transparent !important;
|
|
}
|
|
|
|
/* ─── Settings: color swatches ─── */
|
|
.swatch-row {
|
|
display: inline-flex;
|
|
gap: 8px;
|
|
}
|
|
.swatch {
|
|
position: relative;
|
|
width: 32px; height: 32px;
|
|
padding: 0;
|
|
background: transparent;
|
|
border: 0;
|
|
border-radius: 9px;
|
|
cursor: pointer;
|
|
}
|
|
.swatch-dot {
|
|
display: block;
|
|
width: 100%; height: 100%;
|
|
border-radius: 8px;
|
|
box-shadow: inset 0 0 0 1px rgba(255,255,255,0.08);
|
|
transition: transform .15s, box-shadow .15s;
|
|
}
|
|
.swatch:hover .swatch-dot { transform: scale(1.06); }
|
|
.swatch.is-active .swatch-dot {
|
|
box-shadow: 0 0 0 2px var(--bg-2), 0 0 0 4px currentColor;
|
|
}
|
|
.swatch-check {
|
|
position: absolute;
|
|
inset: 0;
|
|
display: grid;
|
|
place-items: center;
|
|
color: white;
|
|
filter: drop-shadow(0 1px 2px rgba(0,0,0,0.5));
|
|
pointer-events: none;
|
|
}
|
|
|
|
/* ─── Settings: segmented radio ─── */
|
|
.srad {
|
|
display: inline-flex;
|
|
background: var(--bg-3);
|
|
border: 1px solid var(--bd-1);
|
|
border-radius: 8px;
|
|
padding: 3px;
|
|
}
|
|
.srad-btn {
|
|
display: inline-flex; align-items: center;
|
|
height: 30px;
|
|
padding: 0 14px;
|
|
background: transparent;
|
|
border: 1px solid transparent;
|
|
border-radius: 6px;
|
|
color: var(--t-2);
|
|
font: inherit;
|
|
font-weight: 600;
|
|
font-size: 12.5px;
|
|
cursor: pointer;
|
|
transition: color .15s, background .15s;
|
|
white-space: nowrap;
|
|
}
|
|
.srad-btn:hover { color: var(--t-1); }
|
|
.srad-btn.is-active {
|
|
color: white;
|
|
box-shadow: 0 2px 8px -2px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.18);
|
|
}
|