From c3a01d217dfd8f300a153437a32e5ca1f584c175 Mon Sep 17 00:00:00 2001 From: jake Date: Sat, 21 Mar 2026 10:37:04 +0000 Subject: [PATCH] =?UTF-8?q?agent:=20tokens=20=E2=80=94=20align=20tokens=20?= =?UTF-8?q?to=20brand=20guidelines,=20bundle=20fonts,=20add=20zones=20and?= =?UTF-8?q?=20motion=20tokens?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- src/app.css | 163 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 133 insertions(+), 30 deletions(-) diff --git a/src/app.css b/src/app.css index e5c0d2c..f19b45c 100644 --- a/src/app.css +++ b/src/app.css @@ -1,4 +1,40 @@ -@import url('https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300..700;1,9..40,300..700&family=Instrument+Serif:ital@0;1&display=swap'); +/* === Bundled Fonts — offline-first === */ +@font-face { + font-family: 'Lexend'; + src: url('/fonts/lexend-variable.woff2') format('woff2'); + font-weight: 100 900; + font-display: swap; +} + +@font-face { + font-family: 'Instrument Serif'; + src: url('/fonts/instrument-serif-italic.woff2') format('woff2'); + font-style: italic; + font-weight: 400; + font-display: swap; +} + +@font-face { + font-family: 'JetBrains Mono'; + src: url('/fonts/jetbrains-mono.woff2') format('woff2'); + font-weight: 100 800; + font-display: swap; +} + +@font-face { + font-family: 'Atkinson Hyperlegible Next'; + src: url('/fonts/atkinson-hyperlegible-next.woff2') format('woff2'); + font-weight: 400 700; + font-display: swap; +} + +@font-face { + font-family: 'OpenDyslexic'; + src: url('/fonts/opendyslexic.woff2') format('woff2'); + font-weight: 400 700; + font-display: swap; +} + @import "tailwindcss"; /* === Kon Design Tokens === */ @@ -38,6 +74,18 @@ --radius-lg: 12px; --radius-xl: 16px; --title-size: 26px; + + /* Typography */ + --font-family-body: 'Lexend', system-ui, sans-serif; + --font-family-display: 'Instrument Serif', serif; + --font-family-mono: 'JetBrains Mono', monospace; + --font-size-body: 16px; + --line-height-body: 1.5; + --letter-spacing-body: 0; + + /* Motion */ + --duration-ui: 150ms; + --duration-decorative: 300ms; } /* === Button Component Classes === */ @@ -46,7 +94,7 @@ .btn-lg { @apply px-4 py-2 text-[13px]; } /* === Light theme overrides === */ -html.light { +:root[data-theme="light"] { --color-bg: #faf8f5; --color-bg-elevated: #f3f0eb; --color-bg-card: #ffffff; @@ -58,28 +106,66 @@ html.light { --color-text-secondary: #5c574d; --color-text-tertiary: #8a8578; - --color-accent: #d4956a; - --color-accent-hover: #c48a60; - --color-accent-subtle: #d4956a10; - --color-accent-glow: #d4956a25; + --color-accent: #b87a4a; + --color-accent-hover: #a06b3e; + --color-accent-subtle: #b87a4a10; + --color-accent-glow: #b87a4a20; - --color-success: #4a9e6a; - --color-danger: #d45454; - --color-warning: #c9a84e; + --color-success: #3d8a5a; + --color-danger: #c44d4d; + --color-warning: #b89a3e; --color-sidebar: #f5f2ed; --color-nav-active: #eae6e0; --color-hover: #ede9e3; } -html.light ::-webkit-scrollbar-thumb { +:root[data-theme="light"] ::-webkit-scrollbar-thumb { background: #d0ccc4; } -html.light ::-webkit-scrollbar-thumb:hover { +:root[data-theme="light"] ::-webkit-scrollbar-thumb:hover { background: #b8b3aa; } -html.light .grain::after { - opacity: 0.015; + +/* === Sensory Zones — Dark Theme === */ +/* Zones tint surfaces only. Accent tokens (amber) stay constant across all zones — + the brand colour is the constant, the environment is the variable. */ +:root[data-zone="cave"] { + --color-bg: #0f1214; + --color-bg-elevated: #141a1e; + --color-bg-card: #171f24; + --color-sidebar: #0d1012; +} +:root[data-zone="energy"] { + --color-bg: #100e0b; + --color-bg-elevated: #1c1815; + --color-bg-card: #211d18; + --color-sidebar: #141110; +} +:root[data-zone="reset"] { + --color-bg: #0e100e; + --color-bg-elevated: #161a16; + --color-bg-card: #1a1f1a; + --color-sidebar: #0c0e0c; +} +/* === Sensory Zones — Light Theme === */ +:root[data-theme="light"][data-zone="cave"] { + --color-bg: #f0f5f7; + --color-bg-elevated: #e8f0f2; + --color-bg-card: #f5fafc; + --color-sidebar: #eaf2f4; +} +:root[data-theme="light"][data-zone="energy"] { + --color-bg: #faf7f3; + --color-bg-elevated: #f5f0e8; + --color-bg-card: #fffcf7; + --color-sidebar: #f5f0ea; +} +:root[data-theme="light"][data-zone="reset"] { + --color-bg: #f3f7f2; + --color-bg-elevated: #edf2ea; + --color-bg-card: #f8fcf6; + --color-sidebar: #eff4ec; } /* === Base === */ @@ -90,9 +176,10 @@ html, body { overflow: hidden; background: var(--color-bg); color: var(--color-text); - font-family: "DM Sans", -apple-system, BlinkMacSystemFont, system-ui, sans-serif; - font-size: 14px; - line-height: 1.5; + font-family: var(--font-family-body); + font-size: var(--font-size-body); + line-height: var(--line-height-body); + letter-spacing: var(--letter-spacing-body); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; user-select: none; @@ -100,13 +187,13 @@ html, body { /* === Display font === */ .font-display { - font-family: "Instrument Serif", Georgia, "Times New Roman", serif; + font-family: var(--font-family-display); } /* === Transcript font — optimised for reading === */ .font-transcript { - font-family: "DM Sans", system-ui, sans-serif; - font-size: var(--font-size-transcript, 15px); + font-family: var(--font-family-body); + font-size: var(--text-transcript, 16px); line-height: 1.85; letter-spacing: 0.01em; font-feature-settings: "liga" 1, "kern" 1; @@ -119,9 +206,13 @@ html, body { inset: 0; pointer-events: none; opacity: 0.025; - background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); + background-image: url('/textures/grain.png'); + background-repeat: repeat; + background-size: 200px 200px; z-index: 50; - pointer-events: none !important; +} +:root[data-theme="light"] .grain::after { + opacity: 0.015; } /* === Scrollbar — thin, appears on hover === */ @@ -142,7 +233,7 @@ html, body { /* === Smooth transitions (global) === */ * { transition-property: background-color, border-color, color, opacity, box-shadow; - transition-duration: 150ms; + transition-duration: var(--duration-ui); transition-timing-function: cubic-bezier(0.2, 0.8, 0.2, 1); } @@ -191,7 +282,7 @@ textarea, input, [data-no-transition] { } .animate-fade-in { - animation: fade-in 200ms ease-out; + animation: fade-in var(--duration-decorative) ease-out; } .animate-pulse-soft { @@ -203,7 +294,7 @@ textarea, input, [data-no-transition] { } .animate-slide-up { - animation: slide-up 250ms ease-out; + animation: slide-up var(--duration-decorative) ease-out; } .animate-breathe { @@ -233,7 +324,7 @@ textarea, input, [data-no-transition] { } .animate-slide-in-right { - animation: slide-in-right 200ms ease-out; + animation: slide-in-right var(--duration-decorative) ease-out; } .animate-highlight-warm { border-left: 3px solid transparent; @@ -254,14 +345,14 @@ textarea, input, [data-no-transition] { animation: glow-pulse 700ms ease-out; } -html.light .animate-glow-pulse { +:root[data-theme="light"] .animate-glow-pulse { animation: glow-pulse-light 700ms ease-out; } @keyframes glow-pulse-light { - 0% { box-shadow: 0 0 0 0 rgba(212, 149, 106, 0); } - 30% { box-shadow: 0 0 20px 4px rgba(212, 149, 106, 0.3), inset 0 0 12px rgba(212, 149, 106, 0.06); } - 100% { box-shadow: 0 0 0 0 rgba(212, 149, 106, 0); } + 0% { box-shadow: 0 0 0 0 rgba(184, 122, 74, 0); } + 30% { box-shadow: 0 0 20px 4px rgba(184, 122, 74, 0.3), inset 0 0 12px rgba(184, 122, 74, 0.06); } + 100% { box-shadow: 0 0 0 0 rgba(184, 122, 74, 0); } } /* Float window entrance */ @@ -271,7 +362,7 @@ html.light .animate-glow-pulse { } .animate-float-enter { - animation: float-enter 200ms ease-out; + animation: float-enter var(--duration-decorative) ease-out; } /* === Custom titlebar buttons === */ @@ -305,3 +396,15 @@ html.light .animate-glow-pulse { transition-duration: 0.01ms !important; } } + +/* === Data-attribute reduce-motion support === */ +:root[data-reduce-motion="true"], +:root[data-reduce-motion="true"] *, +:root[data-reduce-motion="true"] *::before, +:root[data-reduce-motion="true"] *::after { + --duration-ui: 0ms; + --duration-decorative: 0ms; + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; +}