feat: upgrade typography - Plus Jakarta Sans headings, JetBrains Mono data, 14px base

Heading font: Plus Jakarta Sans (500/600/700) for all h1-h3, stat values, dialog titles, timer display, and wordmark.
Body font: Inter (400/500/600/700) unchanged but base bumped from 13px to 14px.
Mono font: JetBrains Mono replaces IBM Plex Mono for code and tabular data.
This commit is contained in:
Your Name
2026-02-17 22:06:48 +02:00
parent 3c8868c899
commit a300d85f6f
10 changed files with 34 additions and 33 deletions

View File

@@ -7,7 +7,7 @@
<title>ZeroClock</title>
<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=IBM+Plex+Mono:wght@400;500;600&family=IBM+Plex+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Plus+Jakarta+Sans:wght@500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
</head>
<body>
<div id="app"></div>

View File

@@ -50,7 +50,7 @@ async function handleDoubleClick() {
<!-- Left: App name -->
<div class="flex items-center">
<span
class="text-accent-text text-[0.6875rem] font-medium tracking-[0.1em] uppercase"
class="text-accent-text text-[0.6875rem] font-medium font-[family-name:var(--font-heading)] tracking-[0.1em] uppercase"
>
ZeroClock
</span>

View File

@@ -30,7 +30,8 @@
/* Fonts */
--font-sans: 'Inter', system-ui, sans-serif;
--font-mono: 'IBM Plex Mono', monospace;
--font-heading: 'Plus Jakarta Sans', 'Inter', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', 'IBM Plex Mono', monospace;
}
@layer base {
@@ -48,7 +49,7 @@
body {
font-family: var(--font-sans);
font-size: 0.8125rem;
font-size: 0.875rem;
line-height: 1.5;
background-color: var(--color-bg-base);
color: var(--color-text-primary);

View File

@@ -14,7 +14,7 @@
<template v-else>
<!-- Greeting header -->
<div class="mb-8">
<p class="text-lg text-text-secondary">{{ greeting }}</p>
<p class="text-xl font-[family-name:var(--font-heading)] text-text-secondary">{{ greeting }}</p>
<p class="text-xs text-text-tertiary mt-1">{{ formattedDate }}</p>
</div>
@@ -22,25 +22,25 @@
<div class="grid grid-cols-4 gap-6 mb-8">
<div>
<p class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Today</p>
<p class="text-[1.25rem] font-mono text-accent-text font-medium">{{ formatDuration(todayStats.totalSeconds) }}</p>
<p class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">{{ formatDuration(todayStats.totalSeconds) }}</p>
</div>
<div>
<p class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">This Week</p>
<p class="text-[1.25rem] font-mono text-accent-text font-medium">{{ formatDuration(weekStats.totalSeconds) }}</p>
<p class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">{{ formatDuration(weekStats.totalSeconds) }}</p>
</div>
<div>
<p class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">This Month</p>
<p class="text-[1.25rem] font-mono text-accent-text font-medium">{{ formatDuration(monthStats.totalSeconds) }}</p>
<p class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">{{ formatDuration(monthStats.totalSeconds) }}</p>
</div>
<div>
<p class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Active Projects</p>
<p class="text-[1.25rem] font-mono text-accent-text font-medium">{{ activeProjectsCount }}</p>
<p class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">{{ activeProjectsCount }}</p>
</div>
</div>
<!-- Weekly chart -->
<div class="mb-8">
<h2 class="text-[1rem] font-medium text-text-primary mb-4">Weekly Hours</h2>
<h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">Weekly Hours</h2>
<div class="h-48">
<Bar v-if="chartData" :data="chartData" :options="chartOptions" />
</div>
@@ -49,7 +49,7 @@
<!-- Recent entries -->
<div>
<div class="flex items-center justify-between mb-4">
<h2 class="text-[1rem] font-medium text-text-primary">Recent Entries</h2>
<h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary">Recent Entries</h2>
<router-link to="/entries" class="text-xs text-text-tertiary hover:text-text-secondary transition-colors">View all</router-link>
</div>

View File

@@ -1,6 +1,6 @@
<template>
<div class="p-6">
<h1 class="text-[1.5rem] font-medium text-text-primary mb-6">Entries</h1>
<h1 class="text-[1.75rem] font-bold font-[family-name:var(--font-heading)] tracking-tight text-text-primary mb-6">Entries</h1>
<!-- Filters -->
<div class="bg-bg-surface rounded-lg p-4 mb-6 flex flex-wrap items-end gap-4">
@@ -133,7 +133,7 @@
@click.self="closeEditDialog"
>
<div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-md mx-4 p-6 animate-modal-enter">
<h2 class="text-[1rem] font-semibold text-text-primary mb-4">Edit Entry</h2>
<h2 class="text-[1.125rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">Edit Entry</h2>
<form @submit.prevent="handleEdit" class="space-y-4">
<!-- Project -->
@@ -213,7 +213,7 @@
@click.self="cancelDelete"
>
<div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-sm mx-4 p-6 animate-modal-enter">
<h2 class="text-[1rem] font-semibold text-text-primary mb-2">Delete Entry</h2>
<h2 class="text-[1.125rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-2">Delete Entry</h2>
<p class="text-[0.75rem] text-text-secondary mb-6">
Are you sure you want to delete this time entry? This action cannot be undone.
</p>

View File

@@ -1,6 +1,6 @@
<template>
<div class="p-6">
<h1 class="text-[1.5rem] font-medium text-text-primary mb-6">Invoices</h1>
<h1 class="text-[1.75rem] font-bold font-[family-name:var(--font-heading)] tracking-tight text-text-primary mb-6">Invoices</h1>
<!-- View tabs -->
<div class="flex gap-6 mb-6 border-b border-border-subtle">
@@ -120,7 +120,7 @@
<!-- Create View -->
<div v-else-if="view === 'create'" class="max-w-lg">
<h2 class="text-[1rem] font-medium text-text-primary mb-4">Create Invoice</h2>
<h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">Create Invoice</h2>
<form @submit.prevent="handleCreate" class="space-y-4">
<!-- Client -->
@@ -247,7 +247,7 @@
<div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-2xl mx-4 p-6 max-h-[90vh] overflow-y-auto animate-modal-enter">
<div class="flex items-start justify-between mb-6">
<div>
<h2 class="text-[1.5rem] font-medium text-text-primary">{{ selectedInvoice?.invoice_number }}</h2>
<h2 class="text-[1.75rem] font-bold font-[family-name:var(--font-heading)] tracking-tight text-text-primary">{{ selectedInvoice?.invoice_number }}</h2>
<p class="text-[0.75rem] text-text-secondary">{{ getClientName(selectedInvoice?.client_id || 0) }}</p>
</div>
<button
@@ -315,7 +315,7 @@
@click.self="showDeleteDialog = false"
>
<div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-sm mx-4 p-6 animate-modal-enter">
<h2 class="text-[1rem] font-semibold text-text-primary mb-2">Delete Invoice</h2>
<h2 class="text-[1.125rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-2">Delete Invoice</h2>
<p class="text-[0.75rem] text-text-secondary mb-6">
Are you sure you want to delete invoice "{{ invoiceToDelete?.invoice_number }}"? This action cannot be undone.
</p>

View File

@@ -2,7 +2,7 @@
<div class="p-6">
<!-- Header -->
<div class="flex items-center justify-between mb-6">
<h1 class="text-[1.5rem] font-medium text-text-primary">Projects</h1>
<h1 class="text-[1.75rem] font-bold font-[family-name:var(--font-heading)] tracking-tight text-text-primary">Projects</h1>
<button
@click="openCreateDialog"
class="px-3 py-1.5 bg-accent text-bg-base text-xs font-medium rounded-lg hover:bg-accent-hover transition-colors duration-150"
@@ -72,7 +72,7 @@
@click.self="closeDialog"
>
<div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-md mx-4 p-6 animate-modal-enter">
<h2 class="text-[1rem] font-semibold text-text-primary mb-4">
<h2 class="text-[1.125rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">
{{ editingProject ? 'Edit Project' : 'Create Project' }}
</h2>
@@ -175,7 +175,7 @@
@click.self="cancelDelete"
>
<div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-sm mx-4 p-6 animate-modal-enter">
<h2 class="text-[1rem] font-semibold text-text-primary mb-2">Delete Project</h2>
<h2 class="text-[1.125rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-2">Delete Project</h2>
<p class="text-[0.75rem] text-text-secondary mb-6">
Are you sure you want to delete "{{ projectToDelete?.name }}"? This action cannot be undone.
</p>

View File

@@ -1,6 +1,6 @@
<template>
<div class="p-6">
<h1 class="text-[1.5rem] font-medium text-text-primary mb-6">Reports</h1>
<h1 class="text-[1.75rem] font-bold font-[family-name:var(--font-heading)] tracking-tight text-text-primary mb-6">Reports</h1>
<!-- Date Range Selector -->
<div class="bg-bg-surface rounded-lg p-4 mb-6 flex flex-wrap items-end gap-4">
@@ -38,21 +38,21 @@
<div class="grid grid-cols-3 gap-6 mb-8">
<div>
<p class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Total Hours</p>
<p class="text-[1.25rem] font-mono text-accent-text font-medium">{{ formatHours(reportData.totalSeconds) }}</p>
<p class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">{{ formatHours(reportData.totalSeconds) }}</p>
</div>
<div>
<p class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Earnings</p>
<p class="text-[1.25rem] font-mono text-accent-text font-medium">${{ reportData.totalEarnings?.toFixed(2) || '0.00' }}</p>
<p class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">${{ reportData.totalEarnings?.toFixed(2) || '0.00' }}</p>
</div>
<div>
<p class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1">Projects</p>
<p class="text-[1.25rem] font-mono text-accent-text font-medium">{{ reportData.byProject?.length || 0 }}</p>
<p class="text-[1.25rem] font-[family-name:var(--font-heading)] text-accent-text font-medium">{{ reportData.byProject?.length || 0 }}</p>
</div>
</div>
<!-- Chart -->
<div class="mb-8">
<h2 class="text-[1rem] font-medium text-text-primary mb-4">Hours by Project</h2>
<h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">Hours by Project</h2>
<div class="h-64">
<Bar v-if="chartData" :data="chartData" :options="chartOptions" />
<div v-else class="flex flex-col items-center justify-center h-full">
@@ -64,7 +64,7 @@
<!-- Project Breakdown -->
<div>
<h2 class="text-[1rem] font-medium text-text-primary mb-4">Breakdown</h2>
<h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">Breakdown</h2>
<div v-if="reportData.byProject && reportData.byProject.length > 0">
<div

View File

@@ -28,7 +28,7 @@
<div class="flex-1 p-6 overflow-y-auto">
<!-- General -->
<div v-if="activeTab === 'general'">
<h2 class="text-[1.125rem] font-medium text-text-primary mb-6">General</h2>
<h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-6">General</h2>
<div class="flex items-center justify-between">
<div>
@@ -57,7 +57,7 @@
<!-- Timer -->
<div v-if="activeTab === 'timer'">
<h2 class="text-[1.125rem] font-medium text-text-primary mb-6">Timer</h2>
<h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-6">Timer</h2>
<div class="space-y-5">
<!-- Idle Detection toggle -->
@@ -105,7 +105,7 @@
<!-- Billing -->
<div v-if="activeTab === 'billing'">
<h2 class="text-[1.125rem] font-medium text-text-primary mb-6">Billing</h2>
<h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-6">Billing</h2>
<div class="flex items-center justify-between">
<div>
@@ -129,7 +129,7 @@
<!-- Data -->
<div v-if="activeTab === 'data'">
<h2 class="text-[1.125rem] font-medium text-text-primary mb-6">Data</h2>
<h2 class="text-[1.25rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-6">Data</h2>
<div class="space-y-6">
<!-- Export -->
@@ -173,7 +173,7 @@
@click.self="showClearDataDialog = false"
>
<div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-sm mx-4 p-6 animate-modal-enter">
<h2 class="text-[1rem] font-semibold text-text-primary mb-2">Clear All Data</h2>
<h2 class="text-[1.125rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-2">Clear All Data</h2>
<p class="text-[0.75rem] text-text-secondary mb-4">
Are you sure? This action cannot be undone.
</p>

View File

@@ -2,7 +2,7 @@
<div class="p-6">
<!-- Hero timer display -->
<div class="text-center pt-4 pb-8">
<p class="text-[3rem] font-mono font-medium tracking-wider mb-6">
<p class="text-[3.5rem] font-medium font-[family-name:var(--font-heading)] tracking-tighter mb-6">
<span class="text-text-primary">{{ timerParts.hours }}</span>
<span :class="timerStore.isRunning ? 'text-accent-text animate-pulse-colon' : 'text-text-primary'">:</span>
<span class="text-text-primary">{{ timerParts.minutes }}</span>