Purely cosmetic CSS in your own browser. It doesn’t touch orders, positions, or the API, and toggles off in one click.
Setup
- Install Stylus (Chrome/Edge/Arc/Brave, also on Firefox) or your userstyle manager of choice
- Stylus icon → Write new style
- “Applies to” → URLs on the domain →
app.alpaca.markets - Paste the CSS below, name it, Save
- Reload
Leave “Write new style as UserCSS” unchecked, or the paste fails validation.
/* Alpaca dashboard — dark mode override (v2: hover + accent states)
Stylus ▸ URLs on the domain ▸ app.alpaca.markets */
:root {
--al-bg: #0d0d0f; /* page ground */
--al-surface: #16161a; /* cards, panels */
--al-raised: #1f1f25; /* inputs, tabs */
--al-hover: #24242b; /* neutral hover: lift, not bleach */
--al-hover-2: #2e2e36; /* stronger hover / pressed */
--al-border: #2b2b33;
--al-text: #e8e8ea;
--al-muted: #9a9aa2;
--al-dim: #6e6e78;
--al-accent: #ecb206; /* yellow-500, the brand */
--al-accent-soft: rgba(236,178,6,.10); /* selected surface */
--al-accent-hi: rgba(236,178,6,.18); /* hovered surface */
color-scheme: dark;
}
/* ---- surfaces ------------------------------------------------ */
html, body { background: var(--al-bg) !important; }
.bg-white { background-color: var(--al-surface) !important; }
.bg-gray-50, .bg-gray-100, .bg-zinc-100, .bg-zinc-200, .bg-zinc-300,
.bg-cool-gray-50, .bg-cool-gray-100,
.bg-cool-gray-200, .bg-cool-gray-300,
.bg-\[rgba\(215\,215\,215\,0\.24\)\] { background-color: var(--al-raised) !important; }
/* ---- text ---------------------------------------------------- */
.text-black,
.text-zinc-900, .hover\:text-zinc-900:hover,
.text-gray-900, .text-gray-800, .text-gray-700, .text-zinc-800,
.text-cool-gray-900, .text-cool-gray-800,
.text-cool-gray-700 { color: var(--al-text) !important; }
.text-gray-600, .text-gray-500, .text-zinc-500, .text-zinc-600,
.text-cool-gray-500 { color: var(--al-muted) !important; }
.text-gray-300, .text-cool-gray-400 { color: var(--al-dim) !important; }
.text-yellow-600 { color: #e0a800 !important; }
/* ---- ARBITRARY HEX TEXT / BORDERS ------------------------------
Alpaca writes its primary + secondary text colors as hex literals in
places (the symbol-search dropdown is all of these), so no named-palette
sweep reaches them. #282828/#3B3B3B are body text — they were staying
near-black on the dark panel. */
.text-\[\#282828\], .text-\[\#3B3B3B\] { color: var(--al-text) !important; }
.text-\[\#565656\], .text-\[\#60676a\],
.text-\[\#696969\], .text-\[\#7A7A7A\] { color: var(--al-muted) !important; }
.text-\[\#4F46E5\] { color: #818cf8 !important; }
.border-\[\#D1D5DB\] { border-color: var(--al-border) !important; }
/* ---- borders ------------------------------------------------- */
.border-gray-200, .border-gray-300, .border-gray-400, .border-gray-500,
.border-cool-gray-200, .border-cool-gray-300, .border-cool-gray-500,
.border-\[\#9C9C9C\], .border-\[\#565656\] { border-color: var(--al-border) !important; }
.border-zinc-100, .border-zinc-200, .border-zinc-300
{ border-color: var(--al-border) !important; }
.ring-gray-200,
.focus\:ring-zinc-100:focus,
.focus\:ring-zinc-300:focus { --tw-ring-color: var(--al-border) !important; }
/* ---- NEUTRAL HOVER: lift off the surface, never toward white -- */
.hover\:bg-gray-50:hover, .hover\:bg-gray-100:hover,
.hover\:bg-cool-gray-50:hover, .hover\:bg-cool-gray-100:hover,
.hover\:bg-zinc-200:hover { background-color: var(--al-hover) !important; }
.hover\:bg-gray-200:hover, .hover\:bg-gray-300:hover,
.hover\:bg-gray-400:hover, .hover\:bg-black:hover { background-color: var(--al-hover-2) !important; }
/* ---- ACCENT SURFACES: translucent amber, not pastel fill ------ */
/* selected account card (bg-yellow-50) + its hover (bg-yellow-100) */
.bg-yellow-50, .bg-yellow-100,
.bg-yellow-100\/80 { background-color: var(--al-accent-soft) !important; }
.hover\:bg-yellow-100:hover { background-color: var(--al-accent-hi) !important; }
.hover\:border-yellow-600:hover { border-color: var(--al-accent) !important; }
/* ---- SOLID BRAND CTAs: force a near-black label ----------------
Doubled class = specificity (0,2,0), so it beats .text-cool-gray-800
which Alpaca puts on the SAME element (Add Funds, Apply Now, Edit
Payment). The descendant rule catches nested spans + currentColor svg. */
.bg-yellow-200.bg-yellow-200, .bg-yellow-300.bg-yellow-300,
.bg-yellow-400.bg-yellow-400, .bg-yellow-500.bg-yellow-500,
.bg-yellow-200.bg-yellow-200 *, .bg-yellow-300.bg-yellow-300 *,
.bg-yellow-400.bg-yellow-400 *, .bg-yellow-500.bg-yellow-500 *,
.hover\:bg-yellow-200:hover, .hover\:bg-yellow-200:hover *,
.hover\:bg-yellow-400:hover, .hover\:bg-yellow-500:hover,
.focus\:bg-yellow-200:focus { color: #101012 !important; }
/* ---- PALE STATUS / PILL FILLS → translucent tints --------------
bg-indigo-50 = Stock Lending tab, bg-indigo-100 = Credit/Debit Card,
bg-emerald-50 = "Paid" invoice pills, etc. All near-white in light mode. */
.bg-indigo-50, .bg-indigo-100,
.hover\:bg-indigo-50:hover { background-color: rgba(129,140,248,.16) !important; }
.bg-emerald-50, .bg-emerald-100, .bg-green-100 { background-color: rgba(52,211,153,.14) !important; }
.bg-red-50, .bg-red-100, .bg-rose-50, .bg-rose-100,
.hover\:bg-rose-50:hover { background-color: rgba(244,63,94,.15) !important; }
.bg-blue-50, .bg-blue-100 { background-color: rgba(96,165,250,.15) !important; }
.bg-purple-100 { background-color: rgba(192,132,252,.15) !important; }
/* brighten semantic text so it reads on dark */
.text-emerald-600 { color: #34d399 !important; }
.text-red-600, .text-rose-600 { color: #fb7185 !important; }
/* ---- the plan card's white gradient ---------------------------
bg-[linear-gradient(106deg,rgba(255,252,216,.65)_-38.69%,#FFF_97.09%)] */
[class*="bg-[linear-gradient"] {
background-image: linear-gradient(106deg, rgba(236,178,6,.16) -38.69%, rgba(236,178,6,.03) 97.09%) !important;
}
/* ---- ARBITRARY HEX FILLS --------------------------------------
Alpaca hardcodes some colors as Tailwind arbitrary values, which no
named-utility sweep catches. The symbol-search dropdown is bg-[#FFF]
with hover:bg-[#F8F8F8] rows. (bg-[#010101] and bg-[#4F46E5] are
already dark/saturated — left alone.) */
.bg-\[\#FFF\] { background-color: var(--al-surface) !important; }
.bg-\[\#F8F8F8\], .bg-\[\#e6e7ec\] { background-color: var(--al-raised) !important; }
.hover\:bg-\[\#F8F8F8\]:hover { background-color: var(--al-hover) !important; }
.bg-\[\#fefce880\] { background-color: var(--al-accent-soft) !important; }
/* yellow CTAs expressed as hex — same near-black label treatment */
.bg-\[\#fee546\].bg-\[\#fee546\],
.bg-\[\#fee546\].bg-\[\#fee546\] *,
.hover\:bg-\[\#fde020\]:hover,
.hover\:bg-\[\#fde020\]:hover * { color: #101012 !important; }
/* ---- disabled states ------------------------------------------ */
.disabled\:bg-cool-gray-100:disabled { background-color: var(--al-raised) !important; }
.disabled\:text-cool-gray-500:disabled { color: var(--al-dim) !important; }
/* ---- focus ---------------------------------------------------- */
.ring-yellow-200, .focus\:ring-yellow-200:focus { --tw-ring-color: rgba(236,178,6,.45) !important; }
.focus\:border-yellow-50:focus { border-color: var(--al-accent) !important; }
/* ---- form controls -------------------------------------------- */
input, select, textarea {
background-color: var(--al-raised) !important;
color: var(--al-text) !important;
border-color: var(--al-border) !important;
}
input::placeholder { color: var(--al-dim) !important; }
/* Buy/Sell buttons already use translucent rgba tints — untouched. */
Notes
- Covers Home, Positions, Orders, Activities, Balances, Interest Products, Transfers, Documents, the order ticket, and billing.
- Yellow buttons stay yellow only their labels flip to near-black.
- P/L green/red are brightened for dark backgrounds. Delete those two lines to keep Alpaca’s originals.
- Palette is all variables at the top; change
--al-surfaceand the rest follows.
The chart toolbar stays white. It’s TradingView in a blob: iframe whose root is data-theme="light" even though Alpaca already themed the plot inside it dark. Extensions can’t inject there, and switching it means changing an attribute, which CSS can’t do.
It’ll break occasionally these are internal class names, not a public API. If white reappears: Inspect → read the class → add a line.
Hopefully it’s helpful!