diff --git a/src/app/globals.css b/src/app/globals.css
index 9369a3e..bc92033 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -13,6 +13,14 @@
--color-foreground: #e3e3e3;
}
+html {
+ /* Opt the page into dark-mode UA styling so native form controls,
+ scrollbars, autofill highlights, and the iOS Safari status-bar tint
+ pick up dark theming. bg-zinc-950 on only paints the canvas
+ — UA chrome reads color-scheme. */
+ color-scheme: dark;
+}
+
body {
/* No background here — the page canvas colour is bg-zinc-950 on
(layout.tsx) and the fixed Background component paints over
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 79d5016..2551f4f 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,4 +1,4 @@
-import type { Metadata } from "next";
+import type { Metadata, Viewport } from "next";
import { Geist } from "next/font/google";
import "./globals.css";
import Background from "@/components/Background";
@@ -10,6 +10,13 @@ const geistSans = Geist({
subsets: ["latin"],
});
+// Next 15 moved themeColor out of metadata into a dedicated viewport export.
+// Matches bg-zinc-950 (#09090b) so mobile browser chrome (iOS Safari address
+// bar, Android Chrome notification bar) blends into the page background.
+export const viewport: Viewport = {
+ themeColor: "#09090b",
+};
+
// Public URL is hardcoded because the app is reverse-proxied at a fixed
// path (swagcounty.com/shuffleify) and basePath alone doesn't give the
// OpenGraph crawler an absolute URL. If shuffleify ever moves to its own
@@ -67,7 +74,7 @@ export default function RootLayout({
href="https://github.com/LLMATIONS/shuffleify"
target="_blank"
rel="noreferrer noopener"
- className="text-zinc-400 underline transition-colors hover:text-zinc-200"
+ className="inline-block py-1.5 text-zinc-400 underline transition-colors hover:text-zinc-200 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand"
>
GitHub
@@ -76,7 +83,7 @@ export default function RootLayout({
Bug reports, kind words, weird ideas →{" "}
nerds@swagcounty.com
diff --git a/src/app/logged-out/page.tsx b/src/app/logged-out/page.tsx
index c6dd72d..74995cf 100644
--- a/src/app/logged-out/page.tsx
+++ b/src/app/logged-out/page.tsx
@@ -34,7 +34,7 @@ export default function LoggedOut() {
href="https://www.spotify.com/account/apps/"
target="_blank"
rel="noreferrer noopener"
- className="underline transition-colors hover:text-brand-hover"
+ className="inline-block py-0.5 underline decoration-2 underline-offset-2 transition-colors hover:text-brand-hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand"
>
authorized apps list
{" "}
@@ -46,7 +46,7 @@ export default function LoggedOut() {
body={
Log in again
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 57b8218..77de550 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -70,7 +70,7 @@ export default async function Home({
<>
Log in with Spotify
diff --git a/src/components/picker/PlaylistRow.tsx b/src/components/picker/PlaylistRow.tsx
index 43344c6..8f14e36 100644
--- a/src/components/picker/PlaylistRow.tsx
+++ b/src/components/picker/PlaylistRow.tsx
@@ -58,7 +58,7 @@ export function PlaylistRow({
type="button"
onClick={onShuffle}
disabled={locked}
- className={`${CTA_CLASS} shrink-0 px-2 py-2 text-xs disabled:cursor-not-allowed disabled:opacity-50 sm:min-w-[9.5rem] sm:px-4 sm:text-sm`}
+ className={`${CTA_CLASS} shrink-0 min-h-[44px] px-3 py-2 text-xs disabled:cursor-not-allowed disabled:opacity-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand sm:min-w-[9.5rem] sm:px-4 sm:text-sm`}
>
{isShuffling ? "Shuffling…" : "Shuffle for real"}