8f10353f0c
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
312 lines
6.7 KiB
CSS
312 lines
6.7 KiB
CSS
/* ───────────── 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;
|
|
}
|
|
}
|