chore: import upstream snapshot with attribution
CI / lint (push) Has been cancelled
CI / js-syntax (push) Successful in 10m24s
CI / deps-audit (push) Has been cancelled
CI / test (push) Failing after 24m55s
CI / sast-bandit (push) Failing after 11m13s
CI / trivy (push) Failing after 9m32s
Docker Publish / build-and-push (push) Failing after 34m3s
CI / lint (push) Has been cancelled
CI / js-syntax (push) Successful in 10m24s
CI / deps-audit (push) Has been cancelled
CI / test (push) Failing after 24m55s
CI / sast-bandit (push) Failing after 11m13s
CI / trivy (push) Failing after 9m32s
Docker Publish / build-and-push (push) Failing after 34m3s
This commit is contained in:
@@ -0,0 +1,443 @@
|
||||
/* ───────────── Top bar ───────────── */
|
||||
|
||||
.app:not(.is-import) .appbar {
|
||||
padding-top: 12px;
|
||||
padding-bottom: 14px;
|
||||
}
|
||||
|
||||
/* ─── Collapsed icon strip (double-click to toggle) ─── */
|
||||
|
||||
/* Expandable body wrapper — same grid-row trick as .widget-body */
|
||||
.appbar-body {
|
||||
display: grid;
|
||||
grid-template-rows: 1fr;
|
||||
overflow: hidden;
|
||||
opacity: 1;
|
||||
width: 100%;
|
||||
min-height: 0;
|
||||
transition: grid-template-rows 220ms ease, opacity 180ms ease;
|
||||
}
|
||||
.appbar-body-inner {
|
||||
min-height: 0;
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(220px, 300px) minmax(0, 1fr);
|
||||
align-items: stretch;
|
||||
gap: 22px;
|
||||
}
|
||||
|
||||
/* Strip wrapper — collapsed by default */
|
||||
.appbar-icon-strip {
|
||||
display: grid;
|
||||
grid-template-rows: 0fr;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
min-height: 0; /* prevent flex parent from reserving space when row is 0fr */
|
||||
transition: grid-template-rows 220ms ease, opacity 200ms ease 20ms;
|
||||
}
|
||||
.appbar-strip-inner {
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* Collapsed state */
|
||||
.app.appbar-collapsed .appbar-body {
|
||||
grid-template-rows: 0fr;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
height: 0; /* force flex child to zero — grid-template-rows alone isn't enough in a flex container */
|
||||
}
|
||||
.app.appbar-collapsed .appbar-icon-strip {
|
||||
grid-template-rows: 1fr;
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
align-items: center;
|
||||
}
|
||||
.app.appbar-collapsed .appbar {
|
||||
min-height: 52px;
|
||||
height: 52px;
|
||||
padding: 6px 14px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.app.appbar-collapsed .appbar-strip-inner {
|
||||
height: 40px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.strip-sq {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--glass-line);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
transition: background 120ms, border-color 120ms, opacity 120ms;
|
||||
}
|
||||
.strip-sq:hover { background: rgba(255,255,255,0.08) !important; }
|
||||
.strip-sq-process:hover { filter: brightness(1.1); }
|
||||
.strip-sq-brand {
|
||||
font-family: var(--font-mono);
|
||||
font-weight: 700;
|
||||
font-size: 12px;
|
||||
color: var(--ink);
|
||||
background: rgba(255,255,255,0.05);
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
.strip-sq-url {
|
||||
background: rgba(255,255,255,0.03);
|
||||
color: var(--ink-faint);
|
||||
margin-right: 3px;
|
||||
}
|
||||
.strip-sq-stems {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
.strip-sq-stem {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid rgba(255,255,255,0.1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
transition: opacity 120ms, background 120ms;
|
||||
}
|
||||
.strip-sq-stem:hover { opacity: 0.85 !important; }
|
||||
.strip-sq-stem.inactive { opacity: 0.2; }
|
||||
.strip-sq-process {
|
||||
background: linear-gradient(180deg, var(--gold-bright) 0%, var(--gold) 100%);
|
||||
color: #17130c;
|
||||
border-color: transparent;
|
||||
margin-left: 4px;
|
||||
}
|
||||
.strip-sq-process.loading {
|
||||
cursor: progress;
|
||||
filter: saturate(0.92);
|
||||
}
|
||||
.strip-sq-process.loading svg {
|
||||
display: none;
|
||||
}
|
||||
.strip-sq-process.loading::before {
|
||||
content: "";
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex: 0 0 16px;
|
||||
border-radius: 50%;
|
||||
background: conic-gradient(currentColor 0deg 270deg, transparent 270deg 360deg);
|
||||
-webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 0);
|
||||
mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 0);
|
||||
animation: spin 0.85s linear infinite;
|
||||
}
|
||||
|
||||
.brand-version {
|
||||
font-size: 11px;
|
||||
color: rgba(216,222,230,0.35);
|
||||
margin-top: 3px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
.brand-update-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
padding: 1px 5px;
|
||||
border-radius: 3px;
|
||||
background: rgba(100, 200, 120, 0.10);
|
||||
border: 1px solid rgba(100, 200, 120, 0.22);
|
||||
color: #6dcc82;
|
||||
font-size: 9px;
|
||||
text-decoration: none;
|
||||
}
|
||||
.brand-update-chip:hover {
|
||||
background: rgba(100, 200, 120, 0.2);
|
||||
color: #88dfa0;
|
||||
}
|
||||
|
||||
.appbar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20px 24px 22px;
|
||||
border: 1px solid var(--glass-line);
|
||||
border-radius: 16px;
|
||||
background:
|
||||
radial-gradient(circle at 82% -20%, rgba(216, 168, 74, 0.11), transparent 20rem),
|
||||
linear-gradient(180deg, rgba(27, 39, 48, 0.76), rgba(13, 22, 30, 0.84));
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.045),
|
||||
var(--shadow-panel);
|
||||
transition: padding 220ms ease;
|
||||
}
|
||||
|
||||
.brand-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: 5px;
|
||||
min-width: 0;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.brand-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.brand {
|
||||
margin: 0;
|
||||
font-family: var(--font-mono);
|
||||
font-weight: 700;
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
color: var(--ink);
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.brand-logo {
|
||||
display: block;
|
||||
width: 190px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.beta-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: 20px;
|
||||
padding: 0 5px;
|
||||
border: 1px solid rgba(216, 168, 74, 0.65);
|
||||
border-radius: 6px;
|
||||
background: var(--gold-soft);
|
||||
color: var(--gold-bright);
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.brand-sub {
|
||||
font-size: 13px;
|
||||
color: var(--ink-dim);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.post-urlbar,
|
||||
.post-process-btn {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.appbar-form {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.appbar-import-panel {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.appbar-import-panel .import-input-row {
|
||||
grid-template-columns: minmax(0, 1fr) clamp(140px, 14vw, 220px);
|
||||
gap: clamp(12px, 2vw, 28px);
|
||||
padding-bottom: 22px;
|
||||
}
|
||||
|
||||
.appbar-import-panel .url-wrap {
|
||||
min-height: 58px;
|
||||
padding: 0 20px;
|
||||
border: 1px solid rgba(148, 163, 184, 0.24);
|
||||
border-radius: 11px;
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.025), transparent),
|
||||
rgba(3, 9, 14, 0.72);
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.035),
|
||||
inset 0 -1px 0 rgba(0, 0, 0, 0.32),
|
||||
0 0 0 0 rgba(216, 168, 74, 0);
|
||||
transition:
|
||||
border-color var(--t-base) var(--easing),
|
||||
box-shadow var(--t-base) var(--easing),
|
||||
background-color var(--t-base) var(--easing);
|
||||
}
|
||||
|
||||
.appbar-import-panel .url-wrap:focus-within {
|
||||
border-color: rgba(216, 168, 74, 0.56);
|
||||
background-color: rgba(6, 13, 19, 0.86);
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.045),
|
||||
inset 0 -1px 0 rgba(0, 0, 0, 0.34),
|
||||
0 0 0 3px rgba(216, 168, 74, 0.08),
|
||||
0 14px 34px rgba(0, 0, 0, 0.22);
|
||||
}
|
||||
|
||||
.appbar-import-panel .url-prefix {
|
||||
color: #cbd2dc;
|
||||
opacity: 0.92;
|
||||
}
|
||||
|
||||
.appbar-import-panel input[type="url"] {
|
||||
font-size: clamp(15px, 0.95vw, 18px);
|
||||
height: 100%;
|
||||
color: #edf0f4;
|
||||
caret-color: var(--gold-bright);
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.appbar-import-panel .btn-primary {
|
||||
height: 58px;
|
||||
min-width: 0;
|
||||
width: 100%;
|
||||
border-radius: 11px;
|
||||
font-size: clamp(14px, 0.9vw, 16px);
|
||||
}
|
||||
|
||||
.appbar-import-panel .stem-choice-row {
|
||||
grid-template-columns: clamp(110px, 11vw, 156px) repeat(6, minmax(0, 1fr));
|
||||
gap: clamp(8px, 1vw, 14px);
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.appbar-import-panel .stem-choice-row > span {
|
||||
font-size: clamp(12px, 0.8vw, 14px);
|
||||
}
|
||||
|
||||
.appbar-import-panel .stem-choice {
|
||||
min-height: 48px;
|
||||
padding: 0 14px;
|
||||
border-radius: 10px;
|
||||
font-size: clamp(12px, 0.8vw, 14px);
|
||||
background:
|
||||
linear-gradient(180deg, color-mix(in srgb, currentColor 9%, transparent), transparent),
|
||||
rgba(8, 15, 22, 0.42);
|
||||
}
|
||||
|
||||
.url-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.url-prefix {
|
||||
flex-shrink: 0;
|
||||
color: #d7dbe2;
|
||||
}
|
||||
|
||||
.appbar-form input[type="url"],
|
||||
.appbar-import-panel input[type="url"],
|
||||
.import-card input[type="url"] {
|
||||
flex: 1;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
color: var(--ink);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 19px;
|
||||
padding: 0;
|
||||
min-width: 0;
|
||||
appearance: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.appbar-form input[type="url"]::placeholder,
|
||||
.appbar-import-panel input[type="url"]::placeholder,
|
||||
.import-card input[type="url"]::placeholder {
|
||||
color: #9da3ad;
|
||||
opacity: 0.78;
|
||||
}
|
||||
|
||||
.appbar-import-panel input[type="url"]::selection {
|
||||
background: rgba(216, 168, 74, 0.28);
|
||||
color: #fff6de;
|
||||
}
|
||||
|
||||
.appbar-import-panel input[type="url"] {
|
||||
font-size: clamp(15px, 0.95vw, 18px);
|
||||
color: #edf0f4;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
height: 56px;
|
||||
min-width: 150px;
|
||||
background: linear-gradient(180deg, var(--gold-bright) 0%, var(--gold) 100%);
|
||||
color: #17130c;
|
||||
border: 0;
|
||||
border-radius: var(--radius);
|
||||
padding: 0 24px;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.38),
|
||||
0 16px 36px rgba(216, 168, 74, 0.18);
|
||||
transition:
|
||||
filter var(--t-base) var(--easing),
|
||||
transform var(--t-fast) var(--easing);
|
||||
}
|
||||
|
||||
.btn-primary:hover:not(:disabled) {
|
||||
filter: brightness(1.08);
|
||||
}
|
||||
|
||||
.btn-primary:active:not(:disabled) {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.btn-primary:disabled {
|
||||
opacity: 0.82;
|
||||
cursor: progress;
|
||||
}
|
||||
|
||||
.btn-primary.loading {
|
||||
filter: saturate(0.92);
|
||||
}
|
||||
|
||||
.btn-primary.loading .icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.btn-primary.loading::before {
|
||||
content: "";
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
flex: 0 0 18px;
|
||||
border-radius: 50%;
|
||||
background: conic-gradient(currentColor 0deg 270deg, transparent 270deg 360deg);
|
||||
-webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 0);
|
||||
mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 0);
|
||||
animation: spin 0.85s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.btn-primary.loading::before {
|
||||
animation-duration: 1.8s;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background:
|
||||
radial-gradient(circle at 50% 0%, rgba(216, 168, 74, 0.1), transparent 34rem),
|
||||
radial-gradient(circle at 0% 45%, rgba(216, 168, 74, 0.055), transparent 28rem),
|
||||
radial-gradient(circle at 100% 45%, rgba(216, 168, 74, 0.055), transparent 28rem),
|
||||
linear-gradient(180deg, #081016 0%, #050a0f 100%);
|
||||
color: var(--ink);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
min-height: 100vh;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
:focus {
|
||||
outline: 0;
|
||||
}
|
||||
:focus-visible {
|
||||
outline: 2px solid var(--focus-ring);
|
||||
outline-offset: 2px;
|
||||
border-radius: var(--radius-xs);
|
||||
}
|
||||
|
||||
.surface-panel {
|
||||
border: 1px solid var(--glass-line);
|
||||
background:
|
||||
linear-gradient(180deg, rgba(28, 39, 48, 0.82), rgba(15, 23, 31, 0.86));
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.045),
|
||||
var(--shadow-panel);
|
||||
}
|
||||
|
||||
.app {
|
||||
max-width: 1640px;
|
||||
margin: 0 auto;
|
||||
min-height: 100vh;
|
||||
padding: 24px 28px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.app:not(.is-import) {
|
||||
max-width: none;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
min-height: 0;
|
||||
padding: 16px 29px 0;
|
||||
gap: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.app.is-import .now-playing,
|
||||
.app.is-import #lanes {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.app:not(.is-import) .import-page,
|
||||
.app:not(.is-import) .site-footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.site-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
margin-top: auto;
|
||||
padding: 18px 14px 22px;
|
||||
color: #8d929a;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.site-footer > span {
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.site-footer nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 26px;
|
||||
}
|
||||
|
||||
.site-footer a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.site-footer a:hover {
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.help-btn {
|
||||
height: 42px;
|
||||
padding: 0 16px;
|
||||
border: 1px solid rgba(148, 163, 184, 0.16);
|
||||
border-radius: var(--radius);
|
||||
background: rgba(18, 26, 34, 0.75);
|
||||
color: var(--ink);
|
||||
font: inherit;
|
||||
}
|
||||
@@ -0,0 +1,493 @@
|
||||
/* ──────────────────────────────────────────────
|
||||
catalog.css — Left catalog / history panel
|
||||
────────────────────────────────────────────── */
|
||||
|
||||
/* ─── Panel shell ─── */
|
||||
.catalog {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: linear-gradient(180deg, rgba(28,39,48,0.82), rgba(15,23,31,0.86));
|
||||
border: 1px solid var(--glass-line);
|
||||
border-radius: 12px;
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.045), var(--shadow-panel);
|
||||
padding: 12px 10px;
|
||||
gap: 10px;
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
position: relative;
|
||||
top: 0;
|
||||
overflow: hidden;
|
||||
transition: padding 220ms ease;
|
||||
}
|
||||
.app.cat-collapsed .catalog { padding: 12px 8px; }
|
||||
|
||||
/* ─── Header (click to collapse) ─── */
|
||||
.catalog-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 4px 6px 10px;
|
||||
border-bottom: 1px solid rgba(157,170,182,0.1);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
border-radius: 6px;
|
||||
transition: background 120ms;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.catalog-head:hover { background: rgba(31,43,52,0.55); }
|
||||
|
||||
.catalog-head h3 {
|
||||
margin: 0;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
color: var(--ink);
|
||||
white-space: nowrap;
|
||||
}
|
||||
.catalog-head .cat-count {
|
||||
color: var(--ink-faint);
|
||||
font-size: 11px;
|
||||
flex: 1;
|
||||
padding-left: 8px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.cat-chevron {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
color: var(--ink-faint);
|
||||
transition: transform 220ms ease;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Hide text content when collapsed */
|
||||
.app.cat-collapsed .catalog-head h3,
|
||||
.app.cat-collapsed .catalog-head .cat-count { display: none; }
|
||||
.app.cat-collapsed .catalog-head { justify-content: center; padding: 10px 0; }
|
||||
.app.cat-collapsed .cat-chevron { transform: rotate(180deg); }
|
||||
|
||||
/* ─── Search ─── */
|
||||
.catalog-search {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 7px 10px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
background: rgba(21,31,39,0.6);
|
||||
color: var(--ink-faint);
|
||||
font-size: 12px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.catalog-search svg { flex-shrink: 0; }
|
||||
.catalog-search input {
|
||||
min-width: 0;
|
||||
width: 100%;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: var(--ink);
|
||||
font: inherit;
|
||||
font-size: 12px;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
}
|
||||
.catalog-search input::placeholder {
|
||||
color: var(--ink-faint);
|
||||
}
|
||||
|
||||
/* ─── New folder button ─── */
|
||||
.new-folder-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 7px 10px;
|
||||
border: 1px dashed var(--line);
|
||||
border-radius: 8px;
|
||||
background: transparent;
|
||||
color: var(--ink-dim);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
transition: all 120ms;
|
||||
width: 100%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.new-folder-btn:hover {
|
||||
border-color: var(--gold-line);
|
||||
color: var(--gold);
|
||||
}
|
||||
.new-folder-btn svg { width: 13px; height: 13px; flex-shrink: 0; }
|
||||
|
||||
/* ─── Catalog list ─── */
|
||||
.catalog-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
overflow-y: auto;
|
||||
flex: 1;
|
||||
padding-right: 2px;
|
||||
}
|
||||
|
||||
/* ─── Folder ─── */
|
||||
.folder { display: flex; flex-direction: column; }
|
||||
.folder-head {
|
||||
--folder-color: var(--gold);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
padding: 6px 8px;
|
||||
border-radius: 7px;
|
||||
cursor: pointer;
|
||||
color: var(--ink-dim);
|
||||
transition: background 120ms, color 120ms;
|
||||
user-select: none;
|
||||
}
|
||||
.folder-head:hover { background: rgba(31,43,52,0.55); color: var(--ink); }
|
||||
.folder.drop-target .folder-head {
|
||||
background: rgba(216,168,74,0.10);
|
||||
box-shadow: inset 0 0 0 1px var(--gold-line);
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.folder-head .f-chevron {
|
||||
width: 11px; height: 11px;
|
||||
transition: transform 180ms ease;
|
||||
flex-shrink: 0;
|
||||
color: var(--ink-faint);
|
||||
}
|
||||
.folder.collapsed .folder-head .f-chevron { transform: rotate(-90deg); }
|
||||
|
||||
.folder-head .f-icon {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
flex-shrink: 0;
|
||||
color: var(--folder-color);
|
||||
}
|
||||
|
||||
.folder-head .f-name {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: inherit;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 0;
|
||||
font-family: inherit;
|
||||
outline: none;
|
||||
cursor: inherit;
|
||||
}
|
||||
.folder-head .f-name[contenteditable="true"] {
|
||||
background: rgba(28,34,43,0.8);
|
||||
padding: 1px 4px;
|
||||
border-radius: 3px;
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.folder-head .f-count { font-size: 10.5px; color: var(--ink-faint); }
|
||||
|
||||
.folder-color-dot {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
border: 1px solid rgba(255,255,255,0.22);
|
||||
border-radius: 999px;
|
||||
background: var(--folder-color);
|
||||
box-shadow: inset 0 0 0 1px rgba(0,0,0,0.22);
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
}
|
||||
.folder-color-dot:hover,
|
||||
.folder-color-dot:focus-visible {
|
||||
border-color: rgba(255,255,255,0.82);
|
||||
outline: none;
|
||||
}
|
||||
.folder-color-dot.active {
|
||||
box-shadow: 0 0 0 2px rgba(255,255,255,0.18), inset 0 0 0 1px rgba(0,0,0,0.24);
|
||||
border-color: rgba(255,255,255,0.86);
|
||||
}
|
||||
|
||||
.folder-head .f-del {
|
||||
width: 18px; height: 18px;
|
||||
border: none; background: transparent;
|
||||
color: var(--ink-faint);
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
border-radius: 4px;
|
||||
padding: 0;
|
||||
}
|
||||
.folder-head:hover .f-del { opacity: 1; }
|
||||
.folder-head .f-del:hover { background: rgba(21,31,39,0.8); color: var(--danger); }
|
||||
|
||||
.folder-editor-backdrop {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 80;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
background: rgba(3, 8, 13, 0.42);
|
||||
backdrop-filter: blur(2px);
|
||||
}
|
||||
|
||||
.folder-editor {
|
||||
width: min(300px, calc(100vw - 32px));
|
||||
border: 1px solid var(--glass-line);
|
||||
border-radius: 10px;
|
||||
background: linear-gradient(180deg, rgba(28,39,48,0.98), rgba(13,21,29,0.98));
|
||||
box-shadow: var(--shadow-panel);
|
||||
padding: 12px;
|
||||
color: var(--ink);
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
.folder-editor-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.folder-editor-close {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 6px;
|
||||
background: transparent;
|
||||
color: var(--ink-faint);
|
||||
cursor: pointer;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding: 0;
|
||||
}
|
||||
.folder-editor-close:hover {
|
||||
background: rgba(21,31,39,0.8);
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.folder-editor-field {
|
||||
display: grid;
|
||||
gap: 7px;
|
||||
margin-bottom: 12px;
|
||||
color: var(--ink-faint);
|
||||
font-size: 10.5px;
|
||||
}
|
||||
|
||||
.folder-editor-name {
|
||||
width: 100%;
|
||||
min-height: 34px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 7px;
|
||||
background: rgba(10, 17, 24, 0.78);
|
||||
color: var(--ink);
|
||||
font: inherit;
|
||||
font-size: 12px;
|
||||
padding: 0 10px;
|
||||
outline: none;
|
||||
}
|
||||
.folder-editor-name:focus {
|
||||
border-color: var(--gold-line);
|
||||
box-shadow: 0 0 0 2px rgba(216,168,74,0.12);
|
||||
}
|
||||
|
||||
.folder-editor-colors {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 9px;
|
||||
}
|
||||
|
||||
.folder-editor-colors .folder-color-dot {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
.folder-editor-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
.folder-editor-actions button {
|
||||
min-height: 30px;
|
||||
border-radius: 7px;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 11px;
|
||||
cursor: pointer;
|
||||
padding: 0 11px;
|
||||
}
|
||||
.folder-editor-cancel {
|
||||
border: 1px solid var(--line);
|
||||
background: rgba(21,31,39,0.52);
|
||||
color: var(--ink-dim);
|
||||
}
|
||||
.folder-editor-save {
|
||||
border: 1px solid var(--gold-line);
|
||||
background: rgba(216,168,74,0.16);
|
||||
color: var(--gold);
|
||||
}
|
||||
|
||||
.folder-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3px;
|
||||
padding: 3px 0 3px 14px;
|
||||
margin-left: 7px;
|
||||
border-left: 1px solid rgba(157,170,182,0.1);
|
||||
}
|
||||
.folder.collapsed .folder-body { display: none; }
|
||||
.folder-empty {
|
||||
color: var(--ink-faint);
|
||||
font-size: 11px;
|
||||
padding: 5px 8px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* ─── Track item ─── */
|
||||
.cat-item {
|
||||
display: flex;
|
||||
gap: 9px;
|
||||
align-items: center;
|
||||
padding: 7px 8px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 9px;
|
||||
cursor: pointer;
|
||||
transition: background 120ms, border-color 120ms;
|
||||
}
|
||||
.cat-item:hover { background: rgba(31,43,52,0.55); border-color: var(--line); }
|
||||
.cat-item.active { background: rgba(31,43,52,0.55); border-color: var(--gold-line); }
|
||||
.cat-item.dragging { opacity: 0.4; }
|
||||
.cat-item[draggable="true"] { cursor: grab; }
|
||||
|
||||
.cat-thumb {
|
||||
width: 44px; height: 44px;
|
||||
border-radius: 7px;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--line);
|
||||
background: rgba(21,31,39,0.8);
|
||||
}
|
||||
.cat-thumb svg,
|
||||
.cat-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||||
|
||||
.cat-meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
|
||||
.cat-title {
|
||||
color: var(--ink);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.cat-sub {
|
||||
color: var(--ink-faint);
|
||||
font-size: 10.5px;
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
.cat-sub .dot { opacity: 0.4; }
|
||||
|
||||
.cat-status {
|
||||
width: 7px; height: 7px;
|
||||
border-radius: 50%;
|
||||
background: #5fbc56;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.cat-status.processing {
|
||||
background: var(--gold);
|
||||
animation: cat-pulse 1.4s infinite;
|
||||
}
|
||||
@keyframes cat-pulse { 0%,100%{opacity:1;} 50%{opacity:0.3;} }
|
||||
|
||||
.cat-del {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 0;
|
||||
border-radius: 5px;
|
||||
background: transparent;
|
||||
color: var(--ink-faint);
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
flex-shrink: 0;
|
||||
transition: opacity 120ms, background 120ms, color 120ms;
|
||||
}
|
||||
|
||||
.cat-item:hover .cat-del,
|
||||
.cat-del:focus-visible {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.cat-del:hover {
|
||||
background: rgba(21,31,39,0.8);
|
||||
color: var(--danger);
|
||||
}
|
||||
|
||||
/* ─── Catalog footer ─── */
|
||||
.catalog-foot {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
padding: 8px 6px 0;
|
||||
border-top: 1px solid rgba(157,170,182,0.08);
|
||||
color: var(--ink-faint);
|
||||
font-size: 11px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.catalog-foot svg { flex-shrink: 0; }
|
||||
|
||||
/* ─── Collapsed strip: just album thumbs ─── */
|
||||
.cat-collapsed-strip {
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
padding-top: 4px;
|
||||
overflow-y: auto;
|
||||
flex: 1;
|
||||
}
|
||||
.app.cat-collapsed .cat-collapsed-strip { display: flex; }
|
||||
.app.cat-collapsed .catalog-search,
|
||||
.app.cat-collapsed .new-folder-btn,
|
||||
.app.cat-collapsed .catalog-list,
|
||||
.app.cat-collapsed .catalog-foot { display: none; }
|
||||
|
||||
.strip-thumb {
|
||||
width: 40px; height: 40px;
|
||||
border-radius: 7px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--line);
|
||||
cursor: pointer;
|
||||
transition: border-color 120ms, transform 120ms;
|
||||
flex-shrink: 0;
|
||||
background: rgba(21,31,39,0.8);
|
||||
color: var(--ink-dim);
|
||||
}
|
||||
.strip-thumb:hover { transform: scale(1.06); }
|
||||
.strip-thumb.active {
|
||||
border-color: var(--gold-line);
|
||||
box-shadow: 0 0 0 2px rgba(216,168,74,0.18);
|
||||
}
|
||||
.strip-thumb.folder-thumb {
|
||||
color: var(--folder-color, var(--gold));
|
||||
}
|
||||
.strip-thumb.trash-thumb {
|
||||
color: var(--ink-faint);
|
||||
}
|
||||
.strip-thumb svg,
|
||||
.strip-thumb img { width: 100%; height: 100%; display: block; object-fit: cover; }
|
||||
.strip-thumb.folder-thumb svg,
|
||||
.strip-thumb.trash-thumb svg {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
margin: 8px auto;
|
||||
}
|
||||
+2424
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,124 @@
|
||||
/* ───────────── Job progress ───────────── */
|
||||
|
||||
.job {
|
||||
display: none !important;
|
||||
background: var(--panel);
|
||||
border: var(--border-w) solid var(--line);
|
||||
border-radius: var(--radius);
|
||||
padding: 14px 16px;
|
||||
}
|
||||
.job-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#job-title {
|
||||
font-size: 14px;
|
||||
flex: 1;
|
||||
word-break: break-word;
|
||||
}
|
||||
#job-stage {
|
||||
font-size: 13px;
|
||||
color: var(--ink-dim);
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
progress {
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
appearance: none;
|
||||
background: var(--line);
|
||||
border: 0;
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
}
|
||||
progress::-webkit-progress-bar {
|
||||
background: var(--line);
|
||||
}
|
||||
progress::-webkit-progress-value {
|
||||
background: var(--ink);
|
||||
transition: width var(--t-base) var(--easing);
|
||||
}
|
||||
progress::-moz-progress-bar {
|
||||
background: var(--ink);
|
||||
}
|
||||
|
||||
/* Compact technical detail line under the progress bar -- shows the
|
||||
truthful backend `stage` value while #job-stage rotates phrases. */
|
||||
.job-detail {
|
||||
margin-top: 6px;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 11px;
|
||||
color: var(--ink-dim);
|
||||
opacity: 0.65;
|
||||
letter-spacing: 0.02em;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
flex-shrink: 0;
|
||||
background: transparent;
|
||||
color: var(--ink-dim);
|
||||
border: var(--border-w) solid var(--line);
|
||||
border-radius: var(--radius-xs);
|
||||
padding: 4px 10px;
|
||||
font: inherit;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 11px;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
background-color var(--t-base) var(--easing),
|
||||
color var(--t-base) var(--easing),
|
||||
border-color var(--t-base) var(--easing);
|
||||
}
|
||||
.cancel-btn:hover:not(:disabled) {
|
||||
background: var(--danger);
|
||||
color: var(--bg);
|
||||
border-color: var(--danger);
|
||||
}
|
||||
.cancel-btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* ───────────── Error ───────────── */
|
||||
|
||||
.error {
|
||||
background: rgba(214, 90, 74, 0.1);
|
||||
border: var(--border-w) solid rgba(214, 90, 74, 0.5);
|
||||
color: var(--danger);
|
||||
border-radius: var(--radius);
|
||||
padding: 12px 16px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
}
|
||||
.error-msg {
|
||||
flex: 1;
|
||||
word-break: break-word;
|
||||
font-size: 13px;
|
||||
}
|
||||
.retry-btn {
|
||||
flex-shrink: 0;
|
||||
background: transparent;
|
||||
color: var(--danger);
|
||||
border: var(--border-w) solid var(--danger);
|
||||
border-radius: var(--radius-xs);
|
||||
padding: 5px 12px;
|
||||
font: inherit;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
background-color var(--t-base) var(--easing),
|
||||
color var(--t-base) var(--easing);
|
||||
}
|
||||
.retry-btn:hover {
|
||||
background: var(--danger);
|
||||
color: var(--bg);
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/* ───────────── Master fader + VU ─────────────
|
||||
* Console-style: tick-marked vertical fader on the left, twin segmented
|
||||
* LED VU meters on the right, both inside a recessed dark panel.
|
||||
* Custom rendering throughout — `appearance: none` so the browser
|
||||
* doesn't fall back to its blue-track default vertical slider, which
|
||||
* ignores ::-webkit-slider-thumb overrides and offsets the thumb. */
|
||||
|
||||
.np-master {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: 10px;
|
||||
height: 140px;
|
||||
padding: 8px 10px;
|
||||
background: linear-gradient(180deg, #141414, #0d0d0d);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 6px;
|
||||
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
/* Fader column with tick marks down both sides. */
|
||||
.master-fader-track {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 44px;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
justify-content: center;
|
||||
}
|
||||
.master-fader-track::before,
|
||||
.master-fader-track::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
bottom: 4px;
|
||||
width: 5px;
|
||||
background-image: repeating-linear-gradient(
|
||||
to bottom,
|
||||
var(--line-strong) 0,
|
||||
var(--line-strong) 1px,
|
||||
transparent 1px,
|
||||
transparent 8px
|
||||
);
|
||||
pointer-events: none;
|
||||
}
|
||||
.master-fader-track::before { left: 4px; }
|
||||
.master-fader-track::after { right: 4px; }
|
||||
|
||||
.master-fader {
|
||||
/* No `appearance: slider-vertical` — that's a legacy webkit shortcut
|
||||
that forces a blue-track default vertical slider AND ignores
|
||||
::-webkit-slider-thumb overrides (which is why the thumb floats
|
||||
left of center). `writing-mode: vertical-lr` rotates the
|
||||
horizontal range input, `direction: rtl` puts max at the top. */
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
-moz-appearance: none;
|
||||
writing-mode: vertical-lr;
|
||||
direction: rtl;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.master-fader::-webkit-slider-runnable-track {
|
||||
width: 4px;
|
||||
height: 100%;
|
||||
background: #050505;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 2px;
|
||||
}
|
||||
.master-fader::-moz-range-track {
|
||||
width: 4px;
|
||||
height: 100%;
|
||||
background: #050505;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 2px;
|
||||
}
|
||||
.master-fader::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
/* In writing-mode: vertical-lr, `width` is the long (horizontal) axis
|
||||
and `height` is the thin (vertical) axis. Pill-shaped horizontal
|
||||
handle. margin-left: -12px centers it on the 4px track. */
|
||||
width: 28px;
|
||||
height: 14px;
|
||||
margin-left: -12px;
|
||||
background: linear-gradient(180deg, #6a6a6a 0%, #2a2a2a 55%, #161616 100%);
|
||||
border: 1px solid #050505;
|
||||
border-radius: 3px;
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.18),
|
||||
inset 0 -1px 0 rgba(0, 0, 0, 0.7),
|
||||
0 1px 2px rgba(0, 0, 0, 0.7);
|
||||
cursor: pointer;
|
||||
}
|
||||
.master-fader::-moz-range-thumb {
|
||||
width: 28px;
|
||||
height: 14px;
|
||||
background: linear-gradient(180deg, #6a6a6a 0%, #2a2a2a 55%, #161616 100%);
|
||||
border: 1px solid #050505;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -0,0 +1,418 @@
|
||||
/* ───────────── Preview mixer ───────────── */
|
||||
|
||||
.mixer-column {
|
||||
min-width: 0;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, minmax(68px, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.lane-header {
|
||||
min-height: 190px;
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr;
|
||||
justify-items: center;
|
||||
position: relative;
|
||||
transition: opacity var(--t-base) var(--easing);
|
||||
color: var(--stem-color, #d8dde4);
|
||||
}
|
||||
|
||||
.lane-header[data-stem="vocals"] { --stem-color: #e54249; }
|
||||
.lane-header[data-stem="drums"] { --stem-color: #f06a14; }
|
||||
.lane-header[data-stem="bass"] { --stem-color: #eab414; }
|
||||
.lane-header[data-stem="guitar"] { --stem-color: #5bbf50; }
|
||||
.lane-header[data-stem="piano"] { --stem-color: #7f45d8; }
|
||||
.lane-header[data-stem="other"] { --stem-color: #3e8dcf; }
|
||||
.lane-header[data-stem="original"] { --stem-color: #a8b0bd; }
|
||||
|
||||
.lane-header + .lane-header {
|
||||
border-left: 1px solid var(--glass-line);
|
||||
}
|
||||
|
||||
.lane-header.muted {
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
.lane-stripe {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.lane-content {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
.lane-name-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.lane-icon {
|
||||
width: 29px;
|
||||
height: 29px;
|
||||
flex: 0 0 auto;
|
||||
color: var(--stem-color);
|
||||
filter: drop-shadow(0 0 10px color-mix(in srgb, currentColor 34%, transparent));
|
||||
}
|
||||
|
||||
.lane-icon-toggle {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding: 0;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 8px;
|
||||
background: transparent;
|
||||
color: var(--stem-color);
|
||||
cursor: pointer;
|
||||
opacity: 0.38;
|
||||
transition:
|
||||
opacity var(--t-base) var(--easing),
|
||||
border-color var(--t-base) var(--easing),
|
||||
background-color var(--t-base) var(--easing),
|
||||
transform var(--t-fast) var(--easing);
|
||||
}
|
||||
|
||||
.lane-icon-toggle.active {
|
||||
opacity: 1;
|
||||
border-color: color-mix(in srgb, currentColor 24%, transparent);
|
||||
background: color-mix(in srgb, currentColor 8%, transparent);
|
||||
box-shadow: inset 0 0 18px color-mix(in srgb, currentColor 8%, transparent);
|
||||
}
|
||||
|
||||
.lane-icon-toggle:hover:not(:disabled) {
|
||||
opacity: 1;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.lane-icon-toggle:focus-visible {
|
||||
outline: 2px solid var(--gold);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.lane-icon-toggle:disabled {
|
||||
cursor: default;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
.lane-name {
|
||||
color: #d7dce3 !important;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.lane-controls {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 106px;
|
||||
align-items: end;
|
||||
justify-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.lane-mini-wave {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.lane-dl {
|
||||
display: none;
|
||||
color: #d8dde4;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.lane-knob {
|
||||
grid-column: 1 / -1;
|
||||
grid-row: 1;
|
||||
width: 48px;
|
||||
height: 104px;
|
||||
border-radius: 0;
|
||||
border: 0;
|
||||
background:
|
||||
repeating-linear-gradient(to bottom, rgba(148, 163, 184, 0.22) 0 1px, transparent 1px 12px),
|
||||
linear-gradient(90deg, transparent 0 44%, rgba(148, 163, 184, 0.2) 44% 56%, transparent 56% 100%);
|
||||
position: relative;
|
||||
cursor: ns-resize;
|
||||
/* --lane-pos: 0..1 = bottom..top. Default 0.5 = unity gain (vol=1
|
||||
of LANE_VOLUME_MAX=2). JS rewrites this when volume changes. */
|
||||
--lane-pos: 0.5;
|
||||
}
|
||||
|
||||
/* Fader thumb. Travels vertically along the track based on --lane-pos.
|
||||
The travel envelope is 100% - 18px (the thumb's own height) so the
|
||||
thumb never overshoots the track edges. The transition is only for
|
||||
programmatic moves (Reset, dblclick, wheel) -- during an active
|
||||
drag we kill the transition (.lane-knob.dragging rule below) so the
|
||||
thumb tracks the cursor 1:1 instead of chasing it through an
|
||||
easing curve, which reads as a rigid/laggy fader. */
|
||||
.lane-knob::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: calc((1 - var(--lane-pos)) * (100% - 14px));
|
||||
width: 30px;
|
||||
height: 14px;
|
||||
transform: translateX(-50%);
|
||||
border-radius: 3px;
|
||||
border: 1px solid #050505;
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.2), transparent 42%),
|
||||
linear-gradient(180deg, #6a6a6a 0%, #2a2a2a 55%, #161616 100%);
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.18),
|
||||
inset 0 -1px 0 rgba(0, 0, 0, 0.7),
|
||||
0 0 0 1px color-mix(in srgb, currentColor 34%, transparent),
|
||||
0 1px 2px rgba(0, 0, 0, 0.72);
|
||||
transition: top 120ms var(--easing);
|
||||
will-change: top;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.lane-knob.dragging::before {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
/* Slight grip cue while actively dragging -- thumb gets a tighter
|
||||
shadow ring so it feels "picked up". */
|
||||
.lane-knob.dragging {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.lane-knob-indicator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.lane-knob.disabled {
|
||||
opacity: 0.45;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.ms-btn {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border: 0;
|
||||
border-radius: 6px;
|
||||
background: rgba(255, 255, 255, 0.055);
|
||||
color: #d8dde4;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition:
|
||||
background-color var(--t-base) var(--easing),
|
||||
transform var(--t-fast) var(--easing);
|
||||
}
|
||||
|
||||
.ms-btn:hover {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.ms-btn:active {
|
||||
transform: scale(0.92);
|
||||
}
|
||||
|
||||
.ms-btn.mute.active {
|
||||
background: var(--danger);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.ms-btn.solo.active {
|
||||
background: var(--gold);
|
||||
color: #17130c;
|
||||
}
|
||||
|
||||
.ms-btn:disabled {
|
||||
opacity: 0.38;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.lane-controls .ms-btn.mute {
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
}
|
||||
|
||||
.lane-controls .ms-btn.solo {
|
||||
grid-column: 2;
|
||||
grid-row: 2;
|
||||
}
|
||||
|
||||
.lane-vu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.app:not(.is-import) .preview-mixer-body {
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
gap: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.app:not(.is-import) .mixer-column {
|
||||
height: 100%;
|
||||
grid-template-columns: repeat(var(--visible-track-count, 6), minmax(52px, 1fr));
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.app:not(.is-import) .lane-header {
|
||||
min-height: 0;
|
||||
height: 100%;
|
||||
grid-template-rows: 64px 1fr;
|
||||
padding: 7px 0 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.app:not(.is-import) .lane-name-row {
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.app:not(.is-import) .lane-icon {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
.app:not(.is-import) .lane-icon-toggle {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
.app:not(.is-import) .lane-name {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.app:not(.is-import) .lane-controls {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
min-height: 0;
|
||||
align-self: stretch;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
gap: 0;
|
||||
padding: 0 5px 38px;
|
||||
}
|
||||
|
||||
.app:not(.is-import) .lane-knob {
|
||||
width: 42px;
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
.app:not(.is-import) .lane-vu {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 72px;
|
||||
bottom: 48px;
|
||||
width: 12px;
|
||||
height: auto;
|
||||
transform: translateX(18px);
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
background:
|
||||
linear-gradient(to top,
|
||||
rgba(48, 197, 87, 0.14) 0 55%,
|
||||
rgba(225, 178, 46, 0.14) 55% 80%,
|
||||
rgba(214, 64, 64, 0.14) 80% 100%),
|
||||
rgba(4, 10, 15, 0.82);
|
||||
box-shadow: inset 0 0 0 1px rgba(148, 163, 184, 0.12);
|
||||
}
|
||||
|
||||
.app:not(.is-import) .lane-dl {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
right: 8px;
|
||||
bottom: 6px;
|
||||
height: 34px;
|
||||
transform: none;
|
||||
border: 1px solid color-mix(in srgb, var(--stem-color) 28%, rgba(148, 163, 184, 0.18));
|
||||
border-radius: 8px;
|
||||
background:
|
||||
linear-gradient(180deg, color-mix(in srgb, var(--stem-color) 13%, transparent), transparent),
|
||||
rgba(255, 255, 255, 0.055);
|
||||
color: var(--stem-color);
|
||||
opacity: 0.9;
|
||||
box-shadow:
|
||||
inset 0 0 0 1px rgba(255, 255, 255, 0.035),
|
||||
0 6px 14px rgba(0, 0, 0, 0.16);
|
||||
transition:
|
||||
opacity var(--t-base) var(--easing),
|
||||
background-color var(--t-base) var(--easing),
|
||||
border-color var(--t-base) var(--easing),
|
||||
transform var(--t-fast) var(--easing);
|
||||
}
|
||||
|
||||
.app:not(.is-import) .lane-dl svg {
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
stroke-width: 2.15;
|
||||
}
|
||||
|
||||
.app:not(.is-import) .lane-dl:hover:not(.disabled) {
|
||||
opacity: 1;
|
||||
border-color: color-mix(in srgb, var(--stem-color) 58%, transparent);
|
||||
background:
|
||||
linear-gradient(180deg, color-mix(in srgb, var(--stem-color) 18%, transparent), transparent),
|
||||
rgba(255, 255, 255, 0.075);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.app:not(.is-import) .lane-dl:focus-visible {
|
||||
outline: 2px solid var(--gold);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.app:not(.is-import) .lane-dl.disabled {
|
||||
opacity: 0.28;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.app:not(.is-import) .lane-vu::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 1px;
|
||||
right: 1px;
|
||||
top: 1px;
|
||||
bottom: 1px;
|
||||
background:
|
||||
repeating-linear-gradient(to top, transparent 0 3px, rgba(0, 0, 0, 0.4) 3px 5px),
|
||||
linear-gradient(to top, #24bf55 0 58%, #e1b22e 58% 80%, #d64040 80% 100%);
|
||||
clip-path: inset(calc(100% - var(--vu-level, 0%)) 0 0 0);
|
||||
transition: clip-path 30ms linear;
|
||||
}
|
||||
|
||||
.app:not(.is-import) .lane-vu::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 1px;
|
||||
right: 1px;
|
||||
bottom: var(--vu-peak, 0%);
|
||||
height: 2px;
|
||||
background: rgba(255, 255, 255, 0.78);
|
||||
transition: bottom 80ms linear;
|
||||
}
|
||||
|
||||
.app:not(.is-import) .master-strip {
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 72px 1fr;
|
||||
gap: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.app:not(.is-import) .master-strip .master-fader-track {
|
||||
height: calc(100% - 4px);
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.app:not(.is-import) .master-strip .master-fader-track::before,
|
||||
.app:not(.is-import) .master-strip .master-fader-track::after {
|
||||
display: none;
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
/* ───────────── Responsive ─────────────
|
||||
* Breakpoints:
|
||||
* ≤1100px — laptop / portrait tablet: now-playing card reflows to 3-col
|
||||
* with master spanning full width below transport.
|
||||
* ≤900px — landscape phone / small tablet: appbar wraps, lanes scroll
|
||||
* horizontally with a sticky mixer column, master compresses.
|
||||
* ≤640px — phone: mixer column narrower, brand smaller, transport
|
||||
* buttons full-width touch-friendly, master inline-compact.
|
||||
* ≤480px — small phone: tightest layout, art shrinks, paddings minimal.
|
||||
* pointer:coarse — touch input regardless of screen size: bump
|
||||
* interactive targets to a comfortable hit area.
|
||||
*/
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
.import-card {
|
||||
width: min(100%, 900px);
|
||||
}
|
||||
.stem-choice-row {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
.stem-choice-row > span {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
.appbar {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.appbar-import-panel .import-input-row {
|
||||
grid-template-columns: minmax(0, 1fr) minmax(144px, 180px);
|
||||
}
|
||||
.appbar-import-panel .stem-choice-row {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
.appbar-import-panel .stem-choice-row > span {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
.feature-strip {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 22px;
|
||||
}
|
||||
.feature-item + .feature-item {
|
||||
border-left: 0;
|
||||
border-top: 1px solid var(--gold-line);
|
||||
padding-left: 0;
|
||||
padding-top: 22px;
|
||||
}
|
||||
.now-playing {
|
||||
grid-template-columns: auto 1fr auto;
|
||||
grid-template-areas:
|
||||
"art info transport"
|
||||
"art master master";
|
||||
gap: 14px 16px;
|
||||
}
|
||||
.np-art { grid-area: art; }
|
||||
.np-info { grid-area: info; }
|
||||
.np-transport { grid-area: transport; }
|
||||
.np-master { grid-area: master; }
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.app {
|
||||
padding: 16px;
|
||||
gap: 12px;
|
||||
}
|
||||
.appbar {
|
||||
gap: 12px;
|
||||
}
|
||||
.import-page {
|
||||
padding: 54px 18px 20px;
|
||||
}
|
||||
.import-copy h2 {
|
||||
font-size: 31px;
|
||||
}
|
||||
.import-card {
|
||||
margin-top: 36px;
|
||||
padding: 18px;
|
||||
}
|
||||
.import-input-row {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.appbar-import-panel {
|
||||
padding: 16px;
|
||||
}
|
||||
.appbar-import-panel .import-input-row {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 12px;
|
||||
}
|
||||
.btn-primary {
|
||||
width: 100%;
|
||||
}
|
||||
.brand-group {
|
||||
flex: 1;
|
||||
}
|
||||
.appbar-form {
|
||||
order: 3;
|
||||
width: 100%;
|
||||
flex: none;
|
||||
}
|
||||
/* Compress the master section to recover vertical space — the full
|
||||
140px panel makes the now-playing card too tall when stacked. */
|
||||
.np-master {
|
||||
height: 90px;
|
||||
padding: 6px 8px;
|
||||
}
|
||||
/* Lane scrolling: mixer column stays put, waves scroll under it. */
|
||||
.lanes-body,
|
||||
.lanes-ruler {
|
||||
overflow-x: auto;
|
||||
}
|
||||
.mixer-column,
|
||||
.lanes-ruler-gutter {
|
||||
position: sticky;
|
||||
left: 0;
|
||||
z-index: 4;
|
||||
background: var(--panel);
|
||||
}
|
||||
/* Keep the waves area readable when scrolling — without a min-width
|
||||
the waveform canvases collapse below ~250px and become unusable. */
|
||||
.waves-column,
|
||||
.lanes-ruler-time {
|
||||
min-width: 480px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
:root {
|
||||
--header-w: 200px;
|
||||
}
|
||||
.brand {
|
||||
font-size: 22px;
|
||||
}
|
||||
.brand-logo {
|
||||
width: 146px;
|
||||
}
|
||||
.brand-sub {
|
||||
font-size: 12px;
|
||||
}
|
||||
.import-copy h2 {
|
||||
font-size: 26px;
|
||||
}
|
||||
.import-copy p {
|
||||
font-size: 15px;
|
||||
}
|
||||
.stem-choice-row {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
.feature-strip {
|
||||
padding: 22px;
|
||||
}
|
||||
.feature-item {
|
||||
grid-template-columns: 52px 1fr;
|
||||
}
|
||||
.now-playing {
|
||||
grid-template-columns: auto 1fr;
|
||||
grid-template-areas:
|
||||
"art info"
|
||||
"transport master";
|
||||
gap: 12px;
|
||||
}
|
||||
/* Inline transport + master side-by-side rather than stacked, so the
|
||||
card stays compact. Master is already compressed by the 900px rule. */
|
||||
.np-master {
|
||||
height: 80px;
|
||||
}
|
||||
.np-transport {
|
||||
align-self: center;
|
||||
}
|
||||
.lane-mini-wave {
|
||||
display: none; /* save horizontal space in the mixer column */
|
||||
}
|
||||
.np-title {
|
||||
font-size: 14px;
|
||||
-webkit-line-clamp: 3;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
:root {
|
||||
--header-w: 180px;
|
||||
--lane-h: 84px;
|
||||
}
|
||||
.app {
|
||||
padding: 12px;
|
||||
gap: 10px;
|
||||
}
|
||||
/* Single-column stem buttons; the 2-col grid still squeezes labels at
|
||||
~360px because each button needs the icon + text + 8px gap. */
|
||||
.stem-choice-row {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.stem-choice {
|
||||
min-height: 44px;
|
||||
}
|
||||
.feature-strip {
|
||||
margin-top: 24px;
|
||||
}
|
||||
.privacy-note {
|
||||
margin-top: 22px;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
}
|
||||
.now-playing {
|
||||
padding: 10px 12px;
|
||||
grid-template-columns: auto 1fr;
|
||||
grid-template-areas:
|
||||
"art info"
|
||||
"transport transport"
|
||||
"master master";
|
||||
gap: 10px;
|
||||
}
|
||||
.np-art {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
}
|
||||
.np-art-play {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
.np-master {
|
||||
height: 72px;
|
||||
}
|
||||
.np-transport {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.chip {
|
||||
padding: 3px 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
/* Drop the second chip column to one row of just the essentials */
|
||||
.np-chips {
|
||||
gap: 6px;
|
||||
}
|
||||
/* Mixer rows: tighten internal padding so M/S/knob/cloud fit. */
|
||||
.lane-content {
|
||||
padding: 8px 36px 8px 8px;
|
||||
}
|
||||
.lane-name {
|
||||
font-size: 13px;
|
||||
}
|
||||
/* Tighten lane VU on phone so the row stays readable. */
|
||||
.lane-vu {
|
||||
width: 18px;
|
||||
right: 4px;
|
||||
}
|
||||
/* Keep waves usable — lower the min-width slightly on tiny screens. */
|
||||
.waves-column,
|
||||
.lanes-ruler-time {
|
||||
min-width: 360px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Touch-input devices: enlarge interactive targets to ≥40px hit area
|
||||
regardless of screen size. Desktop stays compact. */
|
||||
@media (pointer: coarse) {
|
||||
.ms-btn {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
font-size: 13px;
|
||||
}
|
||||
.lane-knob {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.lane-knob-indicator {
|
||||
transform-origin: 50% 16px;
|
||||
height: 11px;
|
||||
top: 5px;
|
||||
}
|
||||
.lane-dl {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
.btn-transport {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
.avatar-btn {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
/* Bigger master fader thumb so it's easier to grab. */
|
||||
.master-fader::-webkit-slider-thumb {
|
||||
width: 32px;
|
||||
height: 18px;
|
||||
margin-left: -14px;
|
||||
}
|
||||
.master-fader::-moz-range-thumb {
|
||||
width: 32px;
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Landscape orientation on short screens (phones held sideways): the
|
||||
now-playing card eats too much vertical space if it tries to stack.
|
||||
Prefer a single horizontal row. */
|
||||
@media (max-height: 500px) and (orientation: landscape) {
|
||||
.now-playing {
|
||||
grid-template-columns: auto 1fr auto auto;
|
||||
grid-template-areas: "art info transport master";
|
||||
gap: 10px;
|
||||
padding: 8px 12px;
|
||||
}
|
||||
.np-master {
|
||||
height: 70px;
|
||||
}
|
||||
.np-art {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,632 @@
|
||||
/* ───────────── Import page ───────────── */
|
||||
|
||||
.import-page {
|
||||
min-height: clamp(420px, 60vh, 704px);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: clamp(28px, 6vw, 78px) clamp(14px, 3vw, 24px) clamp(18px, 3vw, 24px);
|
||||
border: 1px solid var(--glass-line);
|
||||
border-radius: 12px;
|
||||
background:
|
||||
radial-gradient(circle at 50% 22%, rgba(216, 168, 74, 0.1), transparent 23rem),
|
||||
radial-gradient(circle at 8% 45%, rgba(216, 168, 74, 0.06), transparent 22rem),
|
||||
radial-gradient(circle at 92% 45%, rgba(216, 168, 74, 0.06), transparent 22rem),
|
||||
linear-gradient(180deg, rgba(16, 26, 34, 0.78), rgba(8, 15, 22, 0.88));
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.035);
|
||||
}
|
||||
|
||||
.import-copy {
|
||||
text-align: center;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.import-copy h2 {
|
||||
margin: 0;
|
||||
color: #f1f3f5;
|
||||
font-size: clamp(24px, 3.4vw + 8px, 39px);
|
||||
line-height: 1.12;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.import-copy h2 span {
|
||||
color: var(--gold-bright);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.import-copy p {
|
||||
margin: 16px 0 0;
|
||||
color: #a9b0bb;
|
||||
font-size: clamp(14px, 1vw + 8px, 18px);
|
||||
}
|
||||
|
||||
.import-card {
|
||||
width: min(100%, 1088px);
|
||||
margin-top: clamp(20px, 4vw, 58px);
|
||||
padding: clamp(14px, 2vw, 19px) clamp(16px, 3vw, 36px) clamp(18px, 2.5vw, 28px);
|
||||
border-radius: 13px;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.import-input-row {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 24px;
|
||||
align-items: center;
|
||||
padding-bottom: 18px;
|
||||
border-bottom: 1px solid var(--glass-line);
|
||||
}
|
||||
|
||||
.stem-choice-row {
|
||||
display: grid;
|
||||
grid-template-columns: 138px repeat(6, minmax(86px, 1fr));
|
||||
gap: 14px;
|
||||
align-items: center;
|
||||
padding-top: 22px;
|
||||
}
|
||||
|
||||
.stem-choice-row > span {
|
||||
color: #d9dde4;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.stem-choice {
|
||||
min-height: 54px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 9px;
|
||||
border: 1px solid rgba(148, 163, 184, 0.18);
|
||||
border-radius: var(--radius);
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.025), transparent),
|
||||
rgba(8, 15, 22, 0.34);
|
||||
color: currentColor;
|
||||
font: inherit;
|
||||
font-weight: 700;
|
||||
transition:
|
||||
border-color var(--t-base) var(--easing),
|
||||
background-color var(--t-base) var(--easing),
|
||||
box-shadow var(--t-base) var(--easing),
|
||||
transform var(--t-fast) var(--easing);
|
||||
}
|
||||
|
||||
.stem-choice:hover {
|
||||
transform: translateY(-1px);
|
||||
background-color: rgba(255, 255, 255, 0.045);
|
||||
box-shadow: inset 0 0 22px color-mix(in srgb, currentColor 10%, transparent);
|
||||
}
|
||||
|
||||
/* Deselected state -- the user has unchecked this stem from the
|
||||
"stems to extract" set, so it's greyed out and won't appear in the
|
||||
studio dashboard after processing. Maintains layout (still occupies
|
||||
its grid slot) so the row doesn't reflow on toggle. */
|
||||
.stem-choice[aria-pressed="false"] {
|
||||
opacity: 0.32;
|
||||
border-color: rgba(148, 163, 184, 0.2) !important;
|
||||
background: rgba(8, 15, 22, 0.2);
|
||||
}
|
||||
|
||||
.stem-choice[aria-pressed="false"]:hover {
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
.stem-choice svg {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.stem-choice.vocals { color: #ff3f46; border-color: rgba(255, 63, 70, 0.28); }
|
||||
.stem-choice.drums { color: #ff7a1a; border-color: rgba(255, 122, 26, 0.24); }
|
||||
.stem-choice.bass { color: #ffd04d; border-color: rgba(255, 208, 77, 0.24); }
|
||||
.stem-choice.guitar { color: #3fc952; border-color: rgba(63, 201, 82, 0.24); }
|
||||
.stem-choice.piano { color: #974cff; border-color: rgba(151, 76, 255, 0.24); }
|
||||
.stem-choice.other { color: #3695ff; border-color: rgba(54, 149, 255, 0.24); }
|
||||
|
||||
.privacy-note {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 9px;
|
||||
margin-top: 34px;
|
||||
color: #a6adb7;
|
||||
font-size: 15px;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.feature-strip {
|
||||
width: min(100%, 1160px);
|
||||
min-height: 136px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
align-items: center;
|
||||
gap: clamp(18px, 2.4vw, 36px);
|
||||
margin-top: clamp(22px, 4vw, 54px);
|
||||
padding: clamp(16px, 2.4vw, 24px) clamp(18px, 3vw, 46px);
|
||||
border-radius: 13px;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.feature-item {
|
||||
display: grid;
|
||||
grid-template-columns: clamp(40px, 4vw, 68px) 1fr;
|
||||
align-items: center;
|
||||
gap: clamp(12px, 1.5vw, 24px);
|
||||
color: var(--gold);
|
||||
}
|
||||
|
||||
.feature-item svg {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-width: 48px;
|
||||
}
|
||||
|
||||
.feature-item + .feature-item {
|
||||
border-left: 1px solid var(--gold-line);
|
||||
padding-left: clamp(18px, 2.4vw, 42px);
|
||||
}
|
||||
|
||||
.feature-item strong {
|
||||
display: block;
|
||||
color: var(--ink);
|
||||
font-size: clamp(14px, 1vw + 6px, 16px);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.feature-item span {
|
||||
color: #a6adb7;
|
||||
font-size: clamp(13px, 0.8vw + 8px, 15px);
|
||||
}
|
||||
|
||||
/* The HTML hard-codes <br> in feature descriptions for desktop layout;
|
||||
on narrow viewports those forced breaks produce ragged 2-word lines.
|
||||
Collapse them so the text wraps naturally. */
|
||||
@media (max-width: 720px) {
|
||||
.feature-item br { display: none; }
|
||||
}
|
||||
|
||||
.wave-lines {
|
||||
position: absolute;
|
||||
top: 152px;
|
||||
width: 32%;
|
||||
height: 120px;
|
||||
opacity: 0.46;
|
||||
background:
|
||||
repeating-linear-gradient(108deg, transparent 0 24px, rgba(216, 168, 74, 0.52) 25px 27px, transparent 28px 50px);
|
||||
mask-image: radial-gradient(ellipse, black 0 48%, transparent 72%);
|
||||
}
|
||||
|
||||
.wave-left {
|
||||
left: 0;
|
||||
transform: skewY(-7deg);
|
||||
}
|
||||
|
||||
.wave-right {
|
||||
right: 0;
|
||||
transform: skewY(7deg);
|
||||
}
|
||||
|
||||
/* Decorative diagonal lines crowd the headline on narrow viewports
|
||||
(they're absolutely positioned at top: 152px; width: 32%) -- hide
|
||||
them below the tablet breakpoint to keep the headline area clean. */
|
||||
@media (max-width: 720px) {
|
||||
.wave-lines { display: none; }
|
||||
}
|
||||
|
||||
/* ───────────── Now-playing card ───────────── */
|
||||
|
||||
.now-playing {
|
||||
display: grid;
|
||||
grid-template-columns:
|
||||
clamp(110px, 11vw, 160px)
|
||||
minmax(0, 1.2fr)
|
||||
minmax(0, 0.9fr)
|
||||
minmax(0, 0.65fr)
|
||||
minmax(0, 0.65fr)
|
||||
minmax(0, 0.8fr);
|
||||
align-items: center;
|
||||
gap: 0;
|
||||
min-height: 224px;
|
||||
padding: 23px 24px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.app:not(.is-import) .now-playing {
|
||||
flex: 0 0 auto;
|
||||
min-height: clamp(120px, 14vh, 160px);
|
||||
padding-top: clamp(7px, 1vh, 12px);
|
||||
padding-bottom: clamp(7px, 1vh, 12px);
|
||||
}
|
||||
|
||||
.app:not(.is-import) .np-art {
|
||||
width: clamp(92px, 13vh, 132px);
|
||||
height: clamp(92px, 14vh, 144px);
|
||||
}
|
||||
|
||||
.np-art {
|
||||
position: relative;
|
||||
width: 154px;
|
||||
height: 168px;
|
||||
border-radius: 9px;
|
||||
overflow: hidden;
|
||||
background:
|
||||
linear-gradient(135deg, rgba(14, 22, 30, 0.95), rgba(5, 9, 13, 0.96)),
|
||||
var(--panel-2);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.np-art-placeholder {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--ink-faint);
|
||||
background: linear-gradient(135deg, #1a1a1a, #0e0e0e);
|
||||
}
|
||||
.np-art-img {
|
||||
position: absolute;
|
||||
inset: 6px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
width: calc(100% - 12px);
|
||||
height: calc(100% - 12px);
|
||||
object-fit: contain;
|
||||
display: none;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.np-art-img.loaded {
|
||||
display: block;
|
||||
}
|
||||
.np-art-play {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
border: 0;
|
||||
background: linear-gradient(180deg, var(--gold-bright), var(--gold));
|
||||
color: #fff;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 12px 24px rgba(216, 168, 74, 0.2);
|
||||
transition: transform var(--t-fast) var(--easing), background-color var(--t-base) var(--easing);
|
||||
}
|
||||
.np-art-play:hover {
|
||||
background: linear-gradient(180deg, #ecc76e, #c78a30);
|
||||
}
|
||||
.np-art-play svg {
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.np-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
min-width: 0;
|
||||
padding: 0 clamp(14px, 2vw, 28px) 0 clamp(16px, 2.2vw, 30px);
|
||||
border-right: 1px solid var(--glass-line);
|
||||
}
|
||||
.np-title {
|
||||
font-size: clamp(19px, 1.45vw, 24px);
|
||||
font-weight: 500;
|
||||
color: var(--ink);
|
||||
line-height: 1.2;
|
||||
white-space: normal;
|
||||
overflow: hidden;
|
||||
text-overflow: clip;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow-wrap: anywhere;
|
||||
max-width: 100%;
|
||||
}
|
||||
.np-chips {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 34px;
|
||||
padding: 5px 12px;
|
||||
background: rgba(255, 255, 255, 0.055);
|
||||
color: var(--ink);
|
||||
border: var(--border-w) solid var(--line);
|
||||
border-radius: var(--radius-xs);
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.np-play-row {
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr) auto;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
margin-top: 6px;
|
||||
color: #c6cbd2;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.np-scrub {
|
||||
height: 4px;
|
||||
border-radius: 999px;
|
||||
background: rgba(148, 163, 184, 0.16);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.np-scrub span {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
transform: translateY(-50%);
|
||||
border-radius: 50%;
|
||||
background: var(--gold-bright);
|
||||
box-shadow: 0 0 0 4px rgba(216, 168, 74, 0.18);
|
||||
}
|
||||
|
||||
.stem-energy,
|
||||
.analysis-card {
|
||||
min-height: clamp(100px, 14vh, 156px);
|
||||
padding: 0 clamp(10px, 1.4vw, 24px);
|
||||
border-left: 1px solid var(--glass-line);
|
||||
}
|
||||
|
||||
.stem-energy {
|
||||
grid-column: 3;
|
||||
}
|
||||
|
||||
.key-card {
|
||||
grid-column: 4;
|
||||
}
|
||||
|
||||
.loudness-card {
|
||||
grid-column: 5;
|
||||
}
|
||||
|
||||
.beat-card {
|
||||
grid-column: 6;
|
||||
}
|
||||
|
||||
.loudness-card.hidden + .beat-card {
|
||||
grid-column: 5 / 7;
|
||||
}
|
||||
|
||||
.stem-energy h3,
|
||||
.analysis-card h3 {
|
||||
margin: 0 0 13px;
|
||||
color: #c9ced6;
|
||||
font-size: 14px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.stem-energy h3 span,
|
||||
.analysis-card h3 span,
|
||||
.panel-title span {
|
||||
display: inline-grid;
|
||||
place-items: center;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-left: 4px;
|
||||
border: 1px solid currentColor;
|
||||
border-radius: 50%;
|
||||
font-size: 10px;
|
||||
opacity: 0.72;
|
||||
}
|
||||
|
||||
.energy-row {
|
||||
display: grid;
|
||||
grid-template-columns: 78px 1fr 40px;
|
||||
align-items: center;
|
||||
gap: 9px;
|
||||
margin: 5px 0;
|
||||
color: var(--stem-color);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.energy-row span {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.energy-row b {
|
||||
height: 12px;
|
||||
border-radius: 999px;
|
||||
background:
|
||||
linear-gradient(90deg, currentColor 0 var(--v, 0%), rgba(148, 163, 184, 0.13) var(--v, 0%) 100%);
|
||||
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.05);
|
||||
transition: background 80ms linear;
|
||||
}
|
||||
|
||||
.energy-row em {
|
||||
color: #c8cdd4;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.vocals { --stem-color: #e54249; color: var(--stem-color); }
|
||||
.drums { --stem-color: #f06a14; color: var(--stem-color); }
|
||||
.bass { --stem-color: #eab414; color: var(--stem-color); }
|
||||
.guitar { --stem-color: #5bbf50; color: var(--stem-color); }
|
||||
.piano { --stem-color: #7f45d8; color: var(--stem-color); }
|
||||
.other { --stem-color: #3e8dcf; color: var(--stem-color); }
|
||||
.original { --stem-color: #a8b0bd; color: var(--stem-color); }
|
||||
|
||||
.analysis-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.key-card {
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.beat-card {
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.analysis-card strong {
|
||||
color: var(--gold-bright);
|
||||
font-size: clamp(17px, 1.7vw, 26px);
|
||||
line-height: 1.1;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.analysis-card small {
|
||||
color: #b9bfc7;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.confidence-ring {
|
||||
width: 66px;
|
||||
height: 66px;
|
||||
position: relative;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border-radius: 50%;
|
||||
background:
|
||||
conic-gradient(
|
||||
var(--gold) calc(var(--confidence-pct, 0) * 1%),
|
||||
rgba(216, 168, 74, 0.16) 0
|
||||
);
|
||||
color: #e9edf2;
|
||||
isolation: isolate;
|
||||
font-size: 14px;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.confidence-ring::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 4px;
|
||||
border-radius: 50%;
|
||||
background: var(--panel);
|
||||
}
|
||||
|
||||
.confidence-ring::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: 50%;
|
||||
box-shadow:
|
||||
inset 0 0 0 1px rgba(216, 168, 74, 0.12),
|
||||
0 0 14px rgba(216, 168, 74, 0.1);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.confidence-ring span {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.loudness-card strong {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: 12px;
|
||||
align-items: baseline;
|
||||
color: #f0f2f5;
|
||||
}
|
||||
|
||||
.beat-values {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
gap: 16px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.beat-values strong {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: 12px;
|
||||
align-items: baseline;
|
||||
color: var(--gold-bright);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.beat-values strong small {
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
color: #b9bfc7;
|
||||
}
|
||||
|
||||
.np-transport {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 26px;
|
||||
color: #cfd4db;
|
||||
font-size: 14px;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.np-transport-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 22px;
|
||||
}
|
||||
.btn-transport {
|
||||
width: 58px;
|
||||
height: 58px;
|
||||
background: rgba(255, 255, 255, 0.055);
|
||||
color: var(--ink);
|
||||
border: 1px solid var(--glass-line);
|
||||
border-radius: 50%;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
background-color var(--t-base) var(--easing),
|
||||
color var(--t-base) var(--easing),
|
||||
border-color var(--t-base) var(--easing),
|
||||
transform var(--t-fast) var(--easing);
|
||||
}
|
||||
.btn-transport:hover {
|
||||
background: rgba(255, 255, 255, 0.09);
|
||||
border-color: var(--line-strong);
|
||||
}
|
||||
.btn-transport:active {
|
||||
transform: scale(0.94);
|
||||
}
|
||||
.btn-transport .pause-icon {
|
||||
display: none;
|
||||
}
|
||||
.btn-transport.playing .pause-icon {
|
||||
display: block;
|
||||
}
|
||||
.btn-transport.playing svg:not(.pause-icon) {
|
||||
display: none;
|
||||
}
|
||||
.btn-transport.playing {
|
||||
background: linear-gradient(180deg, #4ade80, #16a34a);
|
||||
color: white;
|
||||
border-color: #15803d;
|
||||
box-shadow: 0 16px 34px rgba(34, 197, 94, 0.22);
|
||||
}
|
||||
.btn-transport.stopped {
|
||||
background: linear-gradient(180deg, #f87171, #dc2626);
|
||||
color: white;
|
||||
border-color: #b91c1c;
|
||||
box-shadow: 0 16px 34px rgba(239, 68, 68, 0.22);
|
||||
}
|
||||
.btn-transport.loop.active {
|
||||
background: linear-gradient(180deg, var(--gold-bright), var(--gold));
|
||||
color: white;
|
||||
border-color: var(--gold-line);
|
||||
box-shadow: 0 16px 34px rgba(216, 168, 74, 0.18);
|
||||
}
|
||||
.np-time {
|
||||
font-size: 13px;
|
||||
color: var(--ink-dim);
|
||||
font-variant-numeric: tabular-nums;
|
||||
white-space: nowrap;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/* ── Design tokens ── */
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
|
||||
/* Surfaces */
|
||||
--bg: #0b0f12;
|
||||
--bg-2: #0f1418;
|
||||
--panel: #131a1f;
|
||||
--panel-2: #182026;
|
||||
--panel-3: #1d262d;
|
||||
--border: #232c34;
|
||||
--border-strong: #2e3942;
|
||||
|
||||
/* Text */
|
||||
--fg: #e8ecf0;
|
||||
--fg-2: #c2c9d1;
|
||||
--muted: #8a939c;
|
||||
--muted-2: #5d666e;
|
||||
|
||||
/* Stem colours */
|
||||
--vocals: #ef4444;
|
||||
--drums: #f97316;
|
||||
--bass: #eab308;
|
||||
--guitar: #22c55e;
|
||||
--piano: #a855f7;
|
||||
--other: #9ca3af;
|
||||
|
||||
/* Accent */
|
||||
--accent: #f4b740;
|
||||
--accent-2: #d99a2b;
|
||||
|
||||
/* Legacy compat aliases used by waves.css / player.js */
|
||||
--gold: var(--accent);
|
||||
--gold-bright: #f8c054;
|
||||
--gold-soft: rgba(244,183,64,0.16);
|
||||
--gold-line: rgba(244,183,64,0.28);
|
||||
--ink: var(--fg);
|
||||
--ink-dim: var(--fg-2);
|
||||
--ink-faint: var(--muted);
|
||||
--line: var(--border);
|
||||
--line-strong: var(--border-strong);
|
||||
--glass-line: var(--border);
|
||||
--danger: #d65a4a;
|
||||
--focus-ring: rgba(236,236,236,0.55);
|
||||
|
||||
/* Typography */
|
||||
--font-sans: 'Inter', -apple-system, system-ui, sans-serif;
|
||||
--font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
|
||||
|
||||
/* Layout */
|
||||
--header-w: 300px;
|
||||
--lane-h: 86px;
|
||||
--radius: 10px;
|
||||
--radius-sm: 8px;
|
||||
--radius-xs: 6px;
|
||||
|
||||
/* Motion */
|
||||
--t-fast: 80ms;
|
||||
--t-base: 120ms;
|
||||
--easing: cubic-bezier(0.2,0.8,0.2,1);
|
||||
--shadow-panel: 0 4px 24px rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
:root { --t-fast: 0ms; --t-base: 0ms; }
|
||||
*, *::before, *::after {
|
||||
animation-duration: 0.001ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.001ms !important;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user