/* =====================================================================
   webvm.css — single self-contained stylesheet for Web VM.
   Replaces main.css, sidebar-themes.css, mobile.css.

   Class naming: every class is prefixed `wvm-`. Bootstrap 4 classes
   are still used inside the modals (.modal, .form-control, .form-group)
   because the modal markup in main.html uses Bootstrap modal triggers.
   We restyle Bootstrap modals via id selectors.

   IDs preserved (used by /js/script.js):
     #newvm  #folders  #Old  #Work  #Family  #Friends
     #emailModal  #configModal  #securityModal  #greetingsModal
     #fID  #mID  #emailvm  #emailSent  #emailError  #send-button
     #configvm  #configSaved  #configError  #save-button  #emailID
     #autodelID  #announceonlyID
     #securityvm  #securitySaved  #securityError  #security-button
     #newPIN1ID  #newPIN2ID  #tooshortError  #nomatchError
     #greetingsvm  #greetingsSaved  #greetingsError  #saveAudioBtn1
     #greetings-button  #studioAvailable  #studioUnavailable
     #current-greetingsID  #greetingsID  #delID  #audioModeContent1
     #sysError  (added — script.js's deleteMultiVM expects this)
   ===================================================================== */

/* =====================================================================
   1. Design tokens
   ===================================================================== */
:root {
	--wvm-brand:        #2563eb;
	--wvm-brand-h:      #1d4ed8;
	--wvm-brand-soft:   #dbeafe;

	--wvm-green:        #16a34a;
	--wvm-green-d:      #15803d;
	--wvm-green-soft:   #dcfce7;

	--wvm-red:          #dc2626;
	--wvm-red-d:        #b91c1c;
	--wvm-red-soft:     #fee2e2;

	--wvm-ink:          #1c1f24;
	--wvm-ink-2:        #5f5e5a;
	--wvm-ink-3:        #888780;

	--wvm-bg:           #fafaf7;
	--wvm-bg2:          #f1efe8;
	--wvm-surface:      #ffffff;

	--wvm-line:         rgba(0, 0, 0, 0.08);
	--wvm-line-strong:  rgba(0, 0, 0, 0.16);

	--wvm-side-bg:      #1e293b;
	--wvm-side-line:    rgba(255, 255, 255, 0.06);
	--wvm-side-line-2:  rgba(255, 255, 255, 0.10);
	--wvm-side-fg:      rgba(255, 255, 255, 0.70);
	--wvm-side-fg-mute: rgba(255, 255, 255, 0.40);

	--wvm-radius-sm: 7px;
	--wvm-radius:    10px;
	--wvm-radius-lg: 14px;
}

/* =====================================================================
   2. Reset & base
   ===================================================================== */
* { box-sizing: border-box; }
html, body {
	margin: 0;
	padding: 0;
	background: radial-gradient(65% 55% at 15% 18%, rgba(226, 244, 252, 0), transparent 60%) fixed,
	            radial-gradient(70% 60% at 88% 88%, rgba(127, 166, 251, 0), transparent 65%),
	            linear-gradient(rgba(245, 249, 252, 0.15), rgba(232, 238, 246, 0.31)) !important;
	color: var(--wvm-ink);
	font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text",
	             "Segoe UI", system-ui, sans-serif;
	font-size: 14px;
	line-height: 1.5;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}
a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; }

/* =====================================================================
   3. Page layout — sidebar (fixed left) + main content (right)
   ===================================================================== */
.wvm-app {
	min-height: 100vh;
	display: flex;
}

/* FOUC prevention. The sidebar is hardcoded in main.html so it renders
   instantly; the message list is rebuilt by webvm.js from the
   server-rendered <table>. We hide the main column until JS adds
   .wvm-ready to <html>. The sidebar stays visible the whole time
   so the user sees instant context. */
html:not(.wvm-ready) .wvm-main { visibility: hidden; }
html.wvm-ready .wvm-main { visibility: visible; }

/* =====================================================================
   4. Sidebar
   ===================================================================== */
.wvm-side {
	background: var(--wvm-side-bg);
	color: var(--wvm-side-fg);
	width: 260px;
	height: 100vh;
	/* iOS Safari includes the dynamic URL bar/home indicator in 100vh,
	   which pushes the sidebar foot below the visible area. dvh
	   (dynamic viewport height) accounts for the actual visible
	   region. Modern Safari supports it; older browsers fall back to
	   the 100vh declaration above. */
	height: 100dvh;
	position: fixed;
	top: 0;
	left: 0;
	z-index: 100;
	display: flex;
	flex-direction: column;
	overflow: hidden;
	border-right: 1px solid var(--wvm-side-line);
}
.wvm-side-body {
	flex: 1;
	overflow-y: auto;
	padding: 0 12px 12px;
	min-height: 0;
}

/* --- Brand row ----------------------------------------------------- */
/* Logo + product name at the very top of the sidebar. Sits above
   the user block and the section divider. The logo is the same
   asset used for the favicon and the login page so the visual
   identity stays consistent everywhere. */
.wvm-side-brand {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 18px 6px 14px;
	min-width: 0;
}
/* Logo: 28px. The source PNG is now a proper transparent-corners
   asset (the blue circle on a transparent background), so no
   border-radius clipping needed — the corners just show through.
   Doubled selector + !important on dimensions defends against
   Bootstrap's `img { max-width: 100% }` and any other img sizing
   from the legacy stylesheets. */
nav#sidebar .wvm-side-brand-logo,
.wvm-side-brand .wvm-side-brand-logo {
	width: 28px !important;
	height: 28px !important;
	max-width: 28px !important;
	max-height: 28px !important;
	min-width: 28px !important;
	flex-shrink: 0;
	flex-grow: 0;
	display: block;
	object-fit: contain;
}
.wvm-side-brand-name {
	font-size: 16px;
	font-weight: 600;
	letter-spacing: -0.01em;
	color: var(--wvm-side-fg);
}
/* Close button — hidden on desktop, shown only when the sidebar
   is rendered as a mobile drawer. Sits at the right end of the
   brand row (margin-left: auto pushes it). Reuses data-act
   "mobile-menu" on the button itself so the existing JS toggle
   handler closes the drawer; no new wiring required. */
.wvm-side-close {
	display: none;            /* hidden on desktop */
	margin-left: auto;
	width: 34px;
	height: 34px;
	border-radius: 8px;
	background: transparent;
	border: 1px solid var(--wvm-side-line);
	color: var(--wvm-side-fg);
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	padding: 0;
	cursor: pointer;
	-webkit-appearance: none;
	appearance: none;
	-webkit-tap-highlight-color: transparent;
	transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.wvm-side-close:hover {
	background: rgba(255, 255, 255, 0.06);
	color: white;
	border-color: var(--wvm-side-line-2);
}
.wvm-side-close:active { transform: scale(0.96); }
/* Explicit stroke on the SVG so it renders reliably across browsers
   even if currentColor is overridden somewhere. */
.wvm-side-close svg {
	width: 16px;
	height: 16px;
	display: block;
	stroke: currentColor;
	fill: none;
}

/* --- User row ------------------------------------------------------ */
.wvm-side-user {
	display: flex;
	align-items: center;
	gap: 10px;
	/* Reduced top padding because the brand row + divider already
	   give the user block visual breathing room above. */
	padding: 14px 6px 14px;
}
.wvm-side-user-pic {
	width: 36px;
	height: 36px;
	border-radius: 50%;
	overflow: hidden;
	flex-shrink: 0;
	background: rgba(255, 255, 255, 0.08);
}
.wvm-side-user-pic img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
.wvm-side-user-info {
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 1px;
}
.wvm-side-user-name {
	color: white;
	font-size: 13px;
	font-weight: 600;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.wvm-side-user-role {
	color: var(--wvm-side-fg-mute);
	font-size: 11px;
}
.wvm-side-user-status {
	color: var(--wvm-side-fg-mute);
	font-size: 11px;
	display: flex;
	align-items: center;
	gap: 5px;
}
.wvm-side-user-status::before {
	content: '';
	width: 7px;
	height: 7px;
	border-radius: 50%;
	background: var(--wvm-green);
}

/* --- Section header ----------------------------------------------- */
.wvm-side-divider {
	border-top: 1px solid var(--wvm-side-line-2);
	margin: 0 -2px 2px;
}
.wvm-side-section {
	font-size: 10px;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--wvm-side-fg-mute);
	padding: 14px 10px 6px;
}

/* --- Nav links (top-level + accordion trigger) -------------------- */
.wvm-side-link {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 9px 10px;
	border-radius: 9px;
	font-size: 13px;
	color: var(--wvm-side-fg);
	font-weight: 500;
	text-decoration: none;
	transition: background 0.12s, color 0.12s;
	margin-bottom: 1px;
	min-height: 40px;
	border: none;
	background: transparent;
	width: 100%;
	text-align: left;
}
.wvm-side-link:hover {
	background: rgba(255, 255, 255, 0.06);
	color: white;
}
.wvm-side-link.is-active {
	background: var(--wvm-brand);
	color: white;
	box-shadow: 0 1px 3px rgba(37, 99, 235, 0.4);
}
.wvm-side-link.is-open {
	background: rgba(255, 255, 255, 0.04);
	color: white;
}

.wvm-side-ico {
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 26px;
	height: 26px;
	border-radius: var(--wvm-radius-sm);
	background: rgba(255, 255, 255, 0.06);
	color: var(--wvm-side-fg);
	transition: background 0.12s, color 0.12s;
}
.wvm-side-ico svg { width: 14px; height: 14px; }
.wvm-side-link:hover .wvm-side-ico {
	background: rgba(255, 255, 255, 0.10);
	color: white;
}
.wvm-side-link.is-active .wvm-side-ico {
	background: rgba(255, 255, 255, 0.18);
	color: white;
}
.wvm-side-link.is-open .wvm-side-ico {
	background: rgba(255, 255, 255, 0.10);
	color: white;
}
.wvm-side-label {
	flex: 1;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* --- Trailing pill / chevron column (aligns badges vertically) ---- */
/* Unread indicator dot. Replaces the previous number-pill — the
   exact unread count is no longer shown in the sidebar; just a
   binary "you have unread here" signal. The total count is in
   .wvm-side-grand to the right. font-size: 0 hides the number text
   the JS still writes to the element (we keep the data-count
   attribute logic intact). */
.wvm-side-pill {
	width: 8px;
	height: 8px;
	min-width: 0;
	padding: 0;
	border-radius: 50%;
	background: var(--wvm-green);
	font-size: 0;
	line-height: 0;
	flex-shrink: 0;
	/* Visually sit before the total count even though DOM order
	   has grand before pill — order: 1 / 2 puts the dot first. */
	order: 1;
	margin-right: 6px;
}
.wvm-side-pill--green {
	background: #43f283 !important;
}
/* Nudge the New Messages dot 1px right so it aligns vertically with
   the folder rollup dot beneath it. The two rows have slightly
   different trailing-element widths (.wvm-side-nav-chev is 12px,
   .wvm-side-chev is 14px) so the pill ends up 1px off; this fixes
   the alignment without touching the folder dot. */
#newvm .wvm-side-pill {
	margin-right: 5px;
	margin-left: 1px;
}
/* When this row is the active page, keep the dot green to match
   the other folders — the brand-blue active background already
   provides plenty of contrast against the green dot. */
/* Hide the dot when there are no unread messages */
.wvm-side-pill[data-count="0"] {
	display: none;
}
/* Total message count, sits at the far right of every row.
   Bumped to 12px (from 11) for legibility. tabular-nums so the
   numbers stack vertically in a clean column across rows. */
.wvm-side-grand {
	font-size: 14px;
	font-weight: 500;
	color: rgba(255, 255, 255, 0.45);
	font-variant-numeric: tabular-nums;
	flex-shrink: 0;
	order: 2;
}
.wvm-side-grand[data-grand=""] {
	display: none;
}
.wvm-side-link.is-active .wvm-side-grand,
.wvm-side-sub.is-active .wvm-side-grand {
	color: rgba(255, 255, 255, 0.85);
}
/* Roll-up dot on the Folders accordion trigger — visible when
   accordion is CLOSED so user sees there's unread inside without
   expanding. Hidden when open because per-subfolder dots are
   already shown. */
.wvm-side-link.is-open .wvm-side-pill--rollup {
	display: none !important;
}
.wvm-side-trail {
	display: inline-block;
	width: 14px;
	margin-left: 4px;
	flex-shrink: 0;
	order: 3;
}
/* Navigation chevron — sits at the far right of nav rows (New
   Messages + each folder) to signal "tap to open this view". Same
   convention as iOS/Settings list rows. Subtle: small, dimmed
   colour, no animation. The active row's chevron lifts to white
   so it remains visible against the brand-blue background. */
.wvm-side-nav-chev {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 12px;
	height: 12px;
	margin-left: 8px;
	flex-shrink: 0;
	color: rgba(255, 255, 255, 0.30);
	order: 3;
}
.wvm-side-nav-chev svg { width: 12px; height: 12px; }
.wvm-side-link:hover .wvm-side-nav-chev,
.wvm-side-sub:hover .wvm-side-nav-chev {
	color: rgba(255, 255, 255, 0.65);
}
.wvm-side-link.is-active .wvm-side-nav-chev,
.wvm-side-sub.is-active .wvm-side-nav-chev {
	color: rgba(255, 255, 255, 0.85);
}
.wvm-side-chev {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 14px;
	height: 14px;
	margin-left: 4px;
	flex-shrink: 0;
	color: var(--wvm-side-fg-mute);
	/* Same order tier as .wvm-side-nav-chev so the rollup pill
	   (order: 1) sits LEFT of the chevron, matching the layout
	   of every other nav row. */
	order: 3;
	transition: transform 0.2s, color 0.2s;
}
.wvm-side-chev svg { width: 12px; height: 12px; }
.wvm-side-link.is-open .wvm-side-chev {
	transform: rotate(180deg);
	color: white;
}
/* On folder pages the accordion is pinned (cannot be toggled). The
   chevron implies clickability so we hide it — the open state alone
   communicates the breadcrumb. */
.wvm-side-link.is-pinned .wvm-side-chev {
	display: none;
}

/* --- Folders accordion body --------------------------------------- */
.wvm-side-acc {
	display: none;
	padding: 4px 0 6px 8px;
	margin: 2px 0 4px;
	position: relative;
}
.wvm-side-acc.is-open { display: block; }
.wvm-side-acc::before {
	content: '';
	position: absolute;
	left: 22px;
	top: 6px;
	bottom: 6px;
	width: 2px;
	background: rgba(255, 255, 255, 0.08);
	border-radius: 2px;
}

/* --- Sub-link (Old / Work / Family / Friends) --------------------- */
.wvm-side-sub {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 8px 10px 8px 32px;
	border-radius: 9px;
	font-size: 13px;
	color: var(--wvm-side-fg);
	font-weight: 500;
	text-decoration: none;
	transition: background 0.12s, color 0.12s;
	margin-bottom: 1px;
	min-height: 36px;
	position: relative;
}
.wvm-side-sub:hover {
	background: rgba(255, 255, 255, 0.06);
	color: white;
}
.wvm-side-sub.is-active {
	background: var(--wvm-brand);
	color: white;
}
.wvm-side-sub::before {
	/* Tiny dash that points to the guide line */
	content: '';
	position: absolute;
	left: 18px;
	top: 50%;
	transform: translateY(-50%);
	width: 10px;
	height: 2px;
	background: rgba(255, 255, 255, 0.20);
	border-radius: 2px;
}
.wvm-side-sub.is-active::before {
	background: rgba(255, 255, 255, 0.50);
}
.wvm-side-sub-label {
	flex: 1;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* --- Footer -------------------------------------------------------- */
.wvm-side-foot {
	flex-shrink: 0;
	padding: 8px 10px;
	/* iPhones with a home indicator have a safe-area inset at the
	   bottom; honour it so the footer buttons don't sit under the
	   indicator. Falls back to 0 on devices without one. */
	padding-bottom: max(8px, env(safe-area-inset-bottom));
	display: flex;
	gap: 6px;
	border-top: 1px solid var(--wvm-side-line-2);
}
.wvm-side-foot-btn {
	flex: 1;
	height: 36px;
	border-radius: var(--wvm-radius-sm);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	color: var(--wvm-side-fg);
	background: transparent;
	border: none;
	transition: background 0.12s, color 0.12s;
	text-decoration: none;
}
.wvm-side-foot-btn:hover {
	background: rgba(255, 255, 255, 0.08);
	color: white;
}
.wvm-side-foot-btn svg { width: 18px; height: 18px; }

/* =====================================================================
   5. Main content area (next to sidebar)
   ===================================================================== */
.wvm-main {
	flex: 1;
	margin-left: 260px;
	min-height: 100vh;
	display: flex;
	flex-direction: column;
	background: transparent;
}

/* Hide the legacy server-rendered title; we render our own page head */
.wvm-page-title-legacy { display: none; }

/* Where vmwebapi.cgi injects its <table class="table">. We hide
   the table on first paint; webvm.js rebuilds it into .wvm-list and
   reveals once ready. */
.wvm-server-content { /* host */ }
.wvm-server-content > table.table { display: none; }
.wvm-server-content > button.vmg-btn-danger { display: none; }

/* Page header sits ABOVE the list card. It uses the off-white page
   background (no fill of its own) so the user sees a single layered
   surface. The list card below provides its own visual boundary. */
.wvm-head {
	padding: 24px 28px 6px;
	background: transparent;
	display: flex;
	justify-content: space-between;
	align-items: flex-start;
	gap: 16px;
}
.wvm-head-titles { min-width: 0; }
.wvm-head h1 {
	margin: 0;
	font-size: 22px;
	font-weight: 600;
	letter-spacing: -0.01em;
	color: var(--wvm-ink);
}
.wvm-head-sub {
	font-size: 13px;
	color: var(--wvm-ink-2);
	margin-top: 4px;
}

/* Inverted "Select" tick button (matches mobile style) */
.wvm-head-select {
	width: 38px;
	height: 38px;
	border-radius: 9px;
	background: var(--wvm-surface);
	border: 1px solid var(--wvm-line);
	color: var(--wvm-ink-2);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	transition: all 0.12s;
	padding: 0;
}
.wvm-head-select:hover {
	background: var(--wvm-bg2);
	border-color: var(--wvm-line-strong);
	color: var(--wvm-ink);
}
.wvm-head-select svg { width: 16px; height: 16px; }
.wvm-app.is-select-mode .wvm-head-select { display: none; }

/* =====================================================================
   6. Action bar (search row OR select-mode bulk-actions row)
   ===================================================================== */
.wvm-bar {
	padding: 12px 28px 16px;
	display: flex;
	gap: 10px;
	align-items: center;
	background: transparent;
}
.wvm-bar.is-select {
	background: var(--wvm-side-bg);
	color: white;
	border-bottom: none;
	border-radius: 12px;
	margin: 0 24px;
	padding: 12px 20px;
}
/* Hide the default bar in select mode and vice versa */
.wvm-app.is-select-mode .wvm-bar.is-default { display: none; }
.wvm-app:not(.is-select-mode) .wvm-bar.is-select { display: none; }

/* Mobile folder dropdown row (shown only on mobile) */
.wvm-mobile-folder-row { display: none; }

.wvm-search {
	flex: 1;
	display: flex;
	align-items: center;
	gap: 8px;
	background: var(--wvm-surface);
	border: 1px solid var(--wvm-line);
	border-radius: var(--wvm-radius);
	padding: 0 12px;
	height: 38px;
	color: var(--wvm-ink-2);
	box-shadow: 0 1px 2px rgba(15, 20, 25, 0.04),
	            0 2px 6px rgba(15, 20, 25, 0.04);
	transition: all 0.12s;
}
.wvm-search:focus-within {
	border-color: var(--wvm-brand);
	background: var(--wvm-surface);
	box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.12);
}
.wvm-search > svg {
	width: 14px;
	height: 14px;
	color: var(--wvm-ink-3);
	flex-shrink: 0;
}
.wvm-search input {
	flex: 1;
	border: none;
	background: transparent;
	outline: none;
	font-size: 13px;
	color: var(--wvm-ink);
	font-family: inherit;
	min-width: 0;
	padding: 0;
}
.wvm-search input::placeholder { color: var(--wvm-ink-3); }
.wvm-search-clear {
	width: 22px;
	height: 22px;
	border-radius: 50%;
	border: none;
	background: var(--wvm-bg2);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	color: var(--wvm-ink-2);
	flex-shrink: 0;
	padding: 0;
}
.wvm-search-clear svg { width: 10px; height: 10px; }

/* Brand-blue Search button (right of the input on desktop) */
.wvm-btn-primary {
	background: var(--wvm-brand);
	color: white;
	border: none;
	padding: 9px 16px;
	border-radius: var(--wvm-radius);
	font-size: 13px;
	font-weight: 600;
	display: inline-flex;
	align-items: center;
	gap: 8px;
	box-shadow: 0 1px 3px rgba(37, 99, 235, 0.3);
	transition: all 0.12s;
}
.wvm-btn-primary:hover {
	background: var(--wvm-brand-h);
	box-shadow: 0 2px 8px rgba(37, 99, 235, 0.4);
}
.wvm-btn-primary svg { width: 14px; height: 14px; }

/* Select-mode bar elements */
.wvm-select-cb {
	width: 22px;
	height: 22px;
	border-radius: 5px;
	border: 1.5px solid rgba(255, 255, 255, 0.5);
	background: transparent;
	color: white;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	padding: 0;
	transition: all 0.12s;
}
.wvm-select-cb:hover { border-color: white; }
.wvm-select-cb.is-checked,
.wvm-select-cb.is-partial {
	background: var(--wvm-brand);
	border-color: var(--wvm-brand);
}
.wvm-select-cb svg { width: 11px; height: 11px; }
.wvm-select-count {
	font-size: 13px;
	font-weight: 500;
	color: white;
	margin-left: 8px;
}
.wvm-bulk {
	padding: 7px 14px;
	background: transparent;
	color: white;
	border: 1px solid rgba(255, 255, 255, 0.18);
	border-radius: var(--wvm-radius-sm);
	font-size: 13px;
	font-weight: 500;
	display: inline-flex;
	align-items: center;
	gap: 7px;
	transition: all 0.12s;
}
.wvm-bulk:hover:not(:disabled) {
	background: rgba(255, 255, 255, 0.10);
	border-color: rgba(255, 255, 255, 0.40);
}
.wvm-bulk:disabled {
	color: rgba(255, 255, 255, 0.35);
	border-color: rgba(255, 255, 255, 0.08);
	cursor: not-allowed;
}
.wvm-bulk.is-danger:not(:disabled) {
	background: var(--wvm-red);
	border-color: var(--wvm-red);
}
.wvm-bulk.is-danger:not(:disabled):hover {
	background: var(--wvm-red-d);
	border-color: var(--wvm-red-d);
}
.wvm-bulk svg { width: 13px; height: 13px; }
/* Icon-only Delete — drops the text label, square padding so it
   reads as an icon button. Aria-label preserves accessibility. */
.wvm-bulk--icon {
	padding: 7px 10px;
	gap: 0;
}
.wvm-bulk--icon svg { width: 14px; height: 14px; }
.wvm-cancel {
	padding: 7px 14px;
	background: transparent;
	color: white;
	border: 1px solid rgba(255, 255, 255, 0.25);
	border-radius: var(--wvm-radius-sm);
	font-size: 13px;
	font-weight: 500;
	margin-left: 4px;
}
/* Icon-only Cancel (X) — same square treatment. Familiar
   "dismiss" affordance, frees room for the labelled action
   buttons. */
.wvm-cancel--icon {
	padding: 7px 10px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}
.wvm-cancel--icon svg { width: 14px; height: 14px; }
.wvm-cancel:hover {
	background: rgba(255, 255, 255, 0.10);
	border-color: rgba(255, 255, 255, 0.50);
}

/* =====================================================================
   New-message banner (shown when polling detects a new message)
   ===================================================================== */
.wvm-newmsg-banner {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 12px 20px;
	margin: 16px 24px 0;
	background: var(--wvm-green-soft);
	color: var(--wvm-green-d);
	border: 1px solid rgba(22, 163, 74, 0.18);
	border-radius: var(--wvm-radius-lg);
	box-shadow: 0 1px 2px rgba(15, 20, 25, 0.04),
	            0 4px 12px rgba(22, 163, 74, 0.10);
	font-size: 13px;
	font-weight: 500;
	animation: wvm-newmsg-slide 0.25s ease;
}
.wvm-newmsg-banner svg {
	width: 16px;
	height: 16px;
	flex-shrink: 0;
}
.wvm-newmsg-text { flex: 1; }
.wvm-newmsg-refresh {
	border: none;
	background: var(--wvm-green-d);
	color: white;
	padding: 6px 14px;
	border-radius: 8px;
	font-size: 12px;
	font-weight: 600;
	font-family: inherit;
	cursor: pointer;
	transition: background 0.12s;
}
.wvm-newmsg-refresh:hover { background: #166534; }
@keyframes wvm-newmsg-slide {
	from { transform: translateY(-8px); opacity: 0; }
	to   { transform: translateY(0); opacity: 1; }
}
@media (max-width: 768px) {
	.wvm-newmsg-banner { padding: 10px 14px; margin: 8px 14px 0; }
}

/* =====================================================================
   New-message banner end
   ===================================================================== */

/* =====================================================================
   7. Message list
   ===================================================================== */
/* Container for the message list. Previously this was a single white
   card wrapping all rows; now each row is its own card so the wrapper
   is just a positioning container. No bg, no border, no shadow,
   no overflow:hidden (would clip the per-row shadows). */
.wvm-list {
	flex: 1;
	background: transparent;
	margin: 16px 24px 24px;
	border-radius: 0;
	border: none;
	box-shadow: none;
	overflow: visible;
}
/* Day separator floats on the gradient page bg between the row cards.
   No surface, no top/bottom borders — just a label. */
.wvm-day {
	padding: 16px 12px 8px;
	font-size: 11px;
	color: var(--wvm-ink-3);
	text-transform: uppercase;
	letter-spacing: 0.06em;
	font-weight: 600;
	background: transparent;
	border: none;
	display: flex;
	align-items: center;
	gap: 10px;
}
.wvm-day::before {
	content: "";
	display: inline-block;
	width: 3px;
	height: 12px;
	background: var(--wvm-brand);
	border-radius: 2px;
	opacity: 0.6;
}
.wvm-day:first-child { padding-top: 4px; }

/* Each row is its own card. The wrapper .wvm-list no longer paints
   a surface, so each row provides its own white fill, rounded corners,
   border, and shadow. Layered shadow sells the lift against the
   gradient page bg. Margin-bottom creates the gap between rows. */
.wvm-row {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	column-gap: 14px;
	row-gap: 0;
	padding: 14px 24px;
	background: var(--wvm-surface);
	border: 1px solid var(--wvm-line);
	border-radius: var(--wvm-radius-lg);
	margin-bottom: 8px;
	box-shadow: 0 1px 2px rgba(15, 20, 25, 0.04),
	            0 4px 12px rgba(15, 20, 25, 0.06);
	transition: background 0.12s, box-shadow 0.12s, transform 0.06s;
}
.wvm-row:last-child { margin-bottom: 0; }
.wvm-row:hover {
	background: #fafaf7;
	box-shadow: 0 1px 2px rgba(15, 20, 25, 0.06),
	            0 6px 20px rgba(15, 20, 25, 0.10);
}
.wvm-row.is-unread { background: #f5f9ff; }
.wvm-row.is-selected {
	/* Selection is indicated by the checkbox tick alone — keep the row neutral
	   so a long list doesn't turn into a wall of blue when "Select all" is used. */
}

/* Unread dot (default mode) — green */
.wvm-row-dot {
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: var(--wvm-green);
	flex-shrink: 0;
}
.wvm-row:not(.is-unread) .wvm-row-dot { background: transparent; }

/* Coloured initials avatar — gives every row a focal point and a bit
   of personality without going maximalist. The colour is computed
   from the caller name so the same caller always gets the same chip. */
.wvm-row-avatar {
	width: 36px;
	height: 36px;
	border-radius: 50%;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	font-size: 13px;
	font-weight: 600;
	flex-shrink: 0;
	letter-spacing: 0.02em;
	user-select: none;
}
.wvm-app.is-select-mode .wvm-row-avatar { display: none; }

/* Square checkbox (select mode) */
.wvm-row-cb {
	width: 22px;
	height: 22px;
	border-radius: 5px;
	border: 1.5px solid #d3d1c7;
	background: var(--wvm-surface);
	display: none;
	align-items: center;
	justify-content: center;
	color: white;
	flex-shrink: 0;
	padding: 0;
	transition: border-color 0.15s, background 0.15s;
}
/* In select mode, unchecked checkboxes get a brand-blue border so
   the user sees the affordance — "this is waiting for me to tap".
   The checked state below overrides this with a fully-filled tile. */
.wvm-app.is-select-mode .wvm-row-cb:not(.is-on) {
	border-color: var(--wvm-brand);
}
.wvm-row-cb.is-on {
	background: var(--wvm-brand);
	border-color: var(--wvm-brand);
}
.wvm-row-cb svg { width: 12px; height: 12px; }
.wvm-app.is-select-mode .wvm-row-dot { display: none; }
.wvm-app.is-select-mode .wvm-row-cb { display: inline-flex; }

.wvm-row-info { flex: 1; min-width: 0; }
.wvm-row-name {
	font-size: 14px;
	font-weight: 500;
	color: var(--wvm-ink);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.wvm-row:not(.is-unread) .wvm-row-name {
	font-weight: 400;
	color: var(--wvm-ink-2);
}
.wvm-row-meta {
	font-size: 12px;
	color: var(--wvm-ink-3);
	margin-top: 2px;
}
/* Default (desktop): show only the meta-name (the contact name or
   "Unknown caller"). Mobile media query reveals separators + time
   + duration inline and right-aligns the line. */
.wvm-row-meta-sep,
.wvm-row-meta-time,
.wvm-row-meta-dur { display: none; }
/* Right column on desktop: time stacked above duration. On mobile
   this whole column is hidden (meta line above carries both). */
.wvm-row-when {
	font-size: 12px;
	color: var(--wvm-ink-3);
	white-space: nowrap;
	text-align: right;
	flex-shrink: 0;
}
.wvm-row-when-time { line-height: 1.3; }
.wvm-row-when-dur {
	font-size: 11px;
	color: var(--wvm-ink-3);
	opacity: 0.85;
	margin-top: 1px;
}

/* Inline play button — pastel-blue circle + brand-blue when playing */
.wvm-row-play {
	width: 36px;
	height: 36px;
	border-radius: 50%;
	background: var(--wvm-brand-soft);
	color: var(--wvm-brand);
	border: none;
	outline: none;
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	transition: background 0.12s, color 0.12s;
	padding: 0;
	-webkit-appearance: none;
	appearance: none;
	-webkit-tap-highlight-color: transparent;
}
.wvm-row-play:focus,
.wvm-row-play:focus-visible,
.wvm-row-play:active { outline: none; box-shadow: none; }
.wvm-row-play.is-playing {
	background: var(--wvm-brand);
	color: white;
}
/* Inside the open player panel, always render as brand-blue regardless
   of read state — keeps the player's primary control consistent and
   stops it falling back to the muted tan tile. */
.wvm-row-player .wvm-row-play {
	background: var(--wvm-brand);
	color: white;
}
.wvm-row:not(.is-unread) .wvm-row-play {
	background: var(--wvm-bg2);
	color: var(--wvm-ink-2);
}
@media (hover: hover) {
	.wvm-row-play:hover {
		background: var(--wvm-brand);
		color: white;
	}
	.wvm-row-player .wvm-row-play:hover {
		background: var(--wvm-brand-d, var(--wvm-brand));
		color: white;
	}
	.wvm-row:not(.is-unread) .wvm-row-play:hover {
		background: var(--wvm-ink-3);
		color: white;
	}
}
.wvm-row-play svg { width: 12px; height: 12px; }

/* =====================================================================
   Row toggle (chevron) + kebab menu
   =====================================================================
   Chevron toggle: replaces the old play button on each row. Tapping
   it opens/closes the inline player accordion. Rotates 90deg via
   CSS when row is .is-playing so it points down — standard
   accordion idiom.

   Kebab menu: consolidates Forward / Move / Delete into one dropdown
   accessed via a 3-dots button. Click-outside-to-close handled by
   document-level listener in JS.
===================================================================== */
.wvm-row-toggle {
	width: 32px;
	height: 32px;
	border-radius: 50%;
	background: var(--wvm-brand-soft);
	border: none;
	color: var(--wvm-brand);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	flex-shrink: 0;
	transition: background 0.12s, color 0.12s;
	padding: 0;
	-webkit-appearance: none;
	appearance: none;
	-webkit-tap-highlight-color: transparent;
}
@media (hover: hover) {
	.wvm-row-toggle:hover {
		background: var(--wvm-brand);
		color: white;
	}
}
.wvm-row-toggle svg {
	width: 12px;
	height: 12px;
	display: block;
	transition: transform 0.18s ease;
}
.wvm-row.is-playing .wvm-row-toggle {
	background: var(--wvm-brand);
	color: white;
}
.wvm-row.is-playing .wvm-row-toggle svg { transform: rotate(90deg); }
.wvm-app.is-select-mode .wvm-row-toggle { display: none; }

.wvm-row-kebab {
	width: 32px;
	height: 32px;
	border-radius: 50%;
	background: transparent;
	border: none;
	color: var(--wvm-ink-2);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	flex-shrink: 0;
	transition: background 0.12s, color 0.12s;
	padding: 0;
	-webkit-appearance: none;
	appearance: none;
	-webkit-tap-highlight-color: transparent;
}
@media (hover: hover) {
	.wvm-row-kebab:hover {
		background: var(--wvm-bg2);
		color: var(--wvm-ink);
	}
}
.wvm-row-kebab svg {
	width: 16px;
	height: 16px;
	display: block;
	stroke: none;
	fill: currentColor;
}
.wvm-app.is-select-mode .wvm-row-menu-wrap { display: none; }

.wvm-row-menu-wrap {
	position: relative;
	flex-shrink: 0;
}
/* The dropdown panel — absolute relative to the wrap so it floats
   over the rest of the layout. Opens below the kebab by default;
   on mobile we shift it left so it doesn't overflow off-screen. */
.wvm-row-menu {
	position: absolute;
	top: calc(100% + 4px);
	right: 0;
	min-width: 180px;
	background: var(--wvm-surface);
	border: 1px solid var(--wvm-line);
	border-radius: 10px;
	box-shadow: 0 6px 20px rgba(15, 20, 25, 0.10),
	            0 1px 3px rgba(15, 20, 25, 0.06);
	padding: 6px;
	z-index: 50;
	display: none;
}
.wvm-row-menu-wrap.is-open .wvm-row-menu { display: block; }
.wvm-row-menu-item {
	display: flex;
	align-items: center;
	gap: 10px;
	width: 100%;
	padding: 8px 12px;
	border-radius: 6px;
	border: none;
	background: transparent;
	color: var(--wvm-ink);
	font-size: 13px;
	font-family: inherit;
	cursor: pointer;
	text-align: left;
	-webkit-appearance: none;
	appearance: none;
}
.wvm-row-menu-item:hover { background: var(--wvm-bg2); }
.wvm-row-menu-item.is-danger { color: var(--wvm-red-d); }
.wvm-row-menu-item.is-danger:hover { background: var(--wvm-red-soft); }
.wvm-row-menu-item svg {
	width: 14px;
	height: 14px;
	flex-shrink: 0;
}
.wvm-row-menu-divider {
	height: 1px;
	background: var(--wvm-line);
	margin: 4px -2px;
}

/* Per-row action buttons (kept for legacy/select-mode references) */
.wvm-row-actions {
	display: flex;
	gap: 4px;
	flex-shrink: 0;
}
.wvm-app.is-select-mode .wvm-row-actions,
.wvm-app.is-select-mode .wvm-row-play { display: none; }

.wvm-row-iconbtn {
	width: 32px;
	height: 32px;
	border-radius: 8px;
	border: 1px solid var(--wvm-line);
	background: var(--wvm-surface);
	color: var(--wvm-ink-2);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	transition: all 0.12s;
	padding: 0;
}
.wvm-row-iconbtn:hover {
	background: var(--wvm-bg2);
	color: var(--wvm-ink);
	border-color: var(--wvm-line-strong);
}
.wvm-row-iconbtn.is-danger:hover {
	background: var(--wvm-red-soft);
	color: var(--wvm-red-d);
	border-color: var(--wvm-red-soft);
}
.wvm-row-iconbtn svg { width: 12px; height: 12px; }

/* Hidden audio + hidden mtf select (preserved for backend contracts) */
.wvm-row audio { display: none; }
/* Legacy mtf select — vmwebapi.cgi emits <select id="mtfXXX"> with
   an INLINE style="display: inline; ..." that beats external CSS.
   We use !important to force it hidden — the select still exists in
   the DOM (script.js's moveMessage reads its .value as the destination
   folder) but it's invisible to the user. */
.wvm-row select[id^="mtf"] { display: none !important; }

/* =====================================================================
   8. Inline audio player (per row)
   =====================================================================
   When .wvm-row gets .is-playing, the player panel slides open below
   the row's main content. flex-wrap on .wvm-row + width:100% on the
   panel makes it appear as a second flex line. We animate max-height
   + opacity rather than display so the open/close is smooth.
===================================================================== */
.wvm-row-player {
	width: 100%;
	flex-basis: 100%;
	display: none;
	align-items: center;
	gap: 10px;
	overflow: hidden;
	opacity: 0;
	margin-top: 0;
	/* Horizontal extent matches the visible content width above:
	   left edge starts under the contact name (skip past dot+gap+
	   avatar+gap = 8+14+36+14 = 72px); right edge ends under the
	   right edge of the chevron toggle (kebab 32 + gap 14 = 46px
	   from the row's right content edge). Keeps the player visually
	   anchored to row 1 rather than running the full width. */
	padding-left: 72px;
	padding-right: 46px;
	padding-top: 0;
	padding-bottom: 0;
	border-top: 1px solid transparent;
	transition: opacity 0.18s ease;
}
.wvm-row.is-playing .wvm-row-player {
	display: flex;
	opacity: 1;
	margin-top: 4px;
	padding-top: 12px;
	border-top-color: var(--wvm-line);
}
/* Skip back / forward buttons. Same circular style as the play
   button but smaller and quieter. Touch target stays 36px. */
.wvm-row-skipbtn {
	width: 36px;
	height: 36px;
	border-radius: 50%;
	border: 1px solid var(--wvm-line);
	background: var(--wvm-surface);
	color: var(--wvm-ink-2);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	cursor: pointer;
	padding: 0;
	-webkit-appearance: none;
	appearance: none;
	-webkit-tap-highlight-color: transparent;
	transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.wvm-row-skipbtn:hover {
	background: #fafaf7;
	color: var(--wvm-ink);
	border-color: var(--wvm-line-strong);
}
.wvm-row-skipbtn:active { transform: scale(0.94); }
.wvm-row-skipbtn svg {
	width: 22px;
	height: 22px;
	display: block;
}
/* Player time text — current / total. Tabular-nums so the digits
   don't shift width as time progresses. Sits at the right end of
   the player panel. */
.wvm-row-player-time {
	font-size: 12px;
	color: var(--wvm-ink-2);
	font-variant-numeric: tabular-nums;
	flex-shrink: 0;
	min-width: 78px;
	text-align: right;
}
/* Scrubber — styled <input type="range">. We need cross-browser
   styling for the track and thumb. The filled portion of the track
   uses a CSS variable --progress (set inline by JS as a percentage)
   to draw the brand-blue fill behind the thumb. */
.wvm-row-scrub {
	flex: 1;
	min-width: 80px;
	height: 24px;          /* tall hit target for touch dragging */
	background: transparent;
	-webkit-appearance: none;
	appearance: none;
	cursor: pointer;
	margin: 0;
	padding: 0;
}
.wvm-row-scrub:focus { outline: none; }
/* Track (Webkit/Blink) — gradient draws fill up to --progress, then
   neutral track colour after. */
.wvm-row-scrub::-webkit-slider-runnable-track {
	height: 4px;
	border-radius: 2px;
	background: linear-gradient(to right,
		var(--wvm-brand) 0%,
		var(--wvm-brand) var(--progress, 0%),
		var(--wvm-line) var(--progress, 0%),
		var(--wvm-line) 100%);
}
/* Track (Firefox) — Firefox doesn't honour the linear-gradient
   trick the same way, so we use a separate ::-moz-range-progress
   pseudo for the filled portion. */
.wvm-row-scrub::-moz-range-track {
	height: 4px;
	border-radius: 2px;
	background: var(--wvm-line);
	border: none;
}
.wvm-row-scrub::-moz-range-progress {
	height: 4px;
	border-radius: 2px;
	background: var(--wvm-brand);
}
/* Thumb (Webkit) */
.wvm-row-scrub::-webkit-slider-thumb {
	-webkit-appearance: none;
	appearance: none;
	width: 14px;
	height: 14px;
	border-radius: 50%;
	background: var(--wvm-brand);
	border: 2px solid var(--wvm-surface);
	box-shadow: 0 1px 3px rgba(15, 20, 25, 0.20);
	margin-top: -5px;       /* centres thumb on the 4px track */
	cursor: grab;
	transition: transform 0.1s;
}
.wvm-row-scrub::-webkit-slider-thumb:active {
	cursor: grabbing;
	transform: scale(1.15);
}
/* Thumb (Firefox) */
.wvm-row-scrub::-moz-range-thumb {
	width: 14px;
	height: 14px;
	border-radius: 50%;
	background: var(--wvm-brand);
	border: 2px solid var(--wvm-surface);
	box-shadow: 0 1px 3px rgba(15, 20, 25, 0.20);
	cursor: grab;
}

/* Empty state */
.wvm-empty {
	padding: 60px 20px;
	text-align: center;
	color: var(--wvm-ink-3);
	font-size: 13px;
	background: var(--wvm-surface);
	border: 1px solid var(--wvm-line);
	border-radius: var(--wvm-radius-lg);
	box-shadow: 0 1px 2px rgba(15, 20, 25, 0.04),
	            0 4px 12px rgba(15, 20, 25, 0.06);
}

/* =====================================================================
   8. Move-to-folder modal (custom — brand-blue language)
   ===================================================================== */
.wvm-modal-bg {
	position: fixed;
	inset: 0;
	background: rgba(0, 0, 0, 0.45);
	z-index: 1080;
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.18s;
}
.wvm-modal-bg.is-open {
	opacity: 1;
	pointer-events: all;
}
.wvm-modal {
	position: fixed;
	background: var(--wvm-surface);
	border-radius: 16px;
	min-width: 340px;
	max-width: 460px;
	width: calc(100% - 40px);
	box-shadow: 0 20px 60px rgba(0, 0, 0, 0.18);
	z-index: 1081;
	transform: translate(-50%, -50%) scale(0.96);
	transition: transform 0.18s, opacity 0.18s;
	opacity: 0;
	pointer-events: none;
	left: 50%;
	top: 50%;
	overflow: hidden;
}
.wvm-modal.is-open {
	transform: translate(-50%, -50%) scale(1);
	opacity: 1;
	pointer-events: all;
}
.wvm-modal-head {
	display: flex;
	align-items: flex-start;
	gap: 14px;
	padding: 24px 24px 0;
}
.wvm-modal-head-icon {
	width: 44px;
	height: 44px;
	border-radius: 12px;
	background: var(--wvm-brand-soft);
	color: var(--wvm-brand);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
}
/* Danger variant for delete confirm — red soft fill instead of brand */
.wvm-modal-head-icon--danger {
	background: var(--wvm-red-soft);
	color: var(--wvm-red);
}
.wvm-modal-head-icon svg { width: 22px; height: 22px; }
.wvm-modal-titles { flex: 1; min-width: 0; padding-top: 2px; }
.wvm-modal-title {
	font-size: 17px;
	font-weight: 600;
	color: var(--wvm-ink);
	margin: 0;
	letter-spacing: -0.01em;
}
.wvm-modal-sub {
	font-size: 13px;
	color: var(--wvm-ink-2);
	margin-top: 4px;
}
.wvm-modal-close {
	background: transparent;
	border: none;
	color: var(--wvm-ink-3);
	width: 28px;
	height: 28px;
	border-radius: 6px;
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	font-size: 18px;
	margin-top: -2px;
	margin-right: -6px;
	padding: 0;
}
.wvm-modal-close:hover { background: var(--wvm-bg2); color: var(--wvm-ink); }
.wvm-modal-body { padding: 18px 24px 8px; }

/* Help modal — content is prose-heavy so we give it more line-height
   and clear section breaks. Scrolls internally because there's a
   lot of copy and we don't want the modal to grow taller than the
   viewport on small screens. */
.wvm-help-body {
	padding: 14px 24px 16px;
	max-height: 65vh;
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
}
.wvm-help-section {
	padding: 12px 0;
	border-bottom: 1px solid var(--wvm-line);
}
.wvm-help-section:first-child { padding-top: 0; }
.wvm-help-section:last-child { border-bottom: none; padding-bottom: 0; }
.wvm-help-section h4 {
	font-size: 14px;
	font-weight: 600;
	color: var(--wvm-ink);
	margin: 0 0 6px;
	letter-spacing: -0.005em;
}
.wvm-help-section p {
	font-size: 13px;
	line-height: 1.55;
	color: var(--wvm-ink-2);
	margin: 0 0 6px;
}
.wvm-help-section p:last-child { margin-bottom: 0; }
.wvm-help-section b,
.wvm-help-section strong { color: var(--wvm-ink); font-weight: 600; }
.wvm-help-section i,
.wvm-help-section em { font-style: italic; color: var(--wvm-ink); }

/* Mobile — slightly tighter padding to make better use of small
   screens. The internal scroll keeps it contained. */
@media (max-width: 768px) {
	.wvm-help-body {
		padding: 10px 18px 14px;
		max-height: 70vh;
	}
	.wvm-help-section h4 { font-size: 14px; }
	.wvm-help-section p { font-size: 13px; }
}
.wvm-folder-list { display: flex; flex-direction: column; gap: 8px; }
.wvm-folder-pick {
	display: flex;
	align-items: center;
	gap: 14px;
	width: 100%;
	padding: 14px 16px;
	border-radius: 12px;
	background: var(--wvm-surface);
	border: 1px solid var(--wvm-line);
	font-size: 14px;
	font-weight: 500;
	color: var(--wvm-ink);
	text-align: left;
	font-family: inherit;
	transition: all 0.15s ease;
}
.wvm-folder-pick:hover:not(:disabled) {
	background: var(--wvm-bg);
	border-color: var(--wvm-brand);
	transform: translateX(2px);
}
.wvm-folder-pick:disabled,
.wvm-folder-pick--current {
	background: var(--wvm-brand-soft);
	border-color: var(--wvm-brand);
	color: var(--wvm-brand-h);
	cursor: default;
	font-weight: 600;
}
.wvm-folder-pick-tile {
	width: 24px;
	height: 24px;
	background: transparent;
	color: var(--wvm-ink);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	transition: color 0.15s ease;
}
/* Current state — icon stays black/dark; the row background and the
   "Current" pill are enough signal. No coloured tile. */
.wvm-folder-pick--current .wvm-folder-pick-tile,
.wvm-folder-pick:disabled .wvm-folder-pick-tile {
	color: var(--wvm-brand);
}
.wvm-folder-pick-tile svg { width: 22px; height: 22px; stroke-width: 1.75; }
.wvm-folder-pick-name { flex: 1; }
.wvm-folder-pick-current-badge {
	font-size: 10px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: white;
	background: var(--wvm-brand);
	padding: 3px 8px;
	border-radius: 999px;
	margin-left: 4px;
}
/* Unread count pill on each folder row in the move/folder-nav modals.
   Same visual language as the sidebar pill (green = unread) so the
   user reads the same signal everywhere. The count is hidden when 0
   by the JS via conditional rendering. */
.wvm-folder-pick-count {
	font-size: 12px;
	color: white;
	background: var(--wvm-green);
	padding: 3px 9px;
	border-radius: 999px;
	min-width: 24px;
	text-align: center;
	font-weight: 600;
}
/* Folder picker counts (mobile Choose folder + Move to folder modals)
   mirror the side-menu pattern: a small green dot to indicate unread,
   followed by a dimmer total count on the far right. Together they
   give the same at-a-glance signal as the desktop sidebar. */
.wvm-folder-pick-unread {
	width: 9px;
	height: 9px;
	border-radius: 50%;
	background: var(--wvm-green);
	flex-shrink: 0;
	/* Hide the actual digit — the dot itself communicates "unread". */
	font-size: 0;
	line-height: 0;
	/* Tighten distance to the trailing total count (overrides the
	   parent's 14px gap so the dot reads as belonging to the total). */
	margin-right: -8px;
}
.wvm-folder-pick-total {
	font-size: 14px;
	font-weight: 500;
	color: var(--wvm-ink-3);
	font-variant-numeric: tabular-nums;
	flex-shrink: 0;
	min-width: 20px;
	text-align: right;
}
.wvm-folder-pick--current .wvm-folder-pick-total,
.wvm-folder-pick:disabled .wvm-folder-pick-total {
	color: var(--wvm-ink-2);
}
.wvm-modal-foot {
	display: flex;
	justify-content: flex-end;
	gap: 10px;
	padding: 16px 24px 20px;
	border-top: 1px solid var(--wvm-line);
	margin-top: 8px;
}
.wvm-modal-btn {
	padding: 10px 18px;
	border-radius: var(--wvm-radius);
	font-size: 13px;
	font-weight: 600;
	font-family: inherit;
	display: inline-flex;
	align-items: center;
	gap: 7px;
	transition: all 0.12s;
	border: 1px solid transparent;
}
.wvm-modal-btn--secondary {
	background: var(--wvm-surface);
	border-color: var(--wvm-line-strong);
	color: var(--wvm-ink-2);
}
.wvm-modal-btn--secondary:hover {
	background: var(--wvm-bg2);
	color: var(--wvm-ink);
}
.wvm-modal-btn--primary {
	background: var(--wvm-brand);
	color: white;
	box-shadow: 0 1px 3px rgba(37, 99, 235, 0.3);
}
.wvm-modal-btn--primary:hover {
	background: var(--wvm-brand-h);
	box-shadow: 0 2px 8px rgba(37, 99, 235, 0.4);
}
.wvm-modal-btn--danger {
	background: var(--wvm-red);
	color: white;
	box-shadow: 0 1px 3px rgba(220, 38, 38, 0.3);
}
.wvm-modal-btn--danger:hover {
	background: var(--wvm-red-d);
	box-shadow: 0 2px 8px rgba(220, 38, 38, 0.4);
}

/* =====================================================================
   9. Toast
   ===================================================================== */
.wvm-toast {
	position: fixed;
	bottom: 24px;
	left: 50%;
	transform: translateX(-50%) translateY(100px);
	background: var(--wvm-ink);
	color: white;
	padding: 10px 18px;
	border-radius: 999px;
	font-size: 13px;
	font-weight: 500;
	box-shadow: 0 12px 40px rgba(0, 0, 0, 0.20);
	z-index: 2000;
	opacity: 0;
	transition: all 0.25s ease;
	max-width: 90vw;
}
.wvm-toast.is-open {
	opacity: 1;
	transform: translateX(-50%) translateY(0);
}

/* =====================================================================
   10. Bootstrap modal restyling (Email/Forward, Configuration,
       Security, Greetings) — preserve existing IDs and form fields,
       just give them the same visual language as our custom modals.
   ===================================================================== */
#emailModal .modal-content,
#configModal .modal-content,
#securityModal .modal-content,
#greetingsModal .modal-content {
	border-radius: 16px;
	border: none;
	box-shadow: 0 20px 60px rgba(0, 0, 0, 0.18);
	overflow: hidden;
}
#emailModal .modal-header,
#configModal .modal-header,
#securityModal .modal-header,
#greetingsModal .modal-header {
	border-bottom: none;
	padding: 24px 24px 6px;
	display: flex;
	align-items: flex-start;
	gap: 14px;
}
#emailModal .modal-title,
#configModal .modal-title,
#securityModal .modal-title,
#greetingsModal .modal-title {
	font-size: 17px;
	font-weight: 600;
	color: var(--wvm-ink);
	letter-spacing: -0.01em;
	flex: 1;
	display: flex;
	align-items: center;
	gap: 14px;
}
#emailModal .modal-title::before,
#configModal .modal-title::before,
#securityModal .modal-title::before,
#greetingsModal .modal-title::before {
	content: '';
	width: 44px;
	height: 44px;
	border-radius: 12px;
	background: var(--wvm-brand-soft);
	display: inline-block;
	flex-shrink: 0;
	background-repeat: no-repeat;
	background-position: center;
	background-size: 22px 22px;
}
#emailModal .modal-title::before {
	background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232563eb' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='15 17 20 12 15 7'/><path d='M4 18v-2a4 4 0 0 1 4-4h12'/></svg>");
}
#configModal .modal-title::before {
	background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232563eb' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='3'/><path d='M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z'/></svg>");
}
#securityModal .modal-title::before {
	background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232563eb' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><rect x='3' y='11' width='18' height='11' rx='2' ry='2'/><path d='M7 11V7a5 5 0 0 1 10 0v4'/></svg>");
}
#greetingsModal .modal-title::before {
	background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232563eb' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z'/></svg>");
}
#emailModal .modal-header .close,
#configModal .modal-header .close,
#securityModal .modal-header .close,
#greetingsModal .modal-header .close {
	background: transparent;
	border: none;
	color: var(--wvm-ink-3);
	font-size: 22px;
	font-weight: 400;
	width: 28px;
	height: 28px;
	border-radius: 6px;
	padding: 0;
	margin: 0;
	opacity: 1;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	text-shadow: none;
}
#emailModal .modal-header .close:hover,
#configModal .modal-header .close:hover,
#securityModal .modal-header .close:hover,
#greetingsModal .modal-header .close:hover {
	background: var(--wvm-bg2);
	color: var(--wvm-ink);
}
#emailModal .modal-body,
#configModal .modal-body,
#securityModal .modal-body,
#greetingsModal .modal-body {
	padding: 18px 24px 22px;
}

/* Hide the legacy AI-generator "Regenerate" button. script.js
   injects #generateAnotherBtn1 (and id-suffixed variants) with an
   inline display:inline-flex when the user clicks the AI Generate
   tab. We hide it via CSS because the JS observer-based hide can
   miss the inject if Bootstrap's modal lifecycle does anything
   unusual. !important is needed to beat the inline style. The user
   re-generates by editing the message text; webvm.js's
   wireGreetingsAIBehaviour also disables Generate after success
   and re-enables it on edit. */
#greetingsModal [id^="generateAnotherBtn"] {
	display: none !important;
}
#emailModal .form-group,
#configModal .form-group,
#securityModal .form-group,
#greetingsModal .form-group {
	margin-bottom: 16px;
}
#emailModal .form-group:last-child,
#configModal .form-group:last-child,
#securityModal .form-group:last-child,
#greetingsModal .form-group:last-child {
	margin-bottom: 0;
}
#emailModal .form-control,
#configModal .form-control,
#securityModal .form-control,
#greetingsModal .form-control {
	border-radius: 10px;
	border: 1px solid var(--wvm-line);
	font-size: 14px;
	padding: 11px 14px;
	height: auto;
	color: var(--wvm-ink);
	background: var(--wvm-surface);
	transition: all 0.12s;
	box-shadow: none;
}
/* Make textarea-style fields (Note) reasonably tall by default */
#emailModal textarea.form-control {
	min-height: 80px;
	resize: vertical;
}
#emailModal .form-control:focus,
#configModal .form-control:focus,
#securityModal .form-control:focus,
#greetingsModal .form-control:focus {
	border-color: var(--wvm-brand);
	box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.12);
	outline: none;
}
#emailModal .form-control::placeholder,
#configModal .form-control::placeholder,
#securityModal .form-control::placeholder,
#greetingsModal .form-control::placeholder {
	color: var(--wvm-ink-3);
}
#emailModal .form-group label,
#configModal .form-group label,
#securityModal .form-group label,
#greetingsModal .form-group label {
	font-size: 13px;
	font-weight: 500;
	color: var(--wvm-ink-2);
	margin-bottom: 7px;
	display: block;
}

/* Segmented PIN input. Each .vmg-pin-segment is a single-digit
   tel input; together they form a row that looks like a connected
   PIN field. The eye toggle button sits at the end of the row.
   Avoiding type="password" / "PIN"-shaped names is what stops
   Safari from offering its strong-password popover on focus —
   six type="tel" maxlength=1 inputs match the SMS code idiom and
   Safari leaves them alone. */
.vmg-pin-segments {
	display: flex;
	align-items: center;
	gap: 8px;
	flex-wrap: nowrap;
}
.vmg-pin-segment {
	width: 44px;
	height: 52px;
	padding: 0;
	text-align: center;
	font-size: 20px;
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	color: var(--wvm-ink);
	background: var(--wvm-surface);
	border: 1px solid var(--wvm-line);
	border-radius: 10px;
	transition: all 0.12s;
	box-shadow: none;
	-webkit-appearance: none;
	appearance: none;
}
.vmg-pin-segment:focus {
	border-color: var(--wvm-brand);
	box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.12);
	outline: none;
}
.vmg-pin-segment.is-filled {
	background: var(--wvm-bg);
}
/* Mask the digits when the row's eye toggle is in "hide" state.
   Per-segment text-security replaces the digit with a bullet
   without changing input type, so Safari still sees a tel field
   and doesn't offer strong-password generation. */
.vmg-pin-segments.is-masked .vmg-pin-segment {
	-webkit-text-security: disc;
	text-security: disc;
}
/* Eye toggle button sits inline at the end of the segment row */
.vmg-pin-segments .vmg-pin-eye {
	position: static;
	transform: none;
	margin-left: 4px;
	width: 36px;
	height: 36px;
}
.vmg-pin-eye {
	position: absolute;
	right: 6px;
	top: 50%;
	transform: translateY(-50%);
	width: 32px;
	height: 32px;
	border-radius: 8px;
	border: 0;
	background: transparent;
	color: var(--wvm-ink-3);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	padding: 0;
	transition: color 0.12s, background 0.12s;
}
.vmg-pin-eye:hover {
	color: var(--wvm-ink);
	background: var(--wvm-bg);
}
.vmg-pin-eye:focus-visible {
	outline: 2px solid var(--wvm-brand);
	outline-offset: 2px;
}
.vmg-pin-eye svg { width: 16px; height: 16px; }

/* Help text below the input — small, secondary colour, sits in the
   gap between the field and the next form-group. */
.vmg-pin-help {
	margin-top: 6px;
	font-size: 12px;
	color: var(--wvm-ink-3);
	line-height: 1.4;
}
#configModal .form-check {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 0;
	margin-bottom: 12px;
}
#configModal .form-check-input {
	margin: 0;
	width: 18px;
	height: 18px;
	accent-color: var(--wvm-brand);
	flex-shrink: 0;
	position: static !important;
}
#configModal .form-check-label {
	margin: 0;
	font-size: 13px;
	color: var(--wvm-ink);
	font-weight: 400;
}
#emailModal .modal-footer,
#configModal .modal-footer,
#securityModal .modal-footer,
#greetingsModal .modal-footer {
	border-top: 1px solid var(--wvm-line);
	padding: 16px 24px 20px;
	justify-content: flex-end;
	gap: 10px;
}
#emailModal .vmg-btn-close,
#configModal .vmg-btn-close,
#securityModal .vmg-btn-close,
#greetingsModal .vmg-btn-close,
#emailModal .vmg-btn-save,
#configModal .vmg-btn-save,
#securityModal .vmg-btn-save,
#greetingsModal .vmg-btn-save {
	padding: 10px 18px;
	border-radius: var(--wvm-radius);
	font-size: 13px;
	font-weight: 600;
	font-family: inherit;
	border: 1px solid transparent;
	transition: all 0.12s;
	display: inline-flex;
	align-items: center;
	gap: 7px;
}

/* Greetings: current-greeting block with inline delete affordance.
   The header sits above the audio player with the title on the
   left and a small red Delete pill on the right. The button is
   hidden by default; webvm.js reveals it once the audio player
   is present (i.e. there's actually a current greeting to delete).
   Pattern matches iOS-style "destructive action right of label". */
.vmg-greeting-current {
	margin-bottom: 6px;
}
.vmg-greeting-current-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	margin-bottom: 12px;
}
.vmg-greeting-current-head b {
	font-size: 14px;
	color: var(--wvm-ink);
}
.vmg-greeting-delete {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 6px 12px;
	border-radius: 999px;
	border: 1px solid #fecaca;
	background: #fef2f2;
	color: #b91c1c;
	font-size: 12px;
	font-weight: 600;
	cursor: pointer;
	transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.vmg-greeting-delete:hover {
	background: #fee2e2;
	border-color: #fca5a5;
	color: #991b1b;
}
.vmg-greeting-delete:active {
	transform: translateY(1px);
}
.vmg-greeting-delete svg {
	width: 13px;
	height: 13px;
	stroke-width: 2.2;
}
/* Empty-state message shown when no greeting is set. Soft surface
   with dashed border so it reads as informational, not an error.
   Sits below the "You do not have a custom..." copy that
   getGreeting() renders into #current-greetingsID — small top
   margin gives them breathing room. */
.vmg-greeting-empty {
	margin-top: 12px;
	padding: 16px 14px;
	border-radius: 10px;
	background: var(--wvm-bg);
	border: 1px dashed var(--wvm-line);
	color: var(--wvm-ink-2);
	font-size: 13px;
	line-height: 1.5;
	text-align: center;
}

/* Inline file-validation error — sits below the file input when
   the user picks an invalid file (wrong format or too large).
   Shouty enough to be noticed but not alert-level loud. */
.vmg-file-error {
	margin-top: 8px;
	padding: 8px 12px;
	border-radius: 8px;
	background: #fef2f2;
	border: 1px solid #fecaca;
	color: #991b1b;
	font-size: 12px;
	line-height: 1.45;
}
#emailModal .vmg-btn-close,
#configModal .vmg-btn-close,
#securityModal .vmg-btn-close,
#greetingsModal .vmg-btn-close {
	background: var(--wvm-surface);
	border-color: var(--wvm-line-strong);
	color: var(--wvm-ink-2);
}
#emailModal .vmg-btn-close:hover,
#configModal .vmg-btn-close:hover,
#securityModal .vmg-btn-close:hover,
#greetingsModal .vmg-btn-close:hover {
	background: var(--wvm-bg2);
	color: var(--wvm-ink);
}
#emailModal .vmg-btn-save,
#configModal .vmg-btn-save,
#securityModal .vmg-btn-save,
#greetingsModal .vmg-btn-save {
	background: var(--wvm-brand);
	color: white;
	box-shadow: 0 1px 3px rgba(37, 99, 235, 0.3);
}
#emailModal .vmg-btn-save:hover,
#configModal .vmg-btn-save:hover,
#securityModal .vmg-btn-save:hover,
#greetingsModal .vmg-btn-save:hover {
	background: var(--wvm-brand-h);
	box-shadow: 0 2px 8px rgba(37, 99, 235, 0.4);
}
#emailModal .alert,
#configModal .alert,
#securityModal .alert,
#greetingsModal .alert {
	border-radius: 10px;
	border: none;
	font-size: 13px;
	padding: 10px 14px;
}
#emailModal .alert-success,
#configModal .alert-success,
#securityModal .alert-success,
#greetingsModal .alert-success {
	background: var(--wvm-green-soft);
	color: var(--wvm-green-d);
}
#emailModal .alert-danger,
#configModal .alert-danger,
#securityModal .alert-danger,
#greetingsModal .alert-danger {
	background: var(--wvm-red-soft);
	color: var(--wvm-red-d);
}

/* =====================================================================
   11. Mobile (≤ 768px)
   ===================================================================== */

/* Inline header menu button. Lives in .wvm-head on every viewport
   but is hidden on desktop — only shows on mobile where the sidebar
   is collapsed by default. Plain ghost button so it doesn't look
   like a floating Material tile. */
.wvm-head-menu {
	display: none;
	width: 38px;
	height: 38px;
	border-radius: 9px;
	background: transparent;
	border: 1px solid var(--wvm-line);
	color: var(--wvm-ink);
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	transition: all 0.12s;
	padding: 0;
	cursor: pointer;
}
.wvm-head-menu:hover {
	background: var(--wvm-bg2);
	border-color: var(--wvm-line-strong);
}
.wvm-head-menu:active { transform: scale(0.96); }
.wvm-head-menu svg { width: 18px; height: 18px; }
/* Unread count badge — shown on the menu button when there's any
   unread anywhere. Total unread = inbox + rollup. JS writes the
   count into the badge text and the data-count attribute; CSS hides
   it when count is 0. Sized to be legible at a glance: ~18px tall,
   pill shape, brand-green with white text, 2px ring matching the
   page background so it reads as a status overlay rather than
   getting lost on the button. */
.wvm-head-menu {
	position: relative;
}
.wvm-head-menu-badge {
	position: absolute;
	top: -6px;
	right: -6px;
	min-width: 18px;
	height: 18px;
	padding: 0 5px;
	border-radius: 999px;
	background: var(--wvm-green);
	color: white;
	font-size: 11px;
	font-weight: 700;
	line-height: 1;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border: 2px solid var(--wvm-bg);
	box-sizing: content-box;
	letter-spacing: 0.01em;
	pointer-events: none;
}
/* Hide when there's nothing to show */
.wvm-head-menu-badge[data-count="0"] {
	display: none;
}

@media (max-width: 768px) {
	.wvm-head-menu { display: inline-flex; }
	.wvm-side-close { display: inline-flex; }

	/* Sidebar slides in from the left */
	.wvm-side {
		left: -260px;
		transition: left 0.3s ease;
	}
	.wvm-app.is-side-open .wvm-side { left: 0; }

	/* Backdrop when sidebar is open */
	.wvm-side-backdrop {
		display: none;
		position: fixed;
		inset: 0;
		background: rgba(0, 0, 0, 0.5);
		z-index: 99;
	}
	.wvm-app.is-side-open .wvm-side-backdrop { display: block; }

	/* Main content fills full width on mobile */
	.wvm-main { margin-left: 0; }

	/* Consistent 14px gutter from the left/right edge for every
	   horizontal element: header, search bar, folder dropdown, and
	   the list card. Without this the list card sat at 24px while
	   everything else sat at 14-16px, making the layout look ragged. */
	.wvm-head {
		padding: 14px 14px 8px;
		gap: 12px;
		align-items: center;
	}
	.wvm-head h1 { font-size: 19px; }
	.wvm-head-titles { padding-top: 0; }
	.wvm-bar { padding: 8px 14px; }

	/* Mobile folder dropdown row */
	.wvm-mobile-folder-row {
		display: block;
		padding: 8px 14px 0;
		background: transparent;
	}
	.wvm-mobile-folder-trigger {
		display: flex;
		align-items: center;
		gap: 10px;
		width: 100%;
		height: 40px;
		padding: 0 14px;
		background: var(--wvm-surface);
		border: 1px solid var(--wvm-line);
		border-radius: var(--wvm-radius);
		font-size: 13px;
		color: var(--wvm-ink);
		font-family: inherit;
	}
	.wvm-mobile-folder-trigger:hover { background: var(--wvm-bg2); }
	.wvm-mobile-folder-trigger > svg:first-child {
		width: 14px;
		height: 14px;
		color: var(--wvm-ink-2);
		flex-shrink: 0;
	}
	.wvm-mobile-folder-trigger > svg:last-child {
		width: 12px;
		height: 12px;
		color: var(--wvm-ink-3);
		flex-shrink: 0;
	}
	.wvm-mobile-folder-trigger-label {
		flex: 1;
		text-align: left;
	}
	.wvm-mobile-folder-trigger-label b { font-weight: 600; }

	/* List card aligns with everything above (14px gutter) and a
	   slightly tighter top margin since header padding is smaller. */
	.wvm-list {
		margin: 8px 14px 14px;
	}

	/* Tighter rows */
	.wvm-day { padding: 10px 16px 6px; }
	.wvm-row { padding: 12px 16px; column-gap: 10px; row-gap: 0; }
	.wvm-row-name { font-size: 16px; font-weight: 600; }
	.wvm-row-meta { font-size: 12px; }

	/* Mobile uses the desktop-style stacked right-hand column (date
	   above, duration below) instead of cramming both onto the meta
	   line. Reads like the native iOS Phone/Voicemail row. */
	.wvm-row-when {
		display: block;
		font-size: 12px;
	}
	.wvm-row-meta-time,
	.wvm-row-meta-dur,
	.wvm-row-meta-sep {
		display: none;
	}

	/* The play button only ever appears INSIDE the open player panel
	   (no separate row-level play button on this layout). Its desktop
	   sizing works fine on mobile too — no override needed. */

	/* Hide per-row icon buttons on mobile (Select mode for bulk) */
	.wvm-row-actions { display: none !important; }

	/* Player panel on mobile: tighter gap and sizing, full row width
	   (no left/right padding) so all 6 transport controls fit on
	   a narrow viewport. */
	.wvm-row-player {
		gap: 6px;
		padding-left: 0;
		padding-right: 0;
	}
	.wvm-row.is-playing .wvm-row-player { padding-top: 10px; }
	.wvm-row-skipbtn { width: 32px; height: 32px; }
	.wvm-row-skipbtn svg { width: 19px; height: 19px; }
	.wvm-row-player-time {
		font-size: 11px;
		min-width: 60px;
	}
	.wvm-row-scrub { min-width: 40px; }

	/* ---------------------------------------------------------------
	   Select-mode bulk bar on mobile.
	   Goals:
	   - Bar replaces the folder dropdown (no double row)
	   - Same horizontal gutter (14px) as the list card so it aligns
	   - Single-row layout — no wrapping that pushes content down
	   - All buttons icon-only on portrait; "Select all" text drops,
	     the checkbox alone is the affordance
	   --------------------------------------------------------------- */
	.wvm-app.is-select-mode .wvm-mobile-folder-row { display: none; }
	.wvm-bar.is-select {
		margin: 0 14px;
		padding: 8px 10px;
		gap: 6px;
		flex-wrap: nowrap;
	}
	/* Drop the "Select all" text — checkbox alone is the affordance */
	.wvm-bar.is-select .wvm-select-count { display: none; }
	/* Icon-only action buttons: hide their text labels (Forward, Move
	   to...), tighten padding so each button is roughly square. The
	   disabled state still communicates clearly via opacity. */
	.wvm-bar.is-select .wvm-bulk {
		padding: 7px 10px;
		gap: 0;
	}
	.wvm-bar.is-select .wvm-bulk span { display: none; }
	.wvm-bar.is-select .wvm-bulk svg { width: 15px; height: 15px; }
	/* Cancel is already icon-only via wvm-cancel--icon; no override
	   needed here. */
}
