* { box-sizing: border-box; }

/* Dark only (matches music-box/db-audio-meta, neither of which has a light
   mode either) — flat fills instead of borders everywhere. The only line
   left in the whole UI is the hairline divider between list rows; every
   other distinction is made by background contrast alone. */
:root {
    --bg: #0c0c0c;
    --surface2: #2a2a2a;
    --surface2-hover: #3a3a3a;
    --surface2-active: #444;
    --divider: #222;
    --ink: #eeeeee;
    --ok: #7fd08a;
    --err: #e08080;
    --working: #e0c67f;
}

/* Hide scrollbars everywhere so this reads as edge-to-edge on both touch
   and desktop scrolling — scrolling itself still works, just no OS chrome. */
* { scrollbar-width: none; -ms-overflow-style: none; }
*::-webkit-scrollbar { display: none; }

html { -webkit-text-size-adjust: 100%; }

body {
    display: flex;
    flex-direction: column;
    align-items: center;
    min-height: 100dvh;
    margin: 0;
    padding: calc(1.5rem + env(safe-area-inset-top)) 1rem calc(2rem + env(safe-area-inset-bottom));
    font-family: monospace;
    background: var(--bg);
    color: var(--ink);
}

h1 {
    font-size: clamp(1.1rem, 3vw, 1.6rem);
    text-align: center;
    margin: 0 0 1rem;
}

.wrap { width: 100%; max-width: 760px; display: flex; flex-direction: column; gap: 1rem; }

input, select, button, textarea {
    font-family: monospace;
}

/* Flat fill, no border, square corners — the fill against the page bg is
   the only signal that this is an editable field. */
input, select, textarea {
    /* Never below 16px — iOS Safari auto-zooms on focus of any input under
       that threshold. This exact bug has already bitten the sibling apps
       once (db-audio-meta's index.css has the same fix with a note about
       it breaking silently), so it's non-negotiable here too. */
    font-size: 16px;
    background: var(--surface2);
    border: none;
    color: var(--ink);
    border-radius: 0;
    padding: 0.5em 0.6em;
}
input::placeholder, textarea::placeholder { opacity: 0.45; }

/* Buttons are a flat fill too, no border, square corners. `.primary` is the
   one solid ink-on-bg treatment, reserved for the single main action in a
   given section (Resolve, Unlock, Download & Save Selected) — everything
   else stays at the neutral surface2 fill. */
button {
    background: var(--surface2);
    border: none;
    color: var(--ink);
    border-radius: 0;
    padding: 0.55em 1em;
    font-size: 0.95rem;
    cursor: pointer;
    transition: background 0.1s;
    /* Removes the ~300ms tap delay on touch and suppresses the gray flash
       Android/Chrome would otherwise draw on tap. */
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}
button:hover { background: var(--surface2-hover); }
button:active { background: var(--surface2-active); }
button:disabled { opacity: 0.4; cursor: default; }
button:disabled:hover { background: var(--surface2); }

button.primary { background: var(--ink); color: var(--bg); font-weight: 600; }
button.primary:hover { background: var(--ink); opacity: 0.88; }
button.primary:active { opacity: 0.75; }
button.primary:disabled { background: var(--surface2); color: var(--ink); font-weight: 400; opacity: 0.4; }

button.active { background: var(--ink); color: var(--bg); }

.row { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; }
.row.stretch input { flex: 1; min-width: 200px; }

/* Fields always stack in a single column, full width — a paired 2-up
   layout was truncating longer values (album/genre names cut off mid-word);
   full width means nothing gets cut off, on any screen size. */
.field { display: flex; flex-direction: column; gap: 0.25rem; width: 100%; }
.field label { font-size: 0.72rem; opacity: 0.65; text-transform: uppercase; letter-spacing: 0.04em; }

.pillgroup { display: flex; gap: 0.3rem; flex-wrap: wrap; }
.pillgroup button { padding: 0.4em 0.8em; font-size: 0.85rem; }

/* Bigger, themed checkboxes — the native default is a tiny, unthemed touch
   target that's easy to miss on a phone. */
input[type="checkbox"] {
    width: 17px; height: 17px;
    accent-color: var(--ink);
    flex-shrink: 0;
}

/* --- Login overlay --- */
#login-overlay {
    position: fixed; inset: 0;
    background: var(--bg);
    display: flex; align-items: center; justify-content: center;
    padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
    z-index: 50;
}
#login-overlay.hidden { display: none; }
#login-card { width: min(90vw, 320px); display: flex; flex-direction: column; gap: 0.75rem; }
#login-card h2 { text-align: center; margin: 0 0 0.5rem; font-size: 1.1rem; }
#login-error { color: var(--err); font-size: 0.85rem; text-align: center; min-height: 1.1em; }

/* --- Resolve bar --- */
#resolve-bar input { flex: 1; min-width: 220px; }

#status-msg { font-size: 0.85rem; opacity: 0.75; min-height: 1.2em; }
#status-msg.error { color: var(--err); opacity: 1; }

/* --- Progress bar: pinned to the top of the scroll so overall batch
   status stays visible while scrolling a long track list. Flat fill, no
   border, square corners. --- */
#progress-wrap {
    position: sticky; top: 0; z-index: 20;
    background: var(--bg);
    padding: 0.4rem 0 0.6rem;
    display: flex; flex-direction: column; gap: 0.4rem;
}
#progress-status { font-size: 0.8rem; opacity: 0.85; text-align: center; }
#progress-track { height: 4px; width: 100%; background: var(--surface2); overflow: hidden; }
#progress-fill { height: 100%; width: 0%; background: var(--ink); transition: width 0.2s ease; }

/* --- Bulk toolbar --- */
#bulk-panel {
    display: flex; flex-direction: column; gap: 0.75rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--divider);
}
#bulk-panel .row { gap: 0.6rem; }
#bulk-panel .row.bulk-fields { flex-direction: column; align-items: stretch; }
#bulk-artwork-preview {
    width: 40px; height: 40px; border-radius: 0; object-fit: cover;
    background: var(--surface2); flex-shrink: 0;
}

#summary { font-size: 0.85rem; opacity: 0.75; }

/* --- Track list --- */
#tracks { display: flex; flex-direction: column; }

.track {
    display: flex; gap: 0.75rem; align-items: flex-start;
    padding: 0.9rem 0;
    border-bottom: 1px solid var(--divider);
}
.track:last-child { border-bottom: none; }
.track.excluded { opacity: 0.45; }

.track .artwork-wrap {
    position: relative; flex-shrink: 0; cursor: pointer;
    touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}
.track .artwork {
    width: 64px; height: 64px; border-radius: 0; object-fit: cover;
    background: var(--surface2); display: block;
}
.track .artwork-hint {
    position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    font-size: 0.65rem; text-align: center; color: #fff; background: rgba(0,0,0,0.55);
    opacity: 0; transition: opacity 0.15s;
}
.track .artwork-wrap:hover .artwork-hint { opacity: 1; }

/* ":hover" never fires on touch, so the full-cover hint above would be
   permanently undiscoverable on a phone — a small always-visible pencil
   badge substitutes for it there instead. */
.track .artwork-badge {
    display: none;
    position: absolute; bottom: 0; right: 0;
    width: 18px; height: 18px;
    align-items: center; justify-content: center;
    background: rgba(0,0,0,0.7); color: #fff;
    font-size: 11px; line-height: 1;
}
@media (hover: none) {
    .track .artwork-badge { display: flex; }
}

.track .fields { flex: 1; display: flex; flex-direction: column; gap: 0.6rem; min-width: 0; }
.track .fields-grid { display: flex; flex-direction: column; gap: 0.6rem; }

.track .meta-row { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.track .include-toggle { display: flex; align-items: center; gap: 0.4rem; font-size: 0.8rem; opacity: 0.85; }
.track .status { font-size: 0.78rem; opacity: 0.7; white-space: nowrap; }
.track .status.ok { color: var(--ok); opacity: 1; }
.track .status.error { color: var(--err); opacity: 1; }
.track .status.working { color: var(--working); opacity: 1; }

/* Per-track progress sliver — shows while a track is actively
   downloading/tagging/uploading; collapses to nothing otherwise. No
   percentage is available from the backend (one request per track, no
   streamed progress), so this is indeterminate rather than a real fill. */
.track .track-progress {
    height: 3px; width: 100%;
    background: var(--surface2); overflow: hidden;
    max-height: 0; opacity: 0; transition: max-height 0.15s, opacity 0.15s;
}
.track.working .track-progress { max-height: 3px; opacity: 1; margin-top: 0.2rem; }
.track .track-progress-fill {
    height: 100%; width: 40%;
    background: var(--working);
    animation: track-progress-indeterminate 1.1s ease-in-out infinite;
}
@keyframes track-progress-indeterminate {
    0% { transform: translateX(-100%); }
    100% { transform: translateX(250%); }
}

.hidden { display: none !important; }

@media (max-width: 600px) {
    /* Format-pills + "Apply to selected" is two separate action groups —
       side by side they don't have room and the pills spill over the
       button, so stack them instead. */
    #bulk-panel .format-row { flex-direction: column; align-items: stretch; }
    #bulk-panel .format-row > button { width: 100%; }

    button { padding: 0.65em 1em; }
    .pillgroup button { padding: 0.55em 0.8em; }
}
