/*
 * VaultMe. Dark by default, midnight purple as the accent; Light and Auto on the account page.
 * Every color and size used below is a token here; change them in one place.
 */

@font-face {
    font-family: "Geist";
    src: url("../fonts/Geist-Variable.woff2") format("woff2");
    font-weight: 100 900;
    font-display: swap;
}

@font-face {
    font-family: "Geist Mono";
    src: url("../fonts/GeistMono-Variable.woff2") format("woff2");
    font-weight: 100 900;
    font-display: swap;
}

/* Dark only: it is part of the brand. The colors come from the logo kit (background
   #0b0a10, the violet glow, and the holo lavender, ice blue and pink). */
:root {
    color-scheme: dark;

    --bg:          #0b0a10;
    --bg-raised:   #110e19;   /* sidebar, top bar */
    --surface:     #16121f;   /* cards */
    --surface-2:   #1f1a2b;   /* inputs, hover */
    --line:        #282236;
    --line-strong: #3a3150;

    --text:        #eeeaf6;
    --text-2:      #c2bad4;
    --muted:       #968cab;   /* 5.6:1 on --surface */
    --text-strong: #ffffff;

    --accent:       #7c3aed;  /* buttons */
    --accent-hover: #8b5cf6;
    --accent-ink:   #ffffff;  /* text and icons on --accent */
    --accent-hi:    #b79cff;  /* links, icons, focus rings */
    --accent-lo:    #d4c4ff;  /* hovered links, text on --accent-wash */
    --accent-wash:  rgb(139 92 246 / 0.16);
    --accent-ring:  rgb(139 92 246 / 0.4);

    --danger:      #f87171;
    --danger-text: #fca5a5;
    --danger-ink:  #1a0b0b;
    --danger-wash: rgb(248 113 113 / 0.13);
    --warn-text:   #fcd34d;
    --warn-wash:   rgb(251 191 36 / 0.12);
    --good-text:   #86efac;
    --good-wash:   rgb(74 222 128 / 0.12);

    --bar-bg:    rgb(17 14 25 / 0.9);   /* the tab bar on phones, under a blur */
    --glow:      rgb(97 51 143 / 0.55);  /* the logo kit's violet, behind sign-in and share pages */

    /* The logo's holo chrome, for small touches: the played part of a waveform. */
    --holo-1: #e9d5ff;   /* lavender */
    --holo-2: #a5f3fc;   /* ice blue */
    --holo-3: #f0abfc;   /* pink */
    --holo: linear-gradient(90deg, var(--holo-1), var(--holo-2) 50%, var(--holo-3));
    --shadow:    0 1px 0 rgb(255 255 255 / 0.03) inset, 0 12px 32px -16px rgb(0 0 0 / 0.7);
    --shadow-lg: 0 24px 64px -12px rgb(0 0 0 / 0.8);

    /* Projects without a cover yet get one of these, by id (cover_art() in view.php). */
    --tone-0: linear-gradient(135deg, #4c1d95, #7c3aed);
    --tone-1: linear-gradient(135deg, #1e3a8a, #6366f1);
    --tone-2: linear-gradient(135deg, #831843, #db2777);
    --tone-3: linear-gradient(135deg, #134e4a, #0d9488);
    --tone-4: linear-gradient(135deg, #7c2d12, #ea580c);
    --tone-5: linear-gradient(135deg, #3b0764, #c026d3);
    --tone-ink: #ffffff;

    --player-height: 76px;
    --island-bg: rgb(30 25 41 / 0.94);   /* the floating player on phones */
    --np-dim: rgb(0 0 0 / 0.55);           /* the page behind Now Playing */
    --np-dim-closed: rgb(0 0 0 / 0);
    --np-handle: rgb(255 255 255 / 0.3);  /* the grab handle on top of Now Playing */
    --np-wash: linear-gradient(rgb(11 10 16 / 0.35), rgb(11 10 16 / 0.6) 45%, rgb(11 10 16 / 0.85));

    --font: "Geist", system-ui, -apple-system, "Segoe UI", sans-serif;
    --mono: "Geist Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;

    --radius:    14px;
    --radius-sm: 9px;
    --sidebar:   232px;
    --tabbar:    64px;
    --topbar:    56px;
}

/* Base */

*, *::before, *::after { box-sizing: border-box; }

[hidden] { display: none !important; }

html {
    /* The page's very back, not only <body>'s: swiping back in the app shows what's behind the
       page for a moment, and it was white. */
    background: var(--bg);
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font: 400 15px/1.55 var(--font);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    /* No grey flash on tap; buttons have their own pressed states. */
    -webkit-tap-highlight-color: transparent;
    /* Like an app: pressing on the page doesn't select text or pop up the phone's copy and
       look-up menu. Boxes you type in stay selectable (below). */
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
}

input,
textarea,
[contenteditable] {
    -webkit-user-select: text;
    user-select: text;
    -webkit-touch-callout: default;
}

/* Links and pictures can't be picked up and dragged out of the page (Safari does that on a
   long press, which got in the way of holding a song to move it). Rows on computers are
   made draggable on purpose by app.js, for sorting. */
a,
img {
    -webkit-user-drag: none;
}

h1, h2, h3 {
    margin: 0;
    font-weight: 600;
    letter-spacing: -0.02em;
    line-height: 1.2;
}

h1 { font-size: 30px; letter-spacing: -0.03em; }
h2 { font-size: 18px; }

p { margin: 0; }

a { color: var(--accent-hi); text-decoration: none; }
a:hover { color: var(--accent-lo); }

:focus-visible {
    outline: 2px solid var(--accent-hi);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

::selection { background: var(--accent-ring); }

.muted { color: var(--muted); }

.visually-hidden {
    position: absolute !important;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

.icon {
    width: 20px;
    height: 20px;
    flex: none;
}

/* The logo: mark and name. */

.wordmark {
    display: inline-flex;
    align-items: center;
    gap: 10px;
}

.wordmark__mark {
    display: block;
    width: 30px;
    height: 30px;
}

.wordmark__name {
    display: block;
    width: auto;
    height: 14px;
}

.wordmark--lg { gap: 16px; }
.wordmark--lg .wordmark__mark { width: 56px; height: 56px; }
.wordmark--lg .wordmark__name { height: 26px; }
/* App shell: sidebar on the left, the page on the right. */

.shell {
    display: grid;
    grid-template-columns: var(--sidebar) minmax(0, 1fr);
    min-height: 100vh;
    min-height: 100dvh;
}

.sidebar {
    position: sticky;
    top: 0;
    display: flex;
    flex-direction: column;
    gap: 24px;
    height: 100vh;
    height: 100dvh;
    padding: 20px 14px;
    background: var(--bg-raised);
    border-right: 1px solid var(--line);
}

.brand {
    display: flex;
    align-items: center;
    padding: 4px 8px;
}

.brand:hover { color: inherit; }

.topbar { display: none; }

.nav {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.nav__link {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    min-height: 40px;
    padding: 8px 10px;
    border: 0;
    border-radius: var(--radius-sm);
    background: none;
    color: var(--text-2);
    font: inherit;
    font-weight: 500;
    text-align: left;
    cursor: pointer;
}

.nav__link .icon { color: var(--muted); }

.nav__link[aria-current="page"] {
    background: var(--accent-wash);
    color: var(--accent-lo);
}

.nav__link[aria-current="page"] .icon { color: var(--accent-hi); }

.nav__link--soon {
    opacity: 0.45;
    cursor: default;
}

@media (hover: hover) {
    .nav__link:not(.nav__link--soon):not([aria-current="page"]):hover {
        background: var(--surface-2);
        color: var(--text);
    }
}

.sidebar__foot {
    margin-top: auto;
    padding-top: 14px;
    border-top: 1px solid var(--line);
}

.account-link__name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.avatar {
    display: inline-grid;
    place-items: center;
    flex: none;
    width: 36px;
    height: 36px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--accent);
    color: var(--accent-ink);
    font: 600 15px/1 var(--font);
    cursor: pointer;
}

.avatar--sm { width: 28px; height: 28px; font-size: 13px; }
.avatar--lg { width: 64px; height: 64px; font-size: 26px; cursor: default; }

/* The account menu: a popover, placed by the sidebar's foot on computers. */

.account-menu {
    position: fixed;
    inset: auto auto 76px 14px;
    width: 260px;
    margin: 0;
    padding: 6px;
    border: 1px solid var(--line-strong);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    box-shadow: var(--shadow-lg);
}

.account-menu__head {
    display: flex;
    flex-direction: column;
    padding: 10px 12px 12px;
    border-bottom: 1px solid var(--line);
    margin-bottom: 6px;
}

.account-menu__name { font-weight: 600; }

.account-menu__email {
    overflow: hidden;
    color: var(--muted);
    font-size: 13px;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.account-menu form { margin: 0; }

.account-menu__item {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    min-height: 42px;
    padding: 8px 12px;
    border: 0;
    border-radius: var(--radius-sm);
    background: none;
    color: var(--text);
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.account-menu__item .icon { color: var(--muted); }

@media (hover: hover) {
    .account-menu__item:hover { background: var(--surface-2); color: var(--text); }
}

/* The page */

.page-col {
    position: relative;
    min-width: 0;
}

/* The cover's color glowing behind the top of a project's pages (cover_glow() in view.php).
   Everything else on the page sits above it. */
.page-glow {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 620px;
    pointer-events: none;
}

/* (Not the pop-ups: the browser places those itself.) */
.main > :not(.page-glow, [popover]),
.listen-main > :not(.page-glow, [popover]) { position: relative; }

.main {
    width: 100%;
    max-width: 880px;
    margin: 0 auto;
    padding: 40px 32px 120px;
}

.page-head { margin-bottom: 28px; }

.page-head__lede {
    margin-top: 4px;
    color: var(--muted);
}

.account-head {
    display: flex;
    align-items: center;
    gap: 18px;
}

.section { margin-top: 32px; }

.section__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 10px;
}

.section__head .section__title { margin: 0 0 0 4px; }

.section__title {
    margin: 0 0 10px 4px;
    color: var(--muted);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.card {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow);
}

.account-card { padding: 22px; }

.stack {
    display: flex;
    flex-direction: column;
    gap: 18px;
}

.empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 56px 24px;
    text-align: center;
}

.empty .muted { max-width: 420px; }

/* Text about the mouse and dropping files: not on touch screens. */
@media (hover: none) and (pointer: coarse) {
    .only-computer { display: none; }
}
.empty p:last-child { margin-top: 10px; }

.empty__icon {
    display: grid;
    place-items: center;
    width: 56px;
    height: 56px;
    margin-bottom: 6px;
    border-radius: 16px;
    background: var(--accent-wash);
    color: var(--accent-hi);
}

.empty__icon .icon { width: 26px; height: 26px; }

/* Messages */

.flash {
    margin-bottom: 20px;
    padding: 12px 16px;
    border-radius: var(--radius-sm);
    background: var(--good-wash);
    color: var(--good-text);
    font-weight: 500;
}

.flash--error {
    background: var(--danger-wash);
    color: var(--danger-text);
}

.verify-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 10px 16px;
    margin-bottom: 20px;
    padding: 10px 12px 10px 16px;
    border-radius: var(--radius-sm);
    background: var(--warn-wash);
    color: var(--warn-text);
}

.verify-bar strong { overflow-wrap: anywhere; }

/* Forms */

.field {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.field label { font-weight: 500; }
.field label .muted { font-weight: 400; }

.input {
    width: 100%;
    min-height: 44px;
    padding: 10px 12px;
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
    color: var(--text);
    font: inherit;
}

.input:focus {
    outline: none;
    border-color: var(--accent-hi);
    box-shadow: 0 0 0 3px var(--accent-ring);
}

.field--error .input { border-color: var(--danger); }

.field__hint {
    color: var(--muted);
    font-size: 13px;
}

.field__hint--good { color: var(--good-text); }

.field__error {
    color: var(--danger-text);
    font-size: 14px;
}

.check {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 40px;
    cursor: pointer;
}

.check input {
    width: 18px;
    height: 18px;
    margin: 0;
    accent-color: var(--accent);
}

.form-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

/* Buttons */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 44px;
    padding: 10px 18px;
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
    color: var(--text);
    font: 500 15px/1.2 var(--font);
    cursor: pointer;
}

.btn .icon { width: 18px; height: 18px; }

.btn--primary {
    border-color: transparent;
    background: var(--accent);
    color: var(--accent-ink);
}

.btn--quiet {
    border-color: transparent;
    background: none;
    color: var(--text-2);
}

.btn--danger {
    border-color: transparent;
    background: var(--danger);
    color: var(--danger-ink);
}

.btn--sm { min-height: 36px; padding: 6px 12px; font-size: 14px; }
.btn--block { width: 100%; }

.btn--disabled {
    opacity: 0.45;
    cursor: default;
}

@media (hover: hover) {
    .btn:hover { border-color: var(--muted); color: var(--text); }
    .btn--primary:hover { border-color: transparent; background: var(--accent-hover); color: var(--accent-ink); }
    .btn--quiet:hover { background: var(--surface-2); }
    .btn--danger:hover { border-color: transparent; color: var(--danger-ink); filter: brightness(1.08); }
    .btn--disabled:hover { border-color: transparent; background: var(--accent); }
}

.btn:active:not(.btn--disabled) { transform: translateY(1px); }

/* Signed-out pages: sign in, sign up, the email links and the home page. */

.bare-main {
    display: grid;
    /* One column no wider than the screen: the home page's row of screenshots scrolls inside it
       instead of stretching the page. */
    grid-template-columns: minmax(0, 1fr);
    place-items: center;
    min-height: 100vh;
    min-height: 100dvh;
    padding: 40px 20px;
    /* A soft purple glow behind the logo. */
    background: radial-gradient(ellipse 120% 70% at 50% -10%, var(--glow), transparent 75%);
}

.signin {
    display: flex;
    flex-direction: column;
    gap: 20px;
    width: 100%;
    max-width: 400px;
}

.signin__brand {
    display: flex;
    justify-content: center;
    margin: 0 0 8px;
}

.signin__card {
    display: flex;
    flex-direction: column;
    gap: 18px;
    padding: 28px;
}

.signin__title { font-size: 21px; }

/* "or", then Continue with Apple under the card: white on the dark page, Apple's own logo. */
.signin__or {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: -6px 0;
    color: var(--muted);
    font-size: 13px;
}

.signin__or::before,
.signin__or::after {
    content: "";
    flex: 1;
    border-top: 1px solid var(--line);
}

.signin__apple { display: grid; gap: 8px; }

.btn--apple,
.btn--apple:hover {
    min-height: 48px;
    border-color: transparent;
    background: var(--text-strong);
    color: #000;
    font-weight: 600;
}

.btn--apple__logo { margin-top: -2px; }

.signin__forgot,
.signin__switch {
    text-align: center;
}

.signin__switch { color: var(--text-2); }

/* Offline (app.js puts .is-offline on <html>): the page is a saved copy. A note says so, what
   needs the server is greyed out, and old messages from when it was saved aren't shown. */
.offline-note { display: none; }

.is-offline .offline-note {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0 0 18px;
    padding: 11px 14px;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text-2);
    font-size: 14px;
}

.offline-note .icon { flex: none; width: 16px; height: 16px; color: var(--accent-hi); }
.offline-note a { margin-left: auto; color: var(--accent-hi); font-weight: 600; white-space: nowrap; }
.is-offline .flash,
.is-offline .verify-bar,
.is-offline .cover-picker__hint { display: none; }

[data-offline-off] { opacity: 0.38; filter: grayscale(1); }
/* Inside a greyed-out row, not twice as faint. */
[data-offline-off] [data-offline-off] { opacity: 1; filter: none; }

/* "Not available offline": a small note that rises above the player and fades away. */
.toast {
    position: fixed;
    bottom: 120px;
    left: 50%;
    z-index: 1000;
    margin: 0;
    padding: 10px 18px;
    border: 1px solid var(--line-strong);
    border-radius: 999px;
    background: var(--surface-2);
    box-shadow: var(--shadow);
    color: var(--text);
    font-size: 14px;
    font-weight: 500;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    translate: -50% 8px;
    transition: opacity 0.2s ease, translate 0.2s ease;
}

.toast.is-shown { opacity: 1; translate: -50% 0; }
body:not(.has-player) .toast { bottom: 32px; }

/* Phones: above the tab bar and the island. */
@media (max-width: 760px) {
    .toast { bottom: calc(var(--tabbar) + 16px + env(safe-area-inset-bottom)); }
    body.has-player .toast { bottom: calc(var(--tabbar) + 96px + env(safe-area-inset-bottom)); }
}

/* A page on its way (app.js visit()): a thin holo line under the status bar, sliding along, so
   a tap on weak service visibly did something. */
.page-loading {
    position: fixed;
    top: env(safe-area-inset-top);
    left: 0;
    right: 0;
    z-index: 1001;
    height: 2px;
    overflow: hidden;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
}

.page-loading::before {
    content: "";
    position: absolute;
    inset: 0 auto 0 0;
    width: 40%;
    border-radius: 2px;
    background: linear-gradient(90deg, var(--holo-1), var(--holo-2), var(--holo-3));
    animation: page-loading 1.1s ease-in-out infinite;
}

.page-loading.is-on { opacity: 1; }

@keyframes page-loading {
    from { translate: -100% 0; }
    to { translate: 250% 0; }
}

@media (prefers-reduced-motion: reduce) {
    .page-loading::before { width: 100%; animation: none; opacity: 0.7; }
}

/* Add track on a project's page: a slim row of its own above the songs, like the Music app's
   "Add Music". Shown by app.js (it's hidden until uploads can work). */
.add-track {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    margin: 0 0 12px;
    padding: 11px 16px;
    border: 1px dashed var(--line-strong);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--accent-hi);
    font: inherit;
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
}

.add-track[hidden] { display: none; }
.add-track .icon { width: 18px; height: 18px; }
.add-track:hover { border-color: var(--accent-ring); background: var(--accent-wash); color: var(--accent-lo); }
.add-track:active { scale: 0.99; }

/* A page of reading (Privacy): one comfortable column, like an article. */
.doc {
    max-width: 680px;
    margin: 0 auto;
    padding: 40px 20px 64px;
    color: var(--text-2);
    font-size: 16px;
    line-height: 1.7;
}

.doc__brand { margin: 0 0 36px; }
/* Inside the app (signed in) the top bar already has the logo. */
.page-app .doc { padding-top: 8px; }
.page-app .doc__brand { display: none; }
.doc h1 { color: var(--text-strong); font-size: 36px; line-height: 1.15; letter-spacing: -0.02em; }
.doc__updated { margin: 6px 0 28px; color: var(--muted); font-size: 14px; }
.doc__lede { color: var(--text); font-size: 18px; line-height: 1.6; }
.doc h2 { margin: 40px 0 10px; color: var(--text-strong); font-size: 20px; letter-spacing: -0.01em; }
.doc p { margin: 0 0 14px; }
.doc ul,
.doc ol { margin: 0 0 14px; padding-left: 20px; }
.doc li { margin: 0 0 8px; }
.doc strong { color: var(--text); }
.doc a { color: var(--accent-hi); }
.doc__back { margin-top: 48px; }
.doc__back a { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); font-size: 14px; font-weight: 500; }
.doc__back .icon { width: 18px; height: 18px; }

/* The small Privacy link under sign-in, sign-up and the home page. */
.legal-links { margin: 18px 0 0; color: var(--muted); font-size: 13px; text-align: center; }
.legal-links a { color: var(--muted); }
.legal-links a:hover { color: var(--text-2); }
.signin__agree { margin: 0; text-align: center; }
.signin__agree a { color: var(--accent-hi); }

/* The home page, signed out (partials/home.php): what VaultMe is, the App Store's screenshots in a
   row, what sets it apart, questions, and the way in. Down the middle, phone first. */
.home {
    display: flex;
    flex-direction: column;
    gap: 72px;
    width: 100%;
    max-width: 1080px;
    padding: 12px 0 8px;
}

.home-hero {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 20px;
    max-width: 720px;
    margin: 0 auto;
    text-align: center;
}

.home-hero__brand { display: inline-flex; margin-bottom: 8px; }

.home-hero__title {
    margin: 0;
    color: var(--text-strong);
    font-size: clamp(38px, 9vw, 66px);
    font-weight: 800;
    letter-spacing: -0.035em;
    line-height: 1.04;
    text-wrap: balance;
}

.holo-text {
    background: var(--holo);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

.home-hero__lede {
    max-width: 560px;
    margin: 0;
    color: var(--text-2);
    font-size: clamp(17px, 2.4vw, 20px);
    line-height: 1.5;
    text-wrap: pretty;
}

.home-hero__actions,
.home-closing {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
}

.home-hero__actions { margin-top: 8px; }
.home .btn--lg { min-width: 220px; padding: 14px 24px; font-size: 17px; }

.store-badge { display: inline-flex; border-radius: 10px; }
.store-badge img { display: block; width: auto; height: 54px; }
.home__web { margin: 0; color: var(--muted); font-size: 14px; }
.home__web a { color: var(--accent-hi); }

/* A row to swipe through, running to the page's edges on a phone. */
.home-shots { margin: 0 -20px; }

.home-shots__row {
    display: flex;
    gap: 16px;
    padding: 4px 20px 16px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-padding: 0 20px;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}

.home-shots__row::-webkit-scrollbar { display: none; }

.home-shots__shot {
    flex: none;
    width: min(260px, 64vw);
    height: auto;
    border: 1px solid var(--line);
    border-radius: 24px;
    box-shadow: var(--shadow-lg);
    scroll-snap-align: start;
}

.home-features {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: 16px;
}

.home-feature {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 22px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
}

.home-feature__icon,
.whats-new__icon {
    display: grid;
    place-items: center;
    flex: none;
    width: 42px;
    height: 42px;
    border-radius: 12px;
    background: var(--accent-wash);
    color: var(--accent-hi);
}

.home-feature__title { margin: 4px 0 0; color: var(--text-strong); font-size: 18px; }
.home-feature__text { margin: 0; color: var(--text-2); font-size: 15px; line-height: 1.55; }

.home-story {
    max-width: 680px;
    margin: 0 auto;
    text-align: center;
}

.home-story__quote {
    margin: 0;
    color: var(--text-strong);
    font-size: clamp(19px, 2.6vw, 23px);
    line-height: 1.5;
    text-wrap: pretty;
}

.home-story__by { margin: 14px 0 0; color: var(--muted); font-size: 14px; }

.home-faq {
    width: 100%;
    max-width: 680px;
    margin: 0 auto;
}

.home-faq__heading { margin: 0 0 8px; color: var(--text-strong); font-size: 26px; text-align: center; }
.home-faq__item { border-bottom: 1px solid var(--line); }

.home-faq__question {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 18px 0;
    color: var(--text-strong);
    font-size: 17px;
    font-weight: 600;
    list-style: none;
    cursor: pointer;
}

.home-faq__question::-webkit-details-marker { display: none; }
.home-faq__question .icon { flex: none; color: var(--muted); transition: rotate 0.2s ease; }
.home-faq__item[open] .home-faq__question .icon { rotate: 180deg; }
.home-faq__answer { margin: 0 0 18px; color: var(--text-2); font-size: 15px; line-height: 1.6; }

.home-closing { padding: 8px 0; text-align: center; }
.home-closing__title { margin: 0 0 6px; color: var(--text-strong); font-size: clamp(28px, 5vw, 38px); letter-spacing: -0.02em; }
.home__legal { margin-top: 0; }

/* What's new (partials/whats-new.php): an App Store version's notes, a sheet from the bottom on
   phones like the app's others, with × to close. */
.whats-new { width: min(460px, calc(100vw - 32px)); }
.whats-new:popover-open { gap: 20px; }
.whats-new__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.whats-new__version { margin: 2px 0 0; font-size: 14px; }
.whats-new__close { margin: -8px -8px 0 0; }
.whats-new__list { display: flex; flex-direction: column; gap: 18px; margin: 0; padding: 0; list-style: none; }
.whats-new__item { display: flex; align-items: flex-start; gap: 14px; }
.whats-new__text { display: flex; flex-direction: column; gap: 3px; }
.whats-new__title { color: var(--text-strong); font-size: 16px; }
.whats-new__line { color: var(--text-2); font-size: 14.5px; line-height: 1.45; }

/* Importing: a row per file going up, and the overlay while files are dragged over the page. */

.drop-overlay {
    position: fixed;
    inset: 0;
    z-index: 50;
    display: grid;
    place-items: center;
    padding: 24px;
    background: rgb(11 10 16 / 0.85);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    /* The drop lands on the page beneath; app.js catches it on the window. */
    pointer-events: none;
}

.drop-overlay[hidden] { display: none; }

.drop-overlay__box {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    max-width: 480px;
    padding: 40px 48px;
    border: 2px dashed var(--accent-hi);
    border-radius: 20px;
    background: var(--accent-wash);
    text-align: center;
}

.drop-overlay__title {
    font-size: 20px;
    font-weight: 600;
}

.dropzone__icon {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    margin-bottom: 4px;
    border-radius: 12px;
    background: var(--accent-wash);
    color: var(--accent-hi);
}

.dropzone__hint {
    max-width: 420px;
    color: var(--muted);
    font-size: 14px;
}
.uploads {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.uploads:not(:empty) { margin-bottom: 20px; }

.upload {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 6px 12px;
    padding: 12px 14px;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--surface);
}

.upload__name {
    overflow: hidden;
    font-weight: 500;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.upload__bar {
    grid-column: 1 / -1;
    width: 100%;
    height: 6px;
    border: 0;
    border-radius: 3px;
    background: var(--surface-2);
    accent-color: var(--accent);
    appearance: none;
}

.upload__bar::-webkit-progress-bar { border-radius: 3px; background: var(--surface-2); }
.upload__bar::-webkit-progress-value { border-radius: 3px; background: var(--accent); }
.upload__bar::-moz-progress-bar { border-radius: 3px; background: var(--accent); }

.upload__state {
    grid-column: 1;
    color: var(--muted);
    font-size: 13px;
}

.upload button { grid-column: 2; grid-row: 1; }

.upload[data-kind="error"] .upload__state { color: var(--danger-text); }
.upload[data-kind="processing"] .upload__state { color: var(--accent-hi); }

/* Tracks */

.tracks {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.track {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 16px 18px;
}

.track__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
}

.track__name { min-width: 0; }

.track__title {
    overflow: hidden;
    font-size: 17px;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.track__meta {
    margin-top: 2px;
    color: var(--muted);
    font-size: 13px;
}

.waveform {
    display: block;
    width: 100%;
    height: 44px;
    opacity: 0.9;
}

.track__audio {
    display: block;
    width: 100%;
    height: 40px;
}

.version-state {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 8px 12px;
    padding: 8px 12px;
    border-radius: var(--radius-sm);
    background: var(--surface-2);
    color: var(--text-2);
    font-size: 14px;
}

.version-state--processing { background: var(--accent-wash); color: var(--accent-lo); }
.version-state--failed { background: var(--danger-wash); color: var(--danger-text); }
.version-state--uploading { background: var(--warn-wash); color: var(--warn-text); }

.older summary {
    color: var(--muted);
    font-size: 14px;
    cursor: pointer;
}

.older__list {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin: 12px 0 0;
    padding: 0;
    list-style: none;
}


/* Small shared bits */

.icon-btn {
    display: inline-grid;
    place-items: center;
    flex: none;
    width: 40px;
    height: 40px;
    padding: 0;
    border: 0;
    border-radius: var(--radius-sm);
    background: none;
    color: var(--muted);
    cursor: pointer;
}

.icon-btn:disabled { opacity: 0.35; cursor: default; }

@media (hover: hover) {
    .icon-btn:not(:disabled):hover { background: var(--surface-2); color: var(--text); }
}

.page-head--row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;
}

.page-head__actions { display: flex; align-items: center; gap: 10px; }

.back-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: -8px 0 18px -4px;
    padding: 6px 4px;
    color: var(--muted);
    font-size: 14px;
    font-weight: 500;
}

.back-link .icon { width: 18px; height: 18px; }

.tag {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 8px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 500;
    line-height: 1.6;
    vertical-align: 1px;
}

.tag--main { background: var(--accent-wash); color: var(--accent-lo); }
.tag--processing { background: var(--accent-wash); color: var(--accent-lo); }
.tag--failed { background: var(--danger-wash); color: var(--danger-text); }
.tag--uploading { background: var(--warn-wash); color: var(--warn-text); }

.input--sm { min-height: 36px; padding: 6px 10px; font-size: 14px; }
.input--file { padding: 8px; }

.field__label { font-weight: 500; }

/* Pop-ups (popover): a small card in the middle on computers, a sheet from the bottom on
   phones. Used for New project, Edit, and each track's ⋯ menu. */

.prompt,
.menu {
    width: min(420px, calc(100vw - 32px));
    max-height: calc(100dvh - 48px);
    margin: auto;
    padding: 22px;
    overflow: auto;
    border: 1px solid var(--line-strong);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    box-shadow: var(--shadow-lg);
}

.prompt:popover-open { display: flex; flex-direction: column; gap: 16px; }

.prompt--wide { width: min(520px, calc(100vw - 32px)); }

.prompt::backdrop,
.menu::backdrop {
    background: rgb(0 0 0 / 0.5);
}

.prompt__title { font-size: 20px; }

.prompt__section {
    padding-top: 16px;
    border-top: 1px solid var(--line);
}

.menu { width: min(320px, calc(100vw - 32px)); padding: 6px; }

.menu form { margin: 0; }

.menu__item {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    min-height: 44px;
    padding: 8px 12px;
    border: 0;
    border-radius: var(--radius-sm);
    background: none;
    color: var(--text);
    font: inherit;
    text-align: left;
    cursor: pointer;
}

/* A song's ⋯ menu opens with the song: cover, title (tap to rename, app.js), length. */
.menu__head {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 0 0 6px;
    padding: 8px 8px 12px;
    border-bottom: 1px solid var(--line);
}

.menu__head .menu__cover { flex: none; width: 48px; height: 48px; border-radius: 8px; font-size: 20px; }
.menu__head-text { display: flex; flex: 1; flex-direction: column; gap: 2px; min-width: 0; }

.menu__song {
    width: 100%;
    margin: 0 -6px;
    padding: 3px 6px;
    border: 1px solid transparent;
    border-radius: 8px;
    background: none;
    color: var(--text-strong);
    font: inherit;
    font-size: 17px;
    font-weight: 650;
    text-overflow: ellipsis;
    cursor: text;
}

/* Typing: it shows it's a box now. */
.menu__song:focus { border-color: var(--accent-ring); background: var(--surface-2); outline: none; }
.menu__sub { color: var(--muted); font-size: 13px; }

.menu__item .icon { color: var(--muted); }
.menu__item.is-current,
.menu__item.is-current .icon { color: var(--accent-hi); }
/* Sort: only the way it's sorted now has its tick; the others keep the space, lined up. */
#library-sort .menu__item:not(.is-current) .icon { visibility: hidden; }

/* Sort's heading and its line on dragging. */
.menu__title { padding: 10px 12px 4px; color: var(--muted); font-size: 13px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; }
.menu__hint { margin: 4px 0 0; padding: 10px 12px 8px; border-top: 1px solid var(--line); color: var(--muted); font-size: 13px; }
.menu__item--danger,
.menu__item--danger .icon { color: var(--danger-text); }

@media (hover: hover) {
    .menu__item:hover { background: var(--surface-2); color: var(--text); }
    .menu__item--danger:hover { color: var(--danger-text); }
}


/* Covers */

.cover {
    display: block;
    aspect-ratio: 1;
    width: 100%;
    height: auto;
    border-radius: var(--radius-sm);
    object-fit: cover;
    background: var(--surface-2);
}

.cover--blank {
    display: grid;
    place-items: center;
    color: var(--tone-ink);
    font-size: 40px;
    font-weight: 650;
    letter-spacing: -0.03em;
}

.cover--tone-0 { background: var(--tone-0); }
.cover--tone-1 { background: var(--tone-1); }
.cover--tone-2 { background: var(--tone-2); }
.cover--tone-3 { background: var(--tone-3); }
.cover--tone-4 { background: var(--tone-4); }
.cover--tone-5 { background: var(--tone-5); }

/* Your vault, the home page. */

.vault-head { margin-bottom: 30px; }

.vault-head__title {
    font-size: 44px;
    font-weight: 700;
    letter-spacing: -0.04em;
}

.section__heading {
    font-size: 20px;
    font-weight: 650;
    letter-spacing: -0.02em;
}

.section__more {
    font-size: 14px;
    font-weight: 500;
}

.section .section__head { margin-bottom: 14px; }

/* Find in Library: under the title, like the Music app's "Find in Albums". */
.library-search {
    position: relative;
    display: flex;
    align-items: center;
    margin: -6px 0 22px;
}

.library-search__field {
    display: flex;
    flex: 1;
    align-items: center;
    gap: 8px;
    height: 42px;
    padding: 0 40px 0 12px;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: var(--surface);
    color: var(--muted);
    cursor: text;
}

.library-search__field:focus-within { border-color: var(--accent-ring); }
.library-search__field .icon { flex: none; width: 18px; height: 18px; }

/* 16 px, or iPhones zoom in on the page when it's tapped. */
.library-search__input {
    flex: 1;
    min-width: 0;
    height: 100%;
    border: 0;
    background: none;
    color: var(--text);
    font: inherit;
    font-size: 16px;
    outline: none;
    appearance: none;
}

.library-search__input::placeholder { color: var(--muted); }
.library-search__input::-webkit-search-cancel-button { display: none; }
.library-search__clear { position: absolute; right: 2px; color: var(--muted); }
.library-search__clear .icon { width: 18px; height: 18px; }

.search-songs { margin-bottom: 26px; }
.search-songs__list { margin: 0; padding: 4px; list-style: none; }

.search-song {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px;
    border-radius: var(--radius-sm);
    color: inherit;
    text-decoration: none;
}

.search-song:hover { background: var(--surface-2); }
.search-song__cover { flex: none; width: 44px; height: 44px; border-radius: 6px; font-size: 18px; }
.search-song__text { display: flex; flex-direction: column; min-width: 0; }

.search-song__title,
.search-song__project {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.search-song__project { color: var(--muted); font-size: 13px; }
.search-empty { margin: 4px 0 22px; }

/* The admin page (/admin): big numbers, then everyone. */
.admin-numbers {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
    gap: 10px;
}

.admin-number {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: 0;
    padding: 14px 16px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
}

.admin-number strong { color: var(--text-strong); font-size: 26px; font-weight: 700; letter-spacing: -0.02em; }
.admin-number span { color: var(--muted); font-size: 13px; }
.admin-people { margin: 0; padding: 4px; list-style: none; }

.admin-person {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px;
    border-radius: var(--radius-sm);
    color: inherit;
    text-decoration: none;
}

.admin-person:hover { background: var(--surface-2); }
.admin-person__text { display: flex; flex: 1; flex-direction: column; min-width: 0; }

.admin-person__name,
.admin-person__meta {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.admin-person__name { font-weight: 600; }
.admin-person__meta { color: var(--muted); font-size: 13px; }
.admin-person__counts { flex: none; color: var(--text-2); font-size: 13px; text-align: right; }
.admin-facts { margin: 0; }
.admin-facts div { display: flex; justify-content: space-between; gap: 12px; padding: 8px 0; }
.admin-facts div + div { border-top: 1px solid var(--line); }
.admin-facts dt { color: var(--muted); }
.admin-facts dd { margin: 0; text-align: right; }

/* Add to VaultMe (/add): the files shared into the app, a new project, or one of the projects. */
.adding__files { margin: 0 0 16px; padding: 4px 16px; list-style: none; }
.adding__files:empty { display: none; }
.adding__file { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--line); }
.adding__file:last-child { border-bottom: 0; }
.adding__file .icon { flex: none; color: var(--accent-hi); }
.adding__file-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.adding__file-size { flex: none; color: var(--muted); font-size: 13px; }
.adding__file--refused .adding__file-name { color: var(--muted); text-decoration: line-through; }
.adding__new { display: flex; gap: 10px; margin-bottom: 24px; }
.adding__new .input { flex: 1; min-width: 0; }
.adding__new[hidden] { display: none; }
.adding__cancel { margin-top: 24px; text-align: center; }
.adding.is-busy { opacity: 0.5; pointer-events: none; }

/* The library: projects as a grid of covers. */

.projects {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 20px 16px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.project-card {
    display: flex;
    flex-direction: column;
    gap: 2px;
    color: var(--text);
}

.project-card:hover { color: var(--text); }

/* Move to: the same cards, as buttons that open the confirmation. */
.project-card--button {
    width: 100%;
    padding: 0;
    border: 0;
    background: none;
    color: var(--text);
    font: inherit;
    text-align: left;
    cursor: pointer;
}

@media (hover: hover) {
    .project-card--button:hover .project-card__cover { transform: translateY(-2px); }
}

/* A confirmation with a picture on top (the project a song is moving to). */
.prompt--confirm { text-align: center; }
.prompt--confirm:popover-open { align-items: center; }
.prompt--confirm .prompt__buttons { align-self: stretch; }

.prompt__cover {
    width: 96px;
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow);
}

.prompt__cover.cover--blank { font-size: 32px; }

.project-card__art {
    position: relative;
    display: block;
    margin-bottom: 8px;
}

/* "Shared": a working share link points at this project. */
.project-card__badge {
    position: absolute;
    top: 10px;
    right: 10px;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 10px;
    border-radius: 999px;
    background: rgb(11 10 16 / 0.72);
    color: var(--text);
    font-size: 12px;
    font-weight: 600;
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
}

.project-card__badge .icon { width: 14px; height: 14px; }

.project-card__cover {
    box-shadow: var(--shadow);
    transition: transform 0.15s ease;
}

@media (hover: hover) {
    .project-card:hover .project-card__cover { transform: translateY(-2px); }
}

.project-card__name {
    overflow: hidden;
    font-weight: 600;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.project-card__meta { color: var(--muted); font-size: 13px; }

/* A project's page */

.project-head {
    display: flex;
    align-items: flex-end;
    gap: 24px;
    margin-bottom: 28px;
}

.project-head__cover {
    flex: none;
    width: 200px;
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
}

.project-head__cover.cover--blank { font-size: 72px; }

.project-head__text { flex: 1; min-width: 0; }

.project-head__kind {
    color: var(--muted);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.project-head__title {
    display: flex;
    align-items: center;
    gap: 4px;
    margin: 4px 0 6px;
}

.project-head__name {
    margin: 0;
    font-size: 36px;
    overflow-wrap: anywhere;
}

.project-head__actions { margin-top: 16px; }

/* The cover is a button: a small image badge says so. On a computer it's hidden until the
   cover is hovered, then fades in and widens to "Change cover"; moving away folds the text
   back at once and fades the badge out a couple of seconds later. Phones have no hover, so
   there the icon always shows, or nobody would know the cover can be tapped. */
.cover-picker { flex: none; margin: 0; }

.cover-picker__label {
    position: relative;
    display: block;
    border-radius: var(--radius);
    cursor: pointer;
}

/* Only for keyboard users (Tab). A tap or click leaves focus on the hidden picker after it
   closes, and that would draw the ring around the cover. */
.cover-picker__label:has(:focus-visible) {
    outline: 2px solid var(--accent-hi);
    outline-offset: 3px;
}

.cover-picker__hint {
    position: absolute;
    right: 10px;
    bottom: 10px;
    display: flex;
    align-items: center;
    gap: 0;
    padding: 7px;
    border-radius: 999px;
    background: rgb(11 10 16 / 0.72);
    color: var(--text);
    font-size: 13px;
    font-weight: 500;
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    transition: padding 0.25s ease, gap 0.25s ease;
}

.cover-picker__hint .icon { width: 18px; height: 18px; }

/* The words fold away to nothing, so the badge can widen and narrow smoothly. */
.cover-picker__hint span {
    max-width: 0;
    overflow: hidden;
    white-space: nowrap;
    opacity: 0;
    transition: max-width 0.25s ease, opacity 0.2s ease;
}

@media (hover: hover) {
    /* Leaving: the text folds back straight away, the badge fades 1.8 s later. */
    .cover-picker__hint {
        opacity: 0;
        transition: opacity 0.4s ease 1.8s, padding 0.25s ease, gap 0.25s ease;
    }

    .cover-picker__label:hover .cover-picker__hint,
    .cover-picker__label:has(:focus-visible) .cover-picker__hint {
        gap: 6px;
        padding: 7px 12px;
        opacity: 1;
        transition: opacity 0.2s ease, padding 0.25s ease, gap 0.25s ease;
    }

    .cover-picker__label:hover .cover-picker__hint span,
    .cover-picker__label:has(:focus-visible) .cover-picker__hint span {
        max-width: 120px;
        opacity: 1;
    }
}

/* Phones: the cover presses in under the finger and springs back with a little bounce as the
   picker opens. The picker can't wait for it (iOS only opens it straight from the tap), so
   the bounce plays while the sheet slides up. Not for anyone who asked for less motion. */
@media (hover: none) and (prefers-reduced-motion: no-preference) {
    .cover-picker__label .project-head__cover {
        transition: transform 0.12s ease-out;
    }

    .cover-picker__label:active .project-head__cover {
        transform: scale(0.95);
    }

    .cover-picker__label.is-bouncing .project-head__cover {
        animation: cover-bounce 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
    }

    /* Held long enough for the cover's menu (app.js setUpCoverMenu): it sinks a little further. */
    .cover-picker__label.is-held .project-head__cover {
        transform: scale(0.92);
        transition-duration: 0.2s;
    }
}

@keyframes cover-bounce {
    0%   { transform: scale(0.95); }
    55%  { transform: scale(1.03); }
    100% { transform: scale(1); }
}

/* While a new cover goes up, the badge stays, saying so. */
.cover-picker.is-saving .project-head__cover { opacity: 0.5; }

.cover-picker.is-saving .cover-picker__hint {
    gap: 6px;
    padding: 7px 12px;
    opacity: 1;
}

.cover-picker.is-saving .cover-picker__hint span { max-width: 120px; opacity: 1; }

/* Renaming in place. */
.rename {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 4px 0 6px;
}

.rename__input {
    flex: 1 1 260px;
    min-height: 48px;
    font-size: 22px;
    font-weight: 600;
}

/* A button that's just an icon, the same height as the others (⋯). */
.btn--square { width: 44px; padding: 0; }

/* The cover before it's saved, and the delete prompt: iOS-like, buttons stacked. */
.cover-preview__image {
    width: 100%;
    max-width: 320px;
    align-self: center;
    border-radius: var(--radius);
}

.prompt__buttons {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.prompt--danger { text-align: center; }

.prompt--danger:popover-open { align-items: center; }

.prompt--danger .prompt__buttons { align-self: stretch; }

.prompt__icon {
    display: grid;
    place-items: center;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: var(--danger-wash);
    color: var(--danger-text);
}

/* Lists of tracks */

.track-list {
    margin: 0;
    padding: 6px;
    list-style: none;
}

.track-row {
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: 60px;
    padding: 6px 4px 6px 8px;
    border-radius: var(--radius-sm);
}

.track-row + .track-row { box-shadow: 0 -1px 0 var(--line); }

.track-row[draggable="true"] { cursor: grab; }
.track-row--dragging { opacity: 0.4; }

/* Phones: a song held and being dragged (app.js) floats above the others under the finger. */
.track-row--lifted {
    position: relative;
    z-index: 5;
    background: var(--surface-2);
    box-shadow: 0 14px 30px -10px rgb(0 0 0 / 0.75), 0 0 0 1px var(--line-strong);
    scale: 1.03;
    transition: scale 0.15s ease, box-shadow 0.15s ease;
}

.is-sorting .track-row:not(.track-row--lifted) { box-shadow: none; }

/* The Library in its own order: covers dragged on computers, held and dragged on phones (app.js).
   The held one floats under the finger; the others glide out of its way. */
.projects[data-arrange] > li[draggable="true"] { cursor: grab; }
.projects > li.is-dragging { opacity: 0.4; }
.projects > li.is-lifted { position: relative; z-index: 5; pointer-events: none; }
.projects > li.is-lifted .project-card__art {
    scale: 1.06;
    filter: drop-shadow(0 18px 24px rgb(0 0 0 / 0.6));
    transition: scale 0.15s ease;
}
.projects > li.is-lifted .project-card__name,
.projects > li.is-lifted .project-card__meta { opacity: 0; }

/* The whole row plays the song, like a music app. */
a.track-row__main { cursor: pointer; }

/* Opened at this song (from Your vault or Go to project): it glows, then fades back. */
.track-row.is-highlighted { animation: row-found 2.2s ease-out; }

@keyframes row-found {
    0%, 35% { background: var(--accent-wash); box-shadow: inset 0 0 0 1px var(--accent-ring); }
    100%    { background: transparent; box-shadow: inset 0 0 0 1px transparent; }
}

@media (prefers-reduced-motion: reduce) {
    .track-row.is-highlighted { animation-duration: 1.2s; }
}

@media (hover: hover) {
    .track-row:hover { background: var(--surface-2); box-shadow: none; }
    .track-row:hover + .track-row { box-shadow: none; }
}

.track-row__main {
    display: flex;
    flex: 1;
    flex-direction: column;
    min-width: 0;
    color: var(--text);
}

.track-row__main:hover { color: var(--text); }

.track-row__title {
    overflow: hidden;
    font-weight: 500;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.track-row__meta {
    color: var(--muted);
    font-size: 13px;
}

.track-row__meta .tag { margin-left: 0; }

/* The Downloads page's rows are buttons, not links: same look. */
button.track-row__main {
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

/* Play buttons: the play icon, or pause while that song plays (.is-playing, from app.js). */

.play-btn {
    display: inline-grid;
    place-items: center;
    flex: none;
    width: 40px;
    height: 40px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    cursor: pointer;
    background: var(--accent-wash);
    color: var(--accent-hi);
}

.play-btn:hover { color: var(--accent-lo); }

.play-btn .icon { grid-area: 1 / 1; width: 18px; height: 18px; }
.play-btn .eq { grid-area: 1 / 1; }

/* Play by default; while that song plays, the equalizer bouncing (pause on hover, on a
   computer, so it's clear what a click does). */
.play-btn .icon:last-of-type,
.play-btn .eq,
.play-btn.is-playing .icon:first-of-type { visibility: hidden; }
.play-btn.is-playing .eq { visibility: visible; }

@media (hover: hover) {
    .play-btn.is-playing:hover .eq { visibility: hidden; }
    .play-btn.is-playing:hover .icon:last-of-type { visibility: visible; }
}

/* The equalizer: three bars, each bouncing at its own pace. */
.eq {
    display: flex;
    align-items: flex-end;
    gap: 2px;
    height: 14px;
}

.eq span {
    width: 3px;
    height: 100%;
    border-radius: 1px;
    background: currentColor;
    transform-origin: bottom;
    animation: eq-bounce 0.9s ease-in-out infinite;
}

.eq span:nth-child(2) { animation-duration: 0.7s; animation-delay: -0.3s; }
.eq span:nth-child(3) { animation-duration: 1.1s; animation-delay: -0.6s; }

@keyframes eq-bounce {
    0%, 100% { transform: scaleY(0.3); }
    50%      { transform: scaleY(1); }
}

@media (prefers-reduced-motion: reduce) {
    .eq span { animation: none; }
    .eq span:nth-child(1) { transform: scaleY(0.6); }
    .eq span:nth-child(3) { transform: scaleY(0.4); }
}

/* The song that's playing has its name in the accent color, as in a music app. */
.track-row:has(.play-btn.is-playing) .track-row__title { color: var(--accent-hi); }

.play-btn.is-playing {
    background: var(--accent);
    color: var(--accent-ink);
}

.play-btn--off {
    background: var(--surface-2);
    color: var(--muted);
}

.play-btn--off .icon:last-of-type { visibility: visible; }

.play-btn--lg { width: 56px; height: 56px; background: var(--accent); color: var(--accent-ink); }
.play-btn--lg:hover { color: var(--accent-ink); background: var(--accent-hover); }
.play-btn--lg .icon { width: 24px; height: 24px; }

/* A track's page */

.track-head {
    display: flex;
    flex-direction: column;
    gap: 18px;
    margin-bottom: 24px;
}

.track-head__top {
    display: flex;
    align-items: center;
    gap: 16px;
}

.track-head__text { flex: 1; min-width: 0; }

.track-head__title {
    font-size: 30px;
    overflow-wrap: anywhere;
}

.track-head .waveform { height: 64px; }

.versions {
    margin: 0;
    padding: 6px;
    list-style: none;
}

.version {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 12px 6px 14px 10px;
}

.version + .version { border-top: 1px solid var(--line); }

.version__head {
    display: flex;
    align-items: center;
    gap: 12px;
}

.version__text { flex: 1; min-width: 0; }

.version__name { font-weight: 600; }

.version__meta {
    color: var(--muted);
    font-size: 13px;
}

.version__error {
    margin-top: 2px;
    color: var(--danger-text);
    font-size: 13px;
}

.note {
    display: flex;
    gap: 8px;
    padding-left: 52px;
}

.note__input { flex: 1; min-width: 0; }

/* Share links: the list, and the card for the one just made. */

.share-list {
    margin: 0;
    padding: 6px;
    list-style: none;
}

.share {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 12px 10px;
    border-radius: var(--radius-sm);
}

.share + .share { border-top: 1px solid var(--line); border-radius: 0; }

.share--new { background: var(--accent-wash); border-radius: var(--radius-sm); }
.share--off .share__who,
.share--off .share__icon { opacity: 0.55; }

.share__head {
    display: flex;
    align-items: center;
    gap: 12px;
}

.share__icon {
    display: grid;
    place-items: center;
    flex: none;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--surface-2);
    color: var(--accent-hi);
}

.share__icon .icon { width: 18px; height: 18px; }

.share__text { min-width: 0; }
.share__who { font-weight: 600; }
.share__meta { color: var(--muted); font-size: 13px; }

.share__address {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.share__url {
    flex: 1 1 220px;
    min-width: 0;
    font-family: var(--mono);
    font-size: 13px;
}

.share__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin: -4px 0 0 44px;
}

/* How much a link has been listened to; opens its listens page. */
.share__stats {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-left: 48px;
    color: var(--text-2);
    font-size: 13px;
    font-weight: 500;
}

.share__stats .icon { width: 16px; height: 16px; color: var(--accent-hi); }
.share__stats .icon:last-child { width: 14px; height: 14px; color: var(--muted); }
.share__stats:hover { color: var(--text-strong); }

/* A link's listens (/link): three numbers, then the visits. */
.stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    margin: 0 0 28px;
    padding: 16px 6px;
}

.stat { text-align: center; }
.stat + .stat { border-left: 1px solid var(--line); }
.stat dt { color: var(--muted); font-size: 13px; }
.stat dd { margin: 2px 0 0; color: var(--text-strong); font-size: 26px; font-weight: 650; font-variant-numeric: tabular-nums; }

.visits {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.visit { padding: 14px 16px; }
.visit__head { margin: 0 0 4px; font-size: 14px; }
.visit__when { font-weight: 600; }
.visit__who + .visit__when { font-weight: 400; color: var(--muted); }

/* Who saved a link to their Library, on its listens page. */
.savers { list-style: none; margin: 0; padding: 4px 18px; }
.saver { padding: 10px 0; font-size: 15px; }
.saver + .saver { border-top: 1px solid var(--line); }
.visit__none { margin: 0; font-size: 14px; }

.visit__listens {
    margin: 0;
    padding: 0;
    list-style: none;
}

.heard {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 2px 12px;
    padding: 10px 0 4px;
}

.heard + .heard { border-top: 1px solid var(--line); }
.heard__title { overflow: hidden; font-weight: 500; text-overflow: ellipsis; white-space: nowrap; }
.heard__how { color: var(--muted); font-size: 13px; }

.heard__bar {
    grid-column: 1 / -1;
    width: 100%;
    height: 4px;
    margin-top: 6px;
    border: 0;
    border-radius: 2px;
    background: var(--surface-2);
    appearance: none;
}

.heard__bar::-webkit-progress-bar { border-radius: 2px; background: var(--surface-2); }
.heard__bar::-webkit-progress-value { border-radius: 2px; background: var(--holo); }
.heard__bar::-moz-progress-bar { border-radius: 2px; background: var(--holo); }

/* Account → Storage: how much of the 3.5 GB is used. */
.storage__numbers { margin: 0; font-size: 15px; }
.storage__numbers strong { color: var(--text-strong); font-size: 20px; font-weight: 650; }
.storage__bar { height: 6px; margin: 12px 0 10px; }
.storage__bar--full::-webkit-progress-value { background: var(--danger); }
.storage__bar--full::-moz-progress-bar { background: var(--danger); }

/* The account's devices that get notifications. */
.device-list {
    margin: 0;
    padding: 0;
    list-style: none;
}

.device {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 0;
}

.device + .device { border-top: 1px solid var(--line); }
.device__text { display: flex; flex-direction: column; min-width: 0; }
.device__name { font-weight: 500; }
.device__meta { color: var(--muted); font-size: 13px; }

.share-ready {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-bottom: 24px;
    padding: 16px;
    border-color: var(--accent-ring);
    background: var(--accent-wash);
}

.share-ready__title {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--accent-lo);
    font-weight: 600;
}

/* The Share sheet's options: a grouped list of switches, like the iPhone's Settings. */

.settings {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface-2);
    overflow: hidden;
}

.setting {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    min-height: 58px;
    padding: 10px 14px;
    cursor: pointer;
}

.setting + .setting { border-top: 1px solid var(--line); }

.setting__text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.setting__name { font-weight: 500; }

.setting__hint {
    color: var(--muted);
    font-size: 13px;
}

/* The password box, under its switch, only while the switch is on. */
.setting--field {
    display: none;
    min-height: 0;
    padding-top: 0;
    cursor: auto;
}

.settings .setting--field { border-top: 0; }
.settings:has([data-share-password-switch]:checked) .setting--field { display: flex; }
.setting--field .input { width: 100%; background: var(--surface); }

/* A switch in the iOS manner, from a plain checkbox. */
.switch {
    position: relative;
    flex: none;
    width: 51px;
    height: 31px;
    margin: 0;
    border-radius: 999px;
    background: var(--line-strong);
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
    transition: background 0.2s ease;
}

.switch::before {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 27px;
    height: 27px;
    border-radius: 50%;
    background: var(--text-strong);
    box-shadow: 0 2px 6px rgb(0 0 0 / 0.35);
    transition: transform 0.2s ease;
}

.switch:checked { background: var(--accent); }
.switch:checked::before { transform: translateX(20px); }

.switch:focus-visible {
    outline: 2px solid var(--accent-hi);
    outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
    .switch,
    .switch::before { transition: none; }
}

.share-sheet .share__address .btn { min-width: 76px; }

/* The Share sheet: a new link on top, then the links already made, each in a row of its own. */
.share-sheet__new { display: flex; flex-direction: column; gap: 16px; }
.share-sheet__links .section__title { margin: 0 0 2px; }
.share-list--sheet { margin: 0; padding: 0; list-style: none; }
.share-list--sheet .share { padding: 12px 0; }
.share-list--sheet .share--new { padding: 12px 10px; }

/* A share link's page, for whoever it was sent to. */

.listen-main {
    position: relative;
    min-height: 100vh;
    min-height: 100dvh;
    padding: 28px 20px 140px;
    background: radial-gradient(ellipse 120% 55% at 50% -10%, var(--glow), transparent 75%);
}

.listen {
    display: flex;
    flex-direction: column;
    gap: 24px;
    max-width: 760px;
    margin: 0 auto;
}

/* The Downloads page (offline): the songs on this device, a list per project. */
.offline__head { display: flex; flex-direction: column; gap: 4px; }
.offline__projects { display: flex; flex-direction: column; gap: 22px; }
.offline__projects:empty { display: none; }
.offline__project { display: flex; flex-direction: column; gap: 10px; }
.offline__project-head { display: flex; align-items: center; gap: 12px; }
.offline__cover { width: 48px; height: 48px; flex: none; border-radius: 10px; font-size: 18px; }
.offline__cover[hidden] { display: none; }
.offline__project-name { color: var(--text-strong); font-size: 18px; }
.offline__back { margin: 8px 0 0; }

.listen__brand .wordmark__mark { width: 26px; height: 26px; }
.listen__brand .wordmark__name { height: 12px; }

.listen__head {
    display: flex;
    align-items: flex-end;
    gap: 24px;
}

.listen__cover {
    flex: none;
    width: 220px;
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
}

.listen__cover.cover--blank { font-size: 80px; }

.listen__text { min-width: 0; }

.listen__title {
    margin: 4px 0 6px;
    font-size: 38px;
    overflow-wrap: anywhere;
}

.listen__lock {
    align-items: stretch;
    max-width: 420px;
    margin: 6vh auto 0;
}

.listen__lock .empty__icon { align-self: flex-start; }

.listen__note {
    font-size: 13px;
    text-align: center;
}

/* The way to the App Store app, at the foot of a share page in a browser. */
.listen__store {
    display: grid;
    justify-items: center;
    gap: 12px;
    margin-top: 28px;
    text-align: center;
    font-size: 14px;
}

.listen__store p { margin: 0; }
.listen__badge img { height: 48px; }

.track-row__number {
    display: inline-block;
    min-width: 22px;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}

/* No sidebar on a share link's page, so the player runs the full width. */
.page-listen .player { left: 0; }

/* The player bar, along the bottom of the page (above the tab bar on phones). */

.player {
    position: fixed;
    inset: auto 0 0 var(--sidebar);
    z-index: 20;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1.6fr) auto;
    align-items: center;
    gap: 20px;
    height: var(--player-height);
    padding: 0 20px;
    background: var(--bar-bg);
    border-top: 1px solid var(--line);
    -webkit-backdrop-filter: blur(20px);
    backdrop-filter: blur(20px);
}

.player[hidden] { display: none; }

body.has-player .main { padding-bottom: calc(var(--player-height) + 80px); }

.player__info {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
    color: var(--text);
}

.player__info:hover { color: var(--text); }

.player__cover {
    flex: none;
    width: 48px;
    border-radius: 8px;
}

.player__cover.cover--blank { background: var(--accent-wash); color: var(--accent-hi); }
.player__cover.cover--blank .icon { width: 22px; height: 22px; }

.player__text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.player__title,
.player__artist {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.player__title { font-weight: 600; }

/* Phones only (the island): the time line and the progress line. */
.player__clock {
    display: none;
    color: var(--muted);
    font: 12px/1.4 var(--mono);
}

.player__progress { display: none; }
.player__artist { color: var(--muted); font-size: 13px; }

.player__controls {
    display: flex;
    align-items: center;
    gap: 6px;
}

.player__skip .icon { width: 20px; height: 20px; color: var(--text-2); }

.player__play {
    display: inline-grid;
    place-items: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--text-strong);
    color: var(--bg);
    cursor: pointer;
}

.player__play .icon { grid-area: 1 / 1; width: 20px; height: 20px; }
.player__play .icon:last-child,
.player.is-playing .player__play .icon:first-child,
.now-playing.is-playing .player__play .icon:first-child { visibility: hidden; }
.player.is-playing .player__play .icon:last-child,
.now-playing.is-playing .player__play .icon:last-child { visibility: visible; }

/* Now Playing: the whole screen, like the full player in a music app. A sheet that slides up
   over a dimmed page, with the cover blurred out of focus behind everything, the big cover
   (a little smaller while paused, as Apple Music does), the waveform to seek on, and big
   controls. Swiping the sheet down moves it with the finger (app.js). */

.now-playing {
    position: fixed;
    inset: 0;
    z-index: 60;
    background: var(--np-dim-closed);
    transition: background 0.38s ease;
}

.now-playing[hidden] { display: none; }
.now-playing.is-open { background: var(--np-dim); }
body.has-now-playing { overflow: hidden; }

.now-playing__sheet {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    /* Tighter on short screens, so everything fits without scrolling. */
    gap: clamp(10px, 2.4dvh, 22px);
    padding: calc(8px + env(safe-area-inset-top)) 24px calc(clamp(14px, 3dvh, 28px) + env(safe-area-inset-bottom));
    /* Never scrolls, like a music app's full player: everything is sized to fit instead. */
    overflow: hidden;
    overscroll-behavior: none;
    touch-action: none;
    background: var(--bg);
    transform: translateY(100%);
    transition: transform 0.42s cubic-bezier(0.32, 0.72, 0, 1);
}

.now-playing.is-open .now-playing__sheet { transform: translateY(0); }
.now-playing__sheet.is-dragging { transition: none; }

/* Everything but the glow sits in one centred column, above it. */
.now-playing__sheet > :not(.now-playing__glow) {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 440px;
}

/* A dark wash over the glow, so even a bright cover leaves the words readable. */
.now-playing__sheet::after {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--np-wash);
    pointer-events: none;
}

.now-playing__sheet:focus { outline: none; }

/* The glow's frame: the same size as the sheet, and it clips what's bigger. */
.now-playing__glow {
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
}

.now-playing__backdrop {
    position: absolute;
    inset: -20%;
    width: 140%;
    height: 140%;
    object-fit: cover;
    opacity: 0.45;
    filter: blur(70px) saturate(1.3);
    pointer-events: none;
}

.now-playing__top {
    display: grid;
    grid-template-columns: 44px minmax(0, 1fr) 44px;
    align-items: center;
    padding-top: 14px;
}

.now-playing__handle {
    position: absolute;
    top: 0;
    left: 50%;
    width: 38px;
    height: 5px;
    margin-left: -19px;
    border-radius: 3px;
    background: var(--np-handle);
}

.now-playing__close { color: var(--text); }
.now-playing__close .icon { width: 28px; height: 28px; }
.now-playing__airplay { color: var(--text); }
.now-playing__airplay[hidden] { display: none; }
.now-playing__airplay .icon { width: 24px; height: 24px; }

.now-playing__from {
    display: flex;
    flex-direction: column;
    align-items: center;
    min-width: 0;
    text-align: center;
}

.now-playing__from span {
    color: var(--muted);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.now-playing__from strong {
    max-width: 100%;
    overflow: hidden;
    font-size: 14px;
    font-weight: 600;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.now-playing__art {
    display: flex;
    justify-content: center;
    margin-top: 8px;
}

.now-playing__cover {
    width: max(140px, min(100%, 420px, calc(100dvh - 430px - env(safe-area-inset-top) - env(safe-area-inset-bottom))));
    border-radius: 14px;
    box-shadow: 0 30px 60px -20px rgb(0 0 0 / 0.85);
    transform: scale(0.86);
    transition: transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* With the volume slider under the controls, the cover gives up the room for it. */
.now-playing__sheet:has(.now-playing__volume:not([hidden])) .now-playing__cover {
    width: max(140px, min(100%, 420px, calc(100dvh - 520px - env(safe-area-inset-top) - env(safe-area-inset-bottom))));
}

.now-playing.is-playing .now-playing__cover { transform: scale(1); }

.now-playing__cover.cover--blank {
    background: var(--tone-0);
    color: var(--tone-ink);
}

.now-playing__cover.cover--blank .icon { width: 72px; height: 72px; }

/* The title and artist on the left, the A/B button to their right; the alternate's name and the
   A|B switch full width under them. */
.now-playing__meta {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 12px;
    align-items: center;
    min-width: 0;
}

.now-playing__meta > * { grid-column: 1; }
.now-playing__meta > .now-playing__ab { grid-column: 2; grid-row: 1 / span 2; }
.now-playing__meta > .now-playing__alt,
.now-playing__meta > .ab { grid-column: 1 / -1; }

.now-playing__ab {
    width: 48px;
    height: 36px;
    border: 1px solid var(--line-strong);
    border-radius: 999px;
    color: var(--text-2);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.02em;
}

.now-playing__ab[hidden] { display: none; }

.now-playing__title {
    overflow: hidden;
    font-size: 24px;
    font-weight: 700;
    letter-spacing: -0.02em;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.now-playing__title .player__version { color: var(--muted); font-weight: 500; }

.now-playing__artist {
    margin-top: 2px;
    color: var(--text-2);
    font-size: 17px;
}

.now-playing .now-playing__wave {
    flex: none;
    width: 100%;
    height: 64px;
}

.now-playing__times {
    display: flex;
    justify-content: space-between;
    margin-top: 6px;
    color: var(--muted);
    font: 12px/1 var(--mono);
}

.now-playing__controls {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 40px;
}

.now-playing__skip {
    width: 56px;
    height: 56px;
    color: var(--text);
}

.now-playing__skip .icon { width: 32px; height: 32px; }

.now-playing .player__play.now-playing__play {
    width: 76px;
    height: 76px;
}

.now-playing__play .icon { width: 32px !important; height: 32px !important; }

/* Volume (where the device allows it; never on iPhone): the speaker to mute, then a thin slider
   filled in white up to the level, like the waveform's played part. */
.volume {
    display: flex;
    align-items: center;
    gap: 6px;
}

.volume[hidden] { display: none; }
.volume .icon { width: 18px; height: 18px; color: var(--text-2); }
.volume__mute .icon:nth-of-type(2) { display: none; }
.volume.is-muted .volume__mute .icon:nth-of-type(1) { display: none; }
.volume.is-muted .volume__mute .icon:nth-of-type(2) { display: block; }
.volume__loud { display: grid; place-items: center; }

.volume__range {
    --fill: 100%;
    width: 110px;
    height: 4px;
    margin: 0;
    border-radius: 2px;
    background: linear-gradient(to right, var(--text) var(--fill), var(--line-strong) var(--fill));
    cursor: pointer;
    appearance: none;
}

.volume__range::-webkit-slider-thumb {
    width: 14px;
    height: 14px;
    border: 0;
    border-radius: 50%;
    background: var(--text-strong);
    box-shadow: 0 1px 4px rgb(0 0 0 / 0.5);
    appearance: none;
}

.volume__range::-moz-range-thumb {
    width: 14px;
    height: 14px;
    border: 0;
    border-radius: 50%;
    background: var(--text-strong);
}

.volume__range:focus-visible { outline: 2px solid var(--accent-ring); outline-offset: 4px; }

/* In Now Playing: the width of the controls, under them. */
.now-playing__volume { align-self: center; width: min(100%, 340px); }
.now-playing__volume .volume__range { flex: 1; width: auto; }

.now-playing__go {
    align-self: center;
    width: auto !important;
    color: var(--muted);
}

/* Under the controls: shuffle, Go to project, Up Next. On a share page only Go to project's
   place is kept (empty there): no queue to edit. */
.now-playing__bottom {
    display: grid;
    grid-template-columns: 44px minmax(0, 1fr) 44px;
    align-items: center;
}

.now-playing__bottom .now-playing__go { justify-self: center; }
.now-playing__tool { color: var(--text-2); }
.now-playing__tool .icon { width: 22px; height: 22px; }
.page-listen [data-queue-tool] { visibility: hidden; }

/* Shuffle and repeat light up while they're on; repeat one shows the 1. */
[data-shuffle-toggle][aria-pressed="true"],
[data-ab-toggle][aria-pressed="true"],
[data-repeat-toggle]:not([data-repeat="off"]) {
    background: var(--accent-wash);
    color: var(--accent-hi);
}

/* A/B on glows a little more: the switch it opens is right above. */
[data-ab-toggle][aria-pressed="true"] { border-color: var(--accent-hi); box-shadow: 0 0 14px var(--accent-ring); }

[data-repeat-toggle] .icon:last-of-type { display: none; }
[data-repeat-toggle][data-repeat="one"] .icon:first-of-type { display: none; }
[data-repeat-toggle][data-repeat="one"] .icon:last-of-type { display: block; }

/* Up Next: a sheet from the bottom on phones, over Now Playing. */
.up-next {
    width: min(460px, calc(100vw - 32px));
    max-height: min(680px, calc(100dvh - 48px));
}

.up-next:popover-open { gap: 10px; }
.up-next__head { display: flex; align-items: center; gap: 4px; }
.up-next__head .prompt__title { flex: 1; }
.up-next__playing { color: var(--muted); font-size: 13px; }
.up-next__playing:empty { display: none; }
.up-next__list { margin: 0; padding: 0; list-style: none; }

.up-next__row {
    position: relative;
    display: flex;
    align-items: center;
    gap: 2px;
    border-radius: var(--radius-sm);
    background: var(--surface);
    /* Up and down scroll the list; sideways is the swipe that takes a song out (app.js). */
    touch-action: pan-y;
    transition: transform 0.2s ease, opacity 0.2s ease;
}

.up-next__row.is-moving { transition: none; }

.up-next__row.is-dragging {
    z-index: 2;
    background: var(--surface-2);
    box-shadow: var(--shadow-lg);
}

.up-next__song {
    display: flex;
    flex: 1;
    align-items: center;
    gap: 12px;
    min-width: 0;
    padding: 8px 4px;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.up-next__cover { flex: none; width: 44px; height: 44px; border-radius: 6px; }
.up-next__cover.cover--blank { background: var(--tone-0); }
.up-next__cover.cover--blank .icon { width: 20px; height: 20px; }
.up-next__cover[hidden] { display: none; }
.up-next__text { display: flex; flex-direction: column; min-width: 0; }

.up-next__title,
.up-next__project {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.up-next__project { color: var(--muted); font-size: 13px; }

.up-next__grip {
    display: grid;
    flex: none;
    place-items: center;
    width: 44px;
    height: 44px;
    color: var(--muted);
    cursor: grab;
    touch-action: none;
}

.up-next__remove { color: var(--muted); }
/* Touch screens swipe instead. */
@media (hover: none) {
    .up-next__remove { display: none; }
}

.up-next__empty[hidden],
.up-next__clear[hidden] { display: none; }
.up-next__clear { align-self: center; }

/* Compare versions: the line naming an alternate version, and the A|B switch under the artist. */
.now-playing__alt {
    margin-top: 2px;
    overflow: hidden;
    color: var(--accent-hi);
    font-size: 14px;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.now-playing__alt[hidden] { display: none; }

.ab {
    display: flex;
    align-items: stretch;
    max-width: 100%;
    margin-top: 12px;
    padding: 3px;
    border: 1px solid var(--line-strong);
    border-radius: 999px;
    background: rgb(255 255 255 / 0.05);
}

.ab[hidden] { display: none; }

.ab__side {
    display: inline-flex;
    flex: 0 1 auto;
    align-items: center;
    gap: 7px;
    min-width: 0;
    min-height: 34px;
    padding: 4px 14px;
    border: 0;
    border-radius: 999px;
    background: none;
    color: var(--text-2);
    font: inherit;
    font-size: 14px;
    cursor: pointer;
}

.ab__side span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ab__side[data-ab-side="b"] { flex: 1 1 auto; }

.ab__dot {
    flex: none;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--line-strong);
}

/* The side that's playing. */
.ab__side.is-on { background: var(--accent-wash); color: var(--text-strong); }
.ab__side.is-on .ab__dot { background: var(--accent-hi); box-shadow: 0 0 8px var(--accent-hi); }

.ab__more {
    display: grid;
    flex: none;
    place-items: center;
    width: 38px;
    border: 0;
    border-left: 1px solid var(--line);
    background: none;
    color: var(--muted);
    cursor: pointer;
}

.ab__more .icon { width: 18px; height: 18px; }

/* The versions sheet: like Up Next, a sheet from the bottom on phones. */
.versions-sheet { width: min(460px, calc(100vw - 32px)); max-height: min(620px, calc(100dvh - 48px)); }
.versions-sheet:popover-open { gap: 10px; }
.versions-sheet__lede { font-size: 14px; }
.versions-sheet__list { margin: 0; padding: 0; list-style: none; }

.version-pick {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    min-height: 56px;
    padding: 8px 6px;
    border: 0;
    border-radius: var(--radius-sm);
    background: none;
    color: var(--text);
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.version-pick__number {
    display: grid;
    flex: none;
    place-items: center;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: var(--surface-2);
    font-weight: 650;
}

.version-pick__text { display: flex; flex: 1; flex-direction: column; min-width: 0; }
.version-pick__note { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.version-pick__made { color: var(--muted); font-size: 13px; }
.version-pick__main { flex: none; padding: 2px 8px; border-radius: 999px; background: var(--accent-wash); color: var(--accent-lo); font-size: 12px; }
.version-pick.is-current .version-pick__number { background: var(--accent); color: var(--accent-ink); }
.version-pick.is-current .version-pick__note { color: var(--accent-hi); }

@media (hover: hover) {
    .version-pick:hover { background: var(--surface-2); }
    .ab__side:not(.is-on):hover { color: var(--text); }
}

/* Short screens (small iPhones): a smaller play button, waveform and title. */
@media (max-height: 700px) {
    .now-playing .player__play.now-playing__play { width: 64px; height: 64px; }
    .now-playing .now-playing__wave { height: 52px; }
    .now-playing__title { font-size: 21px; }
}

@media (prefers-reduced-motion: reduce) {
    .now-playing,
    .now-playing__sheet,
    .now-playing__cover { transition: none; }
}

.player__seek {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

.player__time {
    flex: none;
    min-width: 34px;
    color: var(--muted);
    font: 12px/1 var(--mono);
    text-align: center;
}

.player__wave {
    flex: 1;
    height: 36px;
    min-width: 0;
    cursor: pointer;
    touch-action: none;
}

.player__wave canvas { display: block; width: 100%; height: 100%; }

.tabbar { display: none; }

/* Phones and narrow windows: a top bar and a tab bar instead of the sidebar. */

@media (max-width: 760px) {
    .shell { display: block; }

    .sidebar { display: none; }

    .topbar {
        position: sticky;
        top: 0;
        z-index: 10;
        display: flex;
        align-items: center;
        justify-content: space-between;
        height: calc(var(--topbar) + env(safe-area-inset-top));
        padding: env(safe-area-inset-top) 12px 0 8px;
        background: var(--bar-bg);
        border-bottom: 1px solid var(--line);
        -webkit-backdrop-filter: blur(16px);
        backdrop-filter: blur(16px);
    }

    .main { padding: 24px 16px calc(var(--tabbar) + 40px + env(safe-area-inset-bottom)); }

    h1 { font-size: 26px; }

    .account-card { padding: 18px; }

    /* Inputs at 16px or iOS zooms in when one is tapped. */
    .input { font-size: 16px; }

    .account-menu { inset: calc(var(--topbar) + env(safe-area-inset-top) + 4px) 12px auto auto; }

    /* The player as a floating island above the tab bar, like Apple Music's: cover, title,
       "v3 · 1:42 / 3:28", play and next, and a thin progress line along its bottom. Tapping
       the cover or title opens the track. */
    .player {
        inset: auto 10px calc(var(--tabbar) + env(safe-area-inset-bottom) + 8px) 10px;
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas: "info controls";
        gap: 12px;
        height: auto;
        padding: 8px 10px 9px 8px;
        overflow: hidden;
        border: 1px solid var(--line-strong);
        border-radius: 18px;
        background: var(--island-bg);
        box-shadow: var(--shadow-lg);
    }

    .player__info { grid-area: info; }
    .player__controls { grid-area: controls; gap: 2px; }
    .player__seek,
    .player__volume { display: none; }
    .player__cover { width: 46px; border-radius: 10px; }
    .player__play { width: 44px; height: 44px; }
    .player .player__artist,
    .player .player__version { display: none; }
    .player__clock { display: block; }

    .player__progress {
        position: absolute;
        right: 16px;
        bottom: 0;
        left: 16px;
        display: block;
        width: auto;
        height: 3px;
        border: 0;
        border-radius: 2px;
        background: transparent;
        appearance: none;
        -webkit-appearance: none;
    }

    .player__progress::-webkit-progress-bar { background: var(--line); border-radius: 2px; }
    .player__progress::-webkit-progress-value { background: var(--holo); border-radius: 2px; }
    .player__progress::-moz-progress-bar { background: var(--holo); border-radius: 2px; }

    /* Phones keep next; previous is on the lock screen and in the list. */
    .player [data-player-previous] { display: none; }

    /* Share pages have no tab bar, so there the island sits near the bottom edge. */
    .page-listen .player { bottom: calc(10px + env(safe-area-inset-bottom)); }
    body.has-player .main { padding-bottom: calc(var(--tabbar) + 110px + env(safe-area-inset-bottom)); }

    /* Pop-ups slide up from the bottom, like a phone's own sheets. */
    .prompt,
    .menu {
        width: 100%;
        max-width: none;
        margin: auto 0 0;
        padding-bottom: calc(22px + env(safe-area-inset-bottom));
        border-radius: var(--radius) var(--radius) 0 0;
    }

    .menu { padding: 8px 8px calc(8px + env(safe-area-inset-bottom)); }

    /* Phones: everything down the middle, a big cover first, like an album page. */
    .project-head {
        flex-direction: column;
        align-items: center;
        gap: 18px;
        text-align: center;
    }

    .project-head__cover { width: min(280px, 72vw); }
    .project-head__text { width: 100%; }

    /* The pencil sits beside the name; the same space on the other side keeps the name
       itself in the middle. */
    .project-head__title {
        justify-content: center;
        padding-left: 44px;
    }

    .project-head__name { font-size: 28px; }
    .rename { justify-content: center; }
    /* The name gets the whole width; Save and Cancel sit side by side under it. */
    .rename__input { flex-basis: 100%; font-size: 20px; text-align: center; }
    .project-head__actions { justify-content: center; }

    .projects {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 18px 12px;
    }

    .track-head__title { font-size: 24px; }

    .note { padding-left: 0; }

    .share__actions { margin-left: 0; }

    /* Share and Edit on a project: just their icons, so the row fits on one line. */
    .btn--icon-phone { padding: 10px 13px; }
    .btn--icon-phone .btn__label { display: none; }

    /* Share link page: no tab bar, so the player sits at the very bottom. */
    .listen-main { padding: 20px 16px 170px; }
    .listen__head { flex-direction: column; align-items: flex-start; gap: 18px; }
    .listen__cover { width: 100%; max-width: 320px; align-self: center; }
    .listen__title { font-size: 30px; }
    /* Its title sits on the left, so its buttons do too (a project page centres both). */
    .listen__head .project-head__actions { justify-content: flex-start; }

    .tabbar {
        position: fixed;
        inset: auto 0 0;
        z-index: 10;
        display: grid;
        grid-auto-columns: 1fr;
        grid-auto-flow: column;
        height: calc(var(--tabbar) + env(safe-area-inset-bottom));
        padding-bottom: env(safe-area-inset-bottom);
        background: var(--bar-bg);
        border-top: 1px solid var(--line);
        -webkit-backdrop-filter: blur(16px);
        backdrop-filter: blur(16px);
    }

    .tabbar__link {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 3px;
        margin: 6px 4px;
        border-radius: 14px;
        color: var(--muted);
        font-size: 11px;
        font-weight: 500;
    }

    .tabbar__link .icon { width: 24px; height: 24px; }

    .tabbar__link[aria-current="page"] {
        background: var(--accent-wash);
        color: var(--accent-hi);
    }
    .tabbar__link--soon { opacity: 0.45; }

    .signin__card { padding: 22px; }
    .wordmark--lg .wordmark__mark { width: 48px; height: 48px; }
    .wordmark--lg .wordmark__name { height: 22px; }
}
