feat(website): finish responsive polish

Self-host the Inter and Space Grotesk variable fonts, tighten the mobile layout, hide oversized edge marks on narrow screens, and add keyboard focus plus reduced-motion safeguards. Exclude website and documentation-only changes from the desktop CI workflow.
This commit is contained in:
2026-06-15 19:55:01 +01:00
parent 072c3887cf
commit e14dbda41d
6 changed files with 66 additions and 18 deletions
+6
View File
@@ -3,7 +3,13 @@ name: CI
on: on:
push: push:
branches: [main] branches: [main]
paths-ignore:
- 'website/**'
- 'docs/**'
pull_request: pull_request:
paths-ignore:
- 'website/**'
- 'docs/**'
workflow_dispatch: workflow_dispatch:
concurrency: concurrency:
+16
View File
@@ -78,6 +78,12 @@ importers:
website: website:
dependencies: dependencies:
'@fontsource-variable/inter':
specifier: 5.2.8
version: 5.2.8
'@fontsource-variable/space-grotesk':
specifier: 5.2.10
version: 5.2.10
framer-motion: framer-motion:
specifier: ^12.38.0 specifier: ^12.38.0
version: 12.38.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) version: 12.38.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
@@ -357,6 +363,12 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@fontsource-variable/inter@5.2.8':
resolution: {integrity: sha512-kOfP2D+ykbcX/P3IFnokOhVRNoTozo5/JxhAIVYLpea/UBmCQ/YWPBfWIDuBImXX/15KH+eKh4xpEUyS2sQQGQ==}
'@fontsource-variable/space-grotesk@5.2.10':
resolution: {integrity: sha512-yJQO/o35/hAP3CFnpdFTwQku2yzJOae2HIpBmqkOVoxhhXJaQP3g+b6Jrz7u+eI7A5ZdCIf88uMWpBJdFiGr5w==}
'@img/colour@1.1.0': '@img/colour@1.1.0':
resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
@@ -1466,6 +1478,10 @@ snapshots:
'@esbuild/win32-x64@0.27.7': '@esbuild/win32-x64@0.27.7':
optional: true optional: true
'@fontsource-variable/inter@5.2.8': {}
'@fontsource-variable/space-grotesk@5.2.10': {}
'@img/colour@1.1.0': {} '@img/colour@1.1.0': {}
'@img/sharp-darwin-arm64@0.34.5': '@img/sharp-darwin-arm64@0.34.5':
-6
View File
@@ -20,12 +20,6 @@
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<meta property="og:url" content="https://phokus.jezz.wtf" /> <meta property="og:url" content="https://phokus.jezz.wtf" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Space+Grotesk:wght@500;600;700&display=swap"
rel="stylesheet"
/>
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
+2
View File
@@ -10,6 +10,8 @@
"typecheck": "tsc --noEmit" "typecheck": "tsc --noEmit"
}, },
"dependencies": { "dependencies": {
"@fontsource-variable/inter": "5.2.8",
"@fontsource-variable/space-grotesk": "5.2.10",
"framer-motion": "^12.38.0", "framer-motion": "^12.38.0",
"react": "^19.1.0", "react": "^19.1.0",
"react-dom": "^19.1.0" "react-dom": "^19.1.0"
+12 -12
View File
@@ -97,13 +97,13 @@ function Hero() {
</div> </div>
<div className="pointer-events-none absolute -left-24 top-8 -z-10 h-96 w-96 rounded-full bg-amber/[0.06] blur-3xl" /> <div className="pointer-events-none absolute -left-24 top-8 -z-10 h-96 w-96 rounded-full bg-amber/[0.06] blur-3xl" />
<div className="relative mx-auto w-full max-w-7xl px-6 py-20 lg:py-24"> <div className="relative mx-auto w-full max-w-7xl px-6 py-16 sm:py-20 lg:py-24">
<div className="max-w-2xl"> <div className="max-w-2xl">
<p className="mb-6 inline-flex items-center gap-2 rounded-full border border-edge bg-surface/80 px-3 py-1 text-xs font-medium text-muted backdrop-blur"> <p className="mb-6 inline-flex items-center gap-2 rounded-full border border-edge bg-surface/80 px-3 py-1 text-xs font-medium text-muted backdrop-blur">
<span className="h-1.5 w-1.5 rounded-full bg-amber" /> <span className="h-1.5 w-1.5 rounded-full bg-amber" />
Local-first · Windows desktop Local-first · Windows desktop
</p> </p>
<h1 className="font-display text-5xl font-semibold leading-[1.04] tracking-tight text-ink sm:text-6xl"> <h1 className="font-display text-[2.5rem] font-semibold leading-[1.06] tracking-tight text-ink sm:text-6xl sm:leading-[1.04]">
Your local media library, Your local media library,
<br /> <br />
made searchable. made searchable.
@@ -163,7 +163,7 @@ function LocalFirst() {
return ( return (
<section id="privacy" className="relative overflow-hidden border-y border-edge bg-surface"> <section id="privacy" className="relative overflow-hidden border-y border-edge bg-surface">
<EdgeMark side="left" /> <EdgeMark side="left" />
<div className="relative mx-auto max-w-7xl px-6 py-24 sm:py-28"> <div className="relative mx-auto max-w-7xl px-6 py-20 sm:py-28">
<div className="max-w-2xl"> <div className="max-w-2xl">
<SectionEyebrow label="Local-first" /> <SectionEyebrow label="Local-first" />
<h2 className="mt-4 font-display text-3xl font-semibold tracking-tight text-ink sm:text-4xl"> <h2 className="mt-4 font-display text-3xl font-semibold tracking-tight text-ink sm:text-4xl">
@@ -200,7 +200,7 @@ function SearchSection() {
return ( return (
<section id="search" className="relative overflow-hidden"> <section id="search" className="relative overflow-hidden">
<EdgeMark side="right" /> <EdgeMark side="right" />
<div className="relative mx-auto max-w-7xl px-6 py-24 sm:py-28"> <div className="relative mx-auto max-w-7xl px-6 py-20 sm:py-28">
<div className="max-w-2xl"> <div className="max-w-2xl">
<SectionEyebrow label="Search by meaning" /> <SectionEyebrow label="Search by meaning" />
<h2 className="mt-4 font-display text-3xl font-semibold tracking-tight text-ink sm:text-4xl"> <h2 className="mt-4 font-display text-3xl font-semibold tracking-tight text-ink sm:text-4xl">
@@ -247,7 +247,7 @@ function EdgeMark({ side }: { side: "left" | "right" }) {
viewBox="0 0 24 24" viewBox="0 0 24 24"
fill="none" fill="none"
aria-hidden="true" aria-hidden="true"
className={`pointer-events-none absolute top-1/2 h-[34rem] w-[34rem] -translate-y-1/2 text-ink opacity-[0.05] ${place}`} className={`pointer-events-none absolute top-1/2 hidden h-[34rem] w-[34rem] -translate-y-1/2 text-ink opacity-[0.05] sm:block ${place}`}
> >
<g <g
transform="translate(12 12)" transform="translate(12 12)"
@@ -273,7 +273,7 @@ function ExploreSection() {
return ( return (
<section id="explore" className="relative overflow-hidden border-t border-edge bg-surface"> <section id="explore" className="relative overflow-hidden border-t border-edge bg-surface">
<EdgeMark side="left" /> <EdgeMark side="left" />
<div className="relative mx-auto max-w-7xl px-6 py-24 sm:py-28"> <div className="relative mx-auto max-w-7xl px-6 py-20 sm:py-28">
<div className="grid items-center gap-10 lg:grid-cols-12"> <div className="grid items-center gap-10 lg:grid-cols-12">
<div className="lg:col-span-5"> <div className="lg:col-span-5">
<SectionEyebrow label="Explore & timeline" /> <SectionEyebrow label="Explore & timeline" />
@@ -310,7 +310,7 @@ function CurateSection() {
return ( return (
<section id="curate" className="relative overflow-hidden"> <section id="curate" className="relative overflow-hidden">
<EdgeMark side="right" /> <EdgeMark side="right" />
<div className="relative mx-auto max-w-7xl px-6 py-24 sm:py-28"> <div className="relative mx-auto max-w-7xl px-6 py-20 sm:py-28">
<div className="grid items-center gap-10 lg:grid-cols-12"> <div className="grid items-center gap-10 lg:grid-cols-12">
<figure className="order-2 overflow-hidden rounded-xl border border-edge bg-surface shadow-2xl shadow-black/50 lg:order-1 lg:col-span-7"> <figure className="order-2 overflow-hidden rounded-xl border border-edge bg-surface shadow-2xl shadow-black/50 lg:order-1 lg:col-span-7">
<Shot <Shot
@@ -347,7 +347,7 @@ function CleanupSection() {
return ( return (
<section id="cleanup" className="relative overflow-hidden border-t border-edge bg-surface"> <section id="cleanup" className="relative overflow-hidden border-t border-edge bg-surface">
<EdgeMark side="left" /> <EdgeMark side="left" />
<div className="relative mx-auto max-w-7xl px-6 py-24 sm:py-28"> <div className="relative mx-auto max-w-7xl px-6 py-20 sm:py-28">
<div className="max-w-2xl"> <div className="max-w-2xl">
<SectionEyebrow label="Clean up safely" /> <SectionEyebrow label="Clean up safely" />
<h2 className="mt-4 font-display text-3xl font-semibold tracking-tight text-ink sm:text-4xl"> <h2 className="mt-4 font-display text-3xl font-semibold tracking-tight text-ink sm:text-4xl">
@@ -381,7 +381,7 @@ function TechFactsSection() {
{ k: "License & build", v: "MIT, open source. The installer is currently unsigned — see the note below." }, { k: "License & build", v: "MIT, open source. The installer is currently unsigned — see the note below." },
]; ];
return ( return (
<section id="tech" className="relative mx-auto max-w-7xl px-6 py-24 sm:py-28"> <section id="tech" className="relative mx-auto max-w-7xl px-6 py-20 sm:py-28">
<div className="max-w-2xl"> <div className="max-w-2xl">
<SectionEyebrow label="The technical facts" /> <SectionEyebrow label="The technical facts" />
<h2 className="mt-4 font-display text-3xl font-semibold tracking-tight text-ink sm:text-4xl"> <h2 className="mt-4 font-display text-3xl font-semibold tracking-tight text-ink sm:text-4xl">
@@ -404,9 +404,9 @@ function DownloadSection() {
return ( return (
<section id="download" className="relative overflow-hidden border-t border-edge bg-surface"> <section id="download" className="relative overflow-hidden border-t border-edge bg-surface">
<EdgeMark side="right" /> <EdgeMark side="right" />
<div className="relative mx-auto max-w-3xl px-6 py-24 text-center sm:py-28"> <div className="relative mx-auto max-w-3xl px-6 py-20 text-center sm:py-28">
<PhokusMark className="mx-auto h-12 w-12 text-ink" dotClassName="fill-amber" /> <PhokusMark className="mx-auto h-12 w-12 text-ink" dotClassName="fill-amber" />
<h2 className="mt-6 font-display text-4xl font-semibold tracking-tight text-ink"> <h2 className="mt-6 font-display text-3xl font-semibold tracking-tight text-ink sm:text-4xl">
Point Phokus at a folder. Point Phokus at a folder.
</h2> </h2>
<p className="mt-4 text-lg leading-relaxed text-muted"> <p className="mt-4 text-lg leading-relaxed text-muted">
@@ -447,7 +447,7 @@ function Footer() {
<span className="font-display font-medium text-ink">Phokus</span> <span className="font-display font-medium text-ink">Phokus</span>
<span className="text-faint">· local-first media library</span> <span className="text-faint">· local-first media library</span>
</div> </div>
<div className="flex items-center gap-6"> <div className="flex flex-wrap items-center gap-x-6 gap-y-2">
<a href={REPO_URL} className="transition-colors hover:text-ink">GitHub</a> <a href={REPO_URL} className="transition-colors hover:text-ink">GitHub</a>
<a href="https://git.jezz.wtf/JezzWTF/phokus" className="transition-colors hover:text-ink">Gitea</a> <a href="https://git.jezz.wtf/JezzWTF/phokus" className="transition-colors hover:text-ink">Gitea</a>
<a href={`${REPO_URL}/blob/main/LICENSE`} className="transition-colors hover:text-ink">MIT</a> <a href={`${REPO_URL}/blob/main/LICENSE`} className="transition-colors hover:text-ink">MIT</a>
+30
View File
@@ -1,5 +1,21 @@
@import "tailwindcss"; @import "tailwindcss";
@font-face {
font-family: "Inter";
font-style: normal;
font-display: swap;
font-weight: 100 900;
src: url("@fontsource-variable/inter/files/inter-latin-wght-normal.woff2") format("woff2-variations");
}
@font-face {
font-family: "Space Grotesk";
font-style: normal;
font-display: swap;
font-weight: 300 700;
src: url("@fontsource-variable/space-grotesk/files/space-grotesk-latin-wght-normal.woff2") format("woff2-variations");
}
/* Phokus brand tokens — near-black surfaces, hairline edges, one amber accent /* Phokus brand tokens — near-black surfaces, hairline edges, one amber accent
(the iris focal point). Borrowed from the app, not copied literally. */ (the iris focal point). Borrowed from the app, not copied literally. */
@theme { @theme {
@@ -23,6 +39,7 @@ html {
} }
body { body {
margin: 0;
background-color: var(--color-canvas); background-color: var(--color-canvas);
color: var(--color-ink); color: var(--color-ink);
font-family: var(--font-sans); font-family: var(--font-sans);
@@ -30,8 +47,21 @@ body {
text-rendering: optimizeLegibility; text-rendering: optimizeLegibility;
} }
a:focus-visible {
outline: 2px solid var(--color-amber);
outline-offset: 4px;
}
@media (prefers-reduced-motion: reduce) { @media (prefers-reduced-motion: reduce) {
html { html {
scroll-behavior: auto; scroll-behavior: auto;
} }
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
} }