/**
 * Vocalis Studio — dark.css
 *
 * Dark theme for the APP PAGES only (dashboard, text-to-speech, voices,
 * audio, favorites, settings). The landing page is intentionally not
 * covered yet.
 *
 * ---------------------------------------------------------------------------
 * WHY THIS IS A SEPARATE FILE RATHER THAN EDITS TO app.css
 *
 * app.css carries ~46 rules with hard-coded light surfaces
 * (`rgba(255,255,255,0.6)` fills, `inset 0 0 0 1px rgba(255,255,255,0.5)`
 * hairlines, `background: #fff` inputs). The tidy refactor would be to
 * replace all of them with variables and flip the variables here.
 *
 * That refactor touches every one of those 46 rules in the file that renders
 * the light theme — the theme that currently works and that you have signed
 * off on. A single mistake there breaks light mode for everyone, to add a
 * feature nobody is using yet.
 *
 * So every rule below is additive and scoped to `[data-vx-theme="dark"]`.
 * Light mode cannot regress, because not one line of app.css changed. Once
 * dark mode has been in use for a while and the palette has settled, the
 * two can be merged into variables properly.
 *
 * ---------------------------------------------------------------------------
 * SURFACE MAPPING
 *
 * In light mode an "elevated" surface is white at high alpha over a pale
 * background. In dark mode the same visual job is done by white at LOW alpha
 * over a dark background — the alpha is not inverted, it is rescaled:
 *
 *     light 0.55  ->  dark 0.045      (tiles, empty states)
 *     light 0.60  ->  dark 0.050      (rows)
 *     light 0.70  ->  dark 0.065      (cards, inputs, pills)
 *     light 0.80  ->  dark 0.090      (hover)
 *     hairline 0.5 -> dark 0.070
 *     hairline 0.6 -> dark 0.085
 *     #fff (opaque) -> #1e2230        (dropdowns, text fields, menus)
 *
 * SIX rules are deliberately NOT converted, because their white sits on a
 * brand gradient rather than on the page: the active sidebar icon, the clone
 * button spinner, the generate-button fill, the plan-card CTA, the switch
 * thumb, and the slider thumbs. White is still correct there in dark mode.
 * All 30 `color: #fff` declarations are left alone for the same reason —
 * every one of them is text on a coloured button.
 */

/* ============================================================
   1. TOKENS
   Everything in the theme that already uses a variable follows from here.
   ============================================================ */
[data-vx-theme="dark"] {
	--background: #0f1117;
	--foreground: #e8eaf0;

	--card: #171a23;
	--card-foreground: #e8eaf0;
	--popover: #1e2230;
	--popover-foreground: #e8eaf0;

	--secondary: rgba(255, 255, 255, 0.07);
	--secondary-foreground: #d3d7e2;

	--muted: rgba(255, 255, 255, 0.05);
	--muted-foreground: #9aa1b4;

	--accent: rgba(139, 92, 246, 0.18);
	--accent-foreground: #e8eaf0;

	--border: rgba(255, 255, 255, 0.09);
	--input: rgba(255, 255, 255, 0.09);

	--surface: rgba(255, 255, 255, 0.05);
	--surface-elevated: #1e2230;

	--glass: rgba(255, 255, 255, 0.055);
	--glass-border: rgba(255, 255, 255, 0.09);

	/* Shadows read as depth against a light page. Against a dark one they
	   have to be much deeper to register at all, and the inset highlight
	   that sells "glass" has to drop to a fraction of its light value or it
	   turns into a visible white line. */
	--shadow-soft: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px -8px rgba(0, 0, 0, 0.5);
	--shadow-elevated: 0 4px 12px -2px rgba(0, 0, 0, 0.45), 0 24px 60px -20px rgba(0, 0, 0, 0.6);
	--shadow-glass: inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 8px 32px -12px rgba(0, 0, 0, 0.55);

	/* The ambient page wash. Same three brand hues, far lower alpha — at
	   light-mode strength they glow like neon against a dark background. */
	--gradient-hero:
		radial-gradient(65% 45% at 50% 0%, rgba(139, 92, 246, 0.16), transparent 70%),
		radial-gradient(45% 35% at 95% 10%, rgba(91, 156, 246, 0.14), transparent 70%),
		radial-gradient(45% 40% at 5% 20%, rgba(224, 123, 208, 0.10), transparent 70%);

	color-scheme: dark;
}

/* Native form controls, scrollbars and the browser UI follow color-scheme. */
[data-vx-theme="dark"] body { background: var(--background); color: var(--foreground); }

/* ============================================================
   2. APP SHELL
   ============================================================ */

/* The fixed header bar and the mobile tab bar.
   These use `.vx-glass-nav`, which — unlike `.vx-glass-panel` — declares its
   fill as a literal `rgba(252,252,255,0.72)` with no variable behind it. So
   flipping the tokens did nothing for them and they stayed near-white while
   everything around them went dark. They keep their backdrop-filter, because
   they genuinely do sit over scrolling content; only the fill, the hairline
   and the shadow change. */
[data-vx-theme="dark"] .vx-glass-nav {
	background: rgba(22, 25, 34, 0.78);
	border: 1px solid rgba(255, 255, 255, 0.08);
	box-shadow: 0 2px 16px rgba(0, 0, 0, 0.45);
}

/* `.vx-btn-glass` picks up `--glass` for its fill, but its inset highlight is
   a literal `rgba(255,255,255,0.7)` — a bright white hairline that reads as a
   scratch on a dark surface. */
[data-vx-theme="dark"] .vx-btn-glass {
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.07), 0 4px 12px rgba(0, 0, 0, 0.45);
	border-color: rgba(255, 255, 255, 0.09);
}

[data-vx-theme="dark"] #vx-app-page { background: var(--background); }

/* Profile-active avatar: `--accent` is already dark-mapped, but the purple
   ring needs lifting or it disappears against the dark bar. */
[data-vx-theme="dark"] .vx-app-header__user.is-active {
	box-shadow: inset 0 0 0 1.5px #a78bfa;
}
[data-vx-theme="dark"] .vx-app-page__bg { background-image: var(--gradient-hero); }

/* The two fixed ambient blobs are gradients now (perf.css section 12), so
   they only need their alpha pulled down for a dark backdrop. */
[data-vx-theme="dark"] .vx-app-page__blob-1,
[data-vx-theme="dark"] .vx-app-page__blob-2 { opacity: 0.55; }
[data-vx-theme="dark"] .vx-hero-shell__blob-a,
[data-vx-theme="dark"] .vx-hero-shell__blob-b { opacity: 0.6; }

[data-vx-theme="dark"] .vx-app-sidebar__link:hover { background: rgba(255, 255, 255, 0.065); }
[data-vx-theme="dark"] .vx-app-sidebar__link:hover:not(.is-active) .vx-app-sidebar__icon { background: #262b3a; }
[data-vx-theme="dark"] .vx-app-sidebar__upsell { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.085); }

/* ============================================================
   3. SURFACES — the 0.55 / 0.60 / 0.70 / 0.80 family
   ============================================================ */

/* 0.55 -> 0.045 */
[data-vx-theme="dark"] .vx-stat-tile,
[data-vx-theme="dark"] .vx-pkg-stat,
[data-vx-theme="dark"] .vx-empty-state {
	background: rgba(255, 255, 255, 0.045);
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.07);
}

/* 0.60 -> 0.050 */
[data-vx-theme="dark"] .vx-history-row,
[data-vx-theme="dark"] .vx-rail-voice-list li,
[data-vx-theme="dark"] .vx-rail-download-list li,
[data-vx-theme="dark"] .vx-top-voices li,
[data-vx-theme="dark"] .vx-audio-row,
[data-vx-theme="dark"] .vx-fav-clip-row {
	background: rgba(255, 255, 255, 0.05);
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.07);
}

/* 0.70 -> 0.065 */
[data-vx-theme="dark"] .vx-rail-quick__item,
[data-vx-theme="dark"] .vx-hero-shell__greeting,
[data-vx-theme="dark"] .vx-access-verified__change,
[data-vx-theme="dark"] .vx-quick-card,
[data-vx-theme="dark"] .vx-voice-picker__search,
[data-vx-theme="dark"] .vx-lang-select__search,
[data-vx-theme="dark"] .vx-player__textbox,
[data-vx-theme="dark"] .vx-voice-card__wave,
[data-vx-theme="dark"] .vx-fav-voice-card {
	background: rgba(255, 255, 255, 0.065);
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.085);
}

/* 0.80 hover -> 0.090 */
[data-vx-theme="dark"] .vx-history-row:hover,
[data-vx-theme="dark"] .vx-rail-voice-list li:hover,
[data-vx-theme="dark"] .vx-top-voices li:hover,
[data-vx-theme="dark"] .vx-audio-row:hover,
[data-vx-theme="dark"] .vx-fav-clip-row:hover,
[data-vx-theme="dark"] .vx-voice-picker__option.is-selected {
	background: rgba(255, 255, 255, 0.09);
}
[data-vx-theme="dark"] .vx-voice-picker__option:hover,
[data-vx-theme="dark"] .vx-lang-select__option:hover,
[data-vx-theme="dark"] .vx-audio-row__menu button:hover {
	background: rgba(255, 255, 255, 0.075);
}

/* ============================================================
   4. OPAQUE SURFACES — the `background: #fff` family
   Dropdowns, text fields and menus need to stay opaque so the content
   behind them cannot show through.
   ============================================================ */
[data-vx-theme="dark"] .vx-text-input .vx-text-highlight,
[data-vx-theme="dark"] .vx-pause-menu,
[data-vx-theme="dark"] .vx-voice-picker__trigger,
[data-vx-theme="dark"] .vx-lang-select__trigger,
[data-vx-theme="dark"] .vx-search-input,
[data-vx-theme="dark"] .vx-settings-field input {
	background: #1e2230;
	color: var(--foreground);
}

/* The textarea sits transparently on top of the highlight layer. */
[data-vx-theme="dark"] .vx-text-input textarea { color: var(--foreground); }
[data-vx-theme="dark"] .vx-text-input textarea::placeholder,
[data-vx-theme="dark"] .vx-search-input::placeholder { color: #79809a; }

[data-vx-theme="dark"] .vx-vc-slot { border-color: rgba(255, 255, 255, 0.14); }
[data-vx-theme="dark"] .vx-vc-active { background: rgba(255, 255, 255, 0.075); }
[data-vx-theme="dark"] .vx-vc-upload { border-color: rgba(255, 255, 255, 0.16); }
[data-vx-theme="dark"] .vx-settings-lock-btn { background: rgba(255, 255, 255, 0.06); }

/* Amber warning surfaces. On a light page these are a pale cream fill with
   dark amber text; inverted, that becomes a deep amber tint with light amber
   text. The hue is preserved so the "caution" reading survives — only the
   lightness is flipped. */
[data-vx-theme="dark"] .vx-vc-queue {
	background: rgba(180, 83, 9, 0.16);
	border-color: rgba(252, 211, 77, 0.35);
}
[data-vx-theme="dark"] .vx-vc-queue__title { color: #fcd34d; }
[data-vx-theme="dark"] .vx-vc-queue__sub { color: #e5b567; }
[data-vx-theme="dark"] .vx-vc-active__badge.warn {
	background: rgba(180, 83, 9, 0.22);
	color: #fbbf24;
}

/* ── Access gate + usage meter (Profile page) ──
   Nearly everything here already follows --secondary / --surface / --border,
   which are remapped above. Only the three hard-coded values need a dark
   counterpart: the emerald "verified" green, which is too dark to read on a
   dark card, and the two focus/error rings, which were tuned for a light
   background. */
[data-vx-theme="dark"] .vx-gate.is-verified .vx-gate__badge,
[data-vx-theme="dark"][data-vx-access="verified"] .vx-gate:not(.is-verified) .vx-gate__badge { background: rgba(52, 211, 153, 0.14); color: #34d399; }
[data-vx-theme="dark"] .vx-gate__status { color: #34d399; }
[data-vx-theme="dark"] .vx-ios-row__value--ok { color: #34d399; }
[data-vx-theme="dark"] .vx-codebar input:focus { box-shadow: 0 0 0 3px rgba(167, 139, 250, 0.24); border-color: #a78bfa; }
[data-vx-theme="dark"] .vx-codebar.is-error input { box-shadow: 0 0 0 3px rgba(248, 113, 113, 0.20); }
[data-vx-theme="dark"] .vx-codebar input { background: rgba(255, 255, 255, 0.05); color: var(--foreground); }

/* ── Voice library cards (2-up) ──
   The card now draws its own surface instead of inheriting `.vx-glass-panel`,
   so it needs its dark counterpart declared here. Everything else on the card
   already runs through --surface / --border / --secondary. */
[data-vx-theme="dark"] .vx-voice-card { background: var(--card); border-color: var(--border); }
[data-vx-theme="dark"] .vx-voice-card__wave { background: rgba(255, 255, 255, 0.05); border-color: var(--border); }
[data-vx-theme="dark"] .vx-fav-toggle.is-active { background: rgba(236, 72, 153, 0.16); color: #f472b6; }

/* Voices toolbar chip needs no dark rule (it is a brand gradient), but the
   count sits on --muted-foreground which is already remapped. Listed here
   only so the next person does not go looking for it. */

/* Packages page: the emerald tick is unreadable on a dark card. */
[data-vx-theme="dark"] .vx-pack__tick { background: rgba(52, 211, 153, 0.14); color: #34d399; }
[data-vx-theme="dark"] .vx-pack.is-featured { box-shadow: var(--shadow-elevated), inset 0 0 0 1.5px #a78bfa; }

[data-vx-theme="dark"] .vx-voice-pin { background: rgba(167, 139, 250, 0.18); color: #c4b5fd; }

/* Pause marker pill inside the script textarea's highlight layer
   (.vx-pause-pill). It had no dark counterpart at all: both its background
   AND its text color read from the single, never-remapped `--primary`
   token — a 14%-opacity wash of the same purple used at full strength for
   the text.

   CORRECTION: the first attempt used #c4b5fd (a bright, light lavender) for
   the text. Light mode's pill is a moderate-contrast pairing — medium-indigo
   text on pale lavender — but bright-text-on-near-black is a much HIGHER
   contrast ratio, and that combination visibly blooms/glows on real phone
   screens and in photos of them (the eye's own irradiation response to a
   light shape on a dark field, the same reason white text on black always
   looks "thicker" than the reverse). Dialing the text down to #a78bfa — a
   more moderate purple already used elsewhere in this file for exactly this
   reason — brings the contrast ratio back in line with light mode's, so the
   pill reads the same clean way in both themes instead of glowing in one. */
[data-vx-theme="dark"] .vx-pause-pill { background: rgba(167, 139, 250, 0.20); color: #a78bfa; }

/* Trending toggle — amber tuned for a light card is too dark to read against
   a dark one. */
[data-vx-theme="dark"] .vx-trend-toggle { background: rgba(251, 191, 36, 0.14); color: #fbbf24; }

/* Translate feature + the revived .vx-lang-select dropdown. Everything runs
   through --surface/--border/--secondary already fixed above in app.css, so
   only the two hard-coded status colours (green result, red error) need a
   dark-safe counterpart here. */
[data-vx-theme="dark"] .vx-translate-result { background: rgba(52, 211, 153, 0.12); color: #34d399; }
[data-vx-theme="dark"] #vx-translate-undo { color: #34d399; }
[data-vx-theme="dark"] .vx-translate-error { background: rgba(248, 113, 113, 0.12); color: #f87171; }

/* ── Slide-out menu ──
   Most of the panel already runs on --card / --surface / --border, which are
   remapped above. Only the scrim, the drop shadow and the two hard-coded
   greens need a dark counterpart: a shadow tuned for a light page is
   invisible against a dark one, and the emerald is unreadable. */
[data-vx-theme="dark"] .vx-menu {
	box-shadow: -8px 0 40px -12px rgba(0, 0, 0, 0.62);
	border-left-color: var(--border);
}
[data-vx-theme="dark"] .vx-menu-scrim { background: rgba(0, 0, 0, 0.55); }
[data-vx-theme="dark"] .vx-menu__dot.is-live { background: #34d399; }
[data-vx-theme="dark"] .vx-menu__pill { background: rgba(52, 211, 153, 0.14); color: #34d399; }
/* #232733 sat against a track that composites to roughly #24262f — the
   selected half was invisible. A lighter fill separates it clearly. */
[data-vx-theme="dark"] .vx-menu__seg button.is-active { background: rgba(255, 255, 255, 0.16); color: #fff; }
[data-vx-theme="dark"] .vx-menu__up-cta,
[data-vx-theme="dark"] .vx .vx-menu__up-cta { color: #3b1d78; }

/* ============================================================
   5. THEME MENU (the dropdown on the header button)
   ============================================================ */
.vx-theme-menu {
	position: absolute;
	top: calc(100% + 0.5rem);
	right: 0;
	z-index: 60;
	min-width: 10rem;
	padding: 0.375rem;
	border-radius: var(--r-xl);
	background: var(--popover);
	border: 1px solid var(--border);
	box-shadow: var(--shadow-elevated);
}
.vx-theme-menu[hidden] { display: none; }
.vx-theme-toggle-wrap { position: relative; }
.vx-theme-menu__item {
	display: flex;
	align-items: center;
	gap: 0.625rem;
	width: 100%;
	padding: 0.5rem 0.625rem;
	border: 0;
	border-radius: var(--r-md);
	background: transparent;
	color: var(--foreground);
	font-size: 0.875rem;
	font-weight: 500;
	cursor: pointer;
	text-align: left;
	transition: background-color 0.2s ease, color 0.2s ease;
}
.vx-theme-menu__item:hover { background: var(--secondary); }
.vx-theme-menu__item.is-active { color: var(--brand-purple); font-weight: 600; }
.vx-theme-menu__check { margin-left: auto; opacity: 0; }
.vx-theme-menu__item.is-active .vx-theme-menu__check { opacity: 1; }

/* The trigger is hidden above 1024px in app.css because it was an unused
   "Filters" button. It is the theme switcher now, so it has to be reachable
   on desktop too. */
@media (min-width: 1024px) {
	.vx-app-header__filter-btn { display: grid; }
}

/* ══════════════════════════════════════════════════════════════════════
   LANDING PAGE
   ══════════════════════════════════════════════════════════════════════
   dark.css now loads on the front page too, so the header's light/dark
   switch has something to act on. Nearly everything out there already
   runs through the tokens remapped at the top of this file; these are the
   few pieces that carry their own colour.
   ══════════════════════════════════════════════════════════════════════ */

/* The demo panel's "explore" strip tints itself blue and sets a blue link
   colour, both chosen against a white card. */
[data-vx-theme="dark"] .vx-vexplore { background-image: linear-gradient(180deg, transparent, rgba(91, 156, 246, 0.16)); }
[data-vx-theme="dark"] .vx-vexplore a { color: #93c5fd; }

/* The cloning comparison's second slot is a fixed pastel gradient with dark
   text — correct in both themes — but its play button borrows `--card`,
   which would make it dark-on-dark. */
[data-vx-theme="dark"] .vx-clone__slot--clone .vx-clone__play { background: rgba(255, 255, 255, 0.9); color: #2b1055; }

/* Feature-card icon plates and the footer's subscribe field are opaque white
   in landing.css. */
[data-vx-theme="dark"] .vx-feature-card__icon { background: var(--card); }
[data-vx-theme="dark"] .vx-landing-footer__subscribe input { background: var(--card); color: var(--foreground); }
[data-vx-theme="dark"] .vx-landing-footer__subscribe input::placeholder { color: var(--muted-foreground); }

/* The landing pill hard-codes near-black text. */
[data-vx-theme="dark"] .vx-pill { color: var(--foreground); }

/* Pricing's featured card is a brand gradient in BOTH themes — its white
   badge and light CTA are correct there and must not follow the theme.
   Noted so the next person does not "fix" them. */
