diff --git a/docs/THEMING.md b/docs/THEMING.md index b3e57e6..3ad501d 100644 --- a/docs/THEMING.md +++ b/docs/THEMING.md @@ -6,16 +6,27 @@ How color, light/dark mode, section tone, and animation work on this site. ## Palette -From the spec, exposed as CSS variables in `src/styles/themes.css` and mapped to -Tailwind utilities in `src/styles/global.css`: +The site uses the Patiun LLC brand palette (shared by Patiun and Greg Kilmer), +exposed as CSS variables in `src/styles/global.css` under `@theme`: | Token | Value | Meaning | |---|---|---| -| `--color-slate` | `#1E293B` | Professional confidence (primary) | -| `--color-amber` | `#F59E0B` | Warm accent (the making/creative side) | -| `--color-teal` | `#699a94` | Soft teal (secondary, favorite) | -| `--color-ink` | `#0F172A` | Near-black text on light | -| `--color-cream` | `#FFFBEB` | Cream-white text on dark | +| `--color-teal` | `#14A39A` | Patiun Teal, primary: buttons, fills, the glyph | +| `--color-teal-bright` | `#2BC2B7` | Teal text and links on dark grounds | +| `--color-teal-deep` | `#0F8C84` | Teal marks on light grounds | +| `--color-slate-teal` | `#2D4A58` | Dark end of the Tide gradient | +| `--color-gold` | `#C9A24A` | Alchemist Gold: stars, rules, seal lines (never a large fill) | +| `--color-gold-bright` | `#D8B35A` | Gold text on dark grounds | +| `--color-gold-deep` | `#8A6516` | Gold text under 24px on Starlight | +| `--color-violet` / `--color-indigo` | `#6A2FE0` / `#3B1F8F` | Nebula light only, never text | +| `--color-midnight` | `#131C2B` | Panels, tiles, browser theme color | +| `--color-sky` | `#0E1522` | Night-sky ground | +| `--color-starlight` | `#F4F2ED` | Text on dark; paper ground | + +The semantic Tailwind tokens (`--color-accent`, `--color-surface`, ...) resolve +at `:root`, so content sections render with the Starlight values in +`themes.css`. Night-sky bands (the nav and page heroes) carry the `.on-sky` +class, which re-points accent and gold to their on-dark values. Brand colors are fixed. **Semantic** tokens (`--surface`, `--text`, `--accent`, `--secondary`, `--border`, ...) resolve differently per theme + section, and are @@ -118,9 +129,33 @@ reduce)')` before drawing, so even JS-driven motion is skipped. Self-hosted variable fonts via Fontsource (woff2, no external requests): -- **Headings / UI:** Plus Jakarta Sans Variable (geometric sans) -- **Body:** Inter Variable -- **Mono / kickers / quotes:** JetBrains Mono Variable +- **Headings, names, card titles:** Cinzel Variable (`font-display`, used by + `h1`-`h4` automatically). Open tracking, never for paragraphs. +- **Body and UI:** Montserrat Variable (`font-sans`, `font-body`). +- **Eyebrows / kickers:** Montserrat uppercase with wide tracking (`font-eyebrow`). +- **Code-like blocks only:** JetBrains Mono Variable (`font-mono`). Font sizes use `clamp()` for fluid scaling (see the `h1`-`h4` rules in `global.css`). + +--- + +## Icons and motifs + +- **Icons:** `` (Astro) and `` (React + islands) render the Patiun stroke icon set in `src/lib/brand-icons.ts`. Call + sites can use either the brand name (`dice`) or the mdi name (`dice-multiple`); + `brandIconAliases` maps one to the other. Only third-party logos (GitHub, + LinkedIn, Steam, ...) fall back to mdi. The gold star accent uses + `--icon-gold` (deep gold on Starlight, flat gold inside `.on-sky`). The file is + generated from the brand source (`newicons.py`); add icons there. +- **Motifs:** `` shows a brand motif from `public/motifs/`, + copied from the brand files with ring text outlined to paths. `-light` files + are the Starlight recolor. One focal motif per surface, kept faint. Every + page carries at least one seal: night-sky heroes have the turning layered + seal, and pages without a hero use `` behind the header. +- **Shape:** cards and panels have 10px corners (`--radius-xl`/`2xl`/`3xl` are + pinned to 10px); buttons and tags are pills. The Patiun seal is never shown + below 72px (nav and footer use 72px). +- **Gold accents:** image frames, quote bars, dividers and rules use + `--color-gold`; teal stays for links, buttons and icons. diff --git a/package-lock.json b/package-lock.json index 777e9dd..11d5bf2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,9 +12,9 @@ "@astrojs/mdx": "^7.0.2", "@astrojs/node": "^11.0.2", "@astrojs/react": "^6.0.2", - "@fontsource-variable/inter": "^5.2.8", + "@fontsource-variable/cinzel": "^5.3.0", "@fontsource-variable/jetbrains-mono": "^5.2.8", - "@fontsource-variable/plus-jakarta-sans": "^5.2.8", + "@fontsource-variable/montserrat": "^5.3.0", "@iconify-json/mdi": "^1.2.3", "@tailwindcss/vite": "^4.3.2", "@types/nodemailer": "^8.0.1", @@ -1389,10 +1389,10 @@ "node": ">=18" } }, - "node_modules/@fontsource-variable/inter": { + "node_modules/@fontsource-variable/cinzel": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@fontsource-variable/inter/-/inter-5.3.0.tgz", - "integrity": "sha512-OupL48va4JNofb97w6NYeF9S7W/kHNKM0Er8Dem5nqi4jeOLrVJDoE8tZEpnMJmtkvNbB1EIPPwHcdkF6b1oUA==", + "resolved": "https://registry.npmjs.org/@fontsource-variable/cinzel/-/cinzel-5.3.0.tgz", + "integrity": "sha512-eFcU0TwaAP5QESF2pV8VoOPJJXJ6sSGm/6mXMwqTdMBPAJMaLhfa6oISHuOtFeddsoHP9RYm4Io0j1j3mNEz2Q==", "license": "OFL-1.1", "funding": { "url": "https://github.com/sponsors/ayuhito" @@ -1407,10 +1407,10 @@ "url": "https://github.com/sponsors/ayuhito" } }, - "node_modules/@fontsource-variable/plus-jakarta-sans": { + "node_modules/@fontsource-variable/montserrat": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@fontsource-variable/plus-jakarta-sans/-/plus-jakarta-sans-5.3.0.tgz", - "integrity": "sha512-/l/4r0yyWK9JzAlmA0LiYgGgmJe/Gswt4jTJEzr5QhJfwMbvJZDmYWyW0M4X7yCK69BajMVlV/Lx8g7WDc1+sw==", + "resolved": "https://registry.npmjs.org/@fontsource-variable/montserrat/-/montserrat-5.3.0.tgz", + "integrity": "sha512-7PaZoxaxrWLAyrhO46v65An9LhUhfkTExWLhfbywYZCnZEgg/W1rEHnlNmZKjNZ3nJTVYyicqxlJt10z/26yTA==", "license": "OFL-1.1", "funding": { "url": "https://github.com/sponsors/ayuhito" diff --git a/package.json b/package.json index d26a1b1..f432565 100644 --- a/package.json +++ b/package.json @@ -19,9 +19,9 @@ "@astrojs/mdx": "^7.0.2", "@astrojs/node": "^11.0.2", "@astrojs/react": "^6.0.2", - "@fontsource-variable/inter": "^5.2.8", + "@fontsource-variable/cinzel": "^5.3.0", "@fontsource-variable/jetbrains-mono": "^5.2.8", - "@fontsource-variable/plus-jakarta-sans": "^5.2.8", + "@fontsource-variable/montserrat": "^5.3.0", "@iconify-json/mdi": "^1.2.3", "@tailwindcss/vite": "^4.3.2", "@types/nodemailer": "^8.0.1", diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png deleted file mode 100644 index eb0469d..0000000 Binary files a/public/android-chrome-192x192.png and /dev/null differ diff --git a/public/android-chrome-512x512.png b/public/android-chrome-512x512.png deleted file mode 100644 index 9f5102f..0000000 Binary files a/public/android-chrome-512x512.png and /dev/null differ diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png index d235de2..30ffa99 100644 Binary files a/public/apple-touch-icon.png and b/public/apple-touch-icon.png differ diff --git a/public/brand/patiun-seal.svg b/public/brand/patiun-seal.svg new file mode 100644 index 0000000..60c4a59 --- /dev/null +++ b/public/brand/patiun-seal.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/favicon-16.png b/public/favicon-16.png new file mode 100644 index 0000000..15b45bd Binary files /dev/null and b/public/favicon-16.png differ diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png deleted file mode 100644 index d500618..0000000 Binary files a/public/favicon-16x16.png and /dev/null differ diff --git a/public/favicon-32.png b/public/favicon-32.png new file mode 100644 index 0000000..832fc93 Binary files /dev/null and b/public/favicon-32.png differ diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png deleted file mode 100644 index 307e061..0000000 Binary files a/public/favicon-32x32.png and /dev/null differ diff --git a/public/favicon-48.png b/public/favicon-48.png new file mode 100644 index 0000000..c61adc2 Binary files /dev/null and b/public/favicon-48.png differ diff --git a/public/favicon.ico b/public/favicon.ico index d698140..46e2cb4 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/public/favicon.svg b/public/favicon.svg index f7aa549..d9761cb 100644 --- a/public/favicon.svg +++ b/public/favicon.svg @@ -1,15 +1 @@ - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/public/icon-192.png b/public/icon-192.png new file mode 100644 index 0000000..25a1055 Binary files /dev/null and b/public/icon-192.png differ diff --git a/public/icon-512.png b/public/icon-512.png new file mode 100644 index 0000000..fcada0b Binary files /dev/null and b/public/icon-512.png differ diff --git a/public/icon-maskable-192.png b/public/icon-maskable-192.png new file mode 100644 index 0000000..2d0d1da Binary files /dev/null and b/public/icon-maskable-192.png differ diff --git a/public/icon-maskable-512.png b/public/icon-maskable-512.png new file mode 100644 index 0000000..c44a1c1 Binary files /dev/null and b/public/icon-maskable-512.png differ diff --git a/public/motifs/astrolabe.svg b/public/motifs/astrolabe.svg new file mode 100644 index 0000000..a5e2fbe --- /dev/null +++ b/public/motifs/astrolabe.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/public/motifs/craft-seal-print-light.svg b/public/motifs/craft-seal-print-light.svg new file mode 100644 index 0000000..a836a71 --- /dev/null +++ b/public/motifs/craft-seal-print-light.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/public/motifs/kepler-nest-seal-light.svg b/public/motifs/kepler-nest-seal-light.svg new file mode 100644 index 0000000..e97bee7 --- /dev/null +++ b/public/motifs/kepler-nest-seal-light.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/public/motifs/layered-seal.svg b/public/motifs/layered-seal.svg new file mode 100644 index 0000000..05127ff --- /dev/null +++ b/public/motifs/layered-seal.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/public/motifs/squared-circle-seal-light.svg b/public/motifs/squared-circle-seal-light.svg new file mode 100644 index 0000000..5d5b1ba --- /dev/null +++ b/public/motifs/squared-circle-seal-light.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/public/motifs/transmutation-seal-light.svg b/public/motifs/transmutation-seal-light.svg new file mode 100644 index 0000000..cf14477 --- /dev/null +++ b/public/motifs/transmutation-seal-light.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/public/motifs/tria-prima-array-seal-light.svg b/public/motifs/tria-prima-array-seal-light.svg new file mode 100644 index 0000000..e9efff8 --- /dev/null +++ b/public/motifs/tria-prima-array-seal-light.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/public/motifs/zodiac-seal-light.svg b/public/motifs/zodiac-seal-light.svg new file mode 100644 index 0000000..5602a89 --- /dev/null +++ b/public/motifs/zodiac-seal-light.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/public/site.webmanifest b/public/site.webmanifest index 45dc8a2..0c8d74d 100644 --- a/public/site.webmanifest +++ b/public/site.webmanifest @@ -1 +1,33 @@ -{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} \ No newline at end of file +{ + "name": "Greg Kilmer Web Development", + "short_name": "Greg Kilmer", + "description": "Web development by Greg Kilmer, a Patiun LLC company.", + "icons": [ + { + "src": "/icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "/icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "/icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ], + "theme_color": "#131C2B", + "background_color": "#131C2B", + "display": "standalone", + "start_url": "/" +} diff --git a/src/components/Icon.astro b/src/components/Icon.astro index 15efe5a..3cfa314 100644 --- a/src/components/Icon.astro +++ b/src/components/Icon.astro @@ -2,17 +2,17 @@ /** * Icon.astro * --------------------------------------------------------------------------- - * Inline mdi (Material Design Icons) renderer. Pulls icon path data at build - * time from `@iconify-json/mdi/icons.json` and emits a single inline , so - * there is no runtime icon library and no extra requests. The svg inherits - * `currentColor`, so color is controlled via text-* utilities or inline style. - * - * The spec calls for mdi icons everywhere instead of emojis; all spec emoji - * references are mapped to mdi names at the call sites. + * Inline icon renderer. Names resolve to the Patiun brand icon set first + * (src/lib/brand-icons.ts: stroke icons with a gold star accent), via either a + * brand name ("dice") or the mdi name the call sites already use ("dice-multiple"). + * Anything not in the brand set, which is only third-party logos like GitHub or + * LinkedIn, falls back to mdi (Material Design Icons) path data. Either way the + * output is one inline that inherits `currentColor`. * * Usage: */ import mdi from '@iconify-json/mdi/icons.json'; +import { brandIconBody } from '@lib/brand-icons'; interface Props { /** mdi icon name WITHOUT prefix, e.g. "briefcase". */ @@ -27,8 +27,11 @@ interface Props { const { name, title, class: className, size, style } = Astro.props; -const icon = (mdi as { icons: Record }).icons[name]; -if (!icon) { +const brand = brandIconBody(name); +const icon = brand + ? undefined + : (mdi as { icons: Record }).icons[name]; +if (!brand && !icon) { // Surface missing-icon names during dev so typos are caught immediately. console.warn(`[Icon] unknown mdi icon: "${name}"`); } @@ -39,9 +42,14 @@ if (!icon) { width={size ?? '1em'} height={size ?? '1em'} viewBox="0 0 24 24" + fill={brand ? 'none' : undefined} + stroke={brand ? 'currentColor' : undefined} + stroke-width={brand ? 1.6 : undefined} + stroke-linecap={brand ? 'round' : undefined} + stroke-linejoin={brand ? 'round' : undefined} class={className} style={style} aria-hidden={title ? undefined : 'true'} role={title ? 'img' : undefined} - set:html={(title ? `${title}` : '') + (icon?.body ?? '')} + set:html={(title ? `${title}` : '') + (brand ?? icon?.body ?? '')} /> diff --git a/src/components/brand/BrandIcon.tsx b/src/components/brand/BrandIcon.tsx new file mode 100644 index 0000000..3b72c2c --- /dev/null +++ b/src/components/brand/BrandIcon.tsx @@ -0,0 +1,37 @@ +/** + * BrandIcon.tsx + * --------------------------------------------------------------------------- + * React twin of Icon.astro for islands: renders a Patiun brand icon (by brand + * name or mdi alias) as an inline stroke SVG that inherits currentColor. + */ +import { brandIconBody } from '@lib/brand-icons'; + +interface Props { + name: string; + size?: number; + className?: string; + /** Accessible label; omit when the icon sits beside visible text. */ + title?: string; +} + +export default function BrandIcon({ name, size = 20, className, title }: Props) { + const body = brandIconBody(name) ?? ''; + return ( + + ); +} diff --git a/src/components/brand/Motif.astro b/src/components/brand/Motif.astro new file mode 100644 index 0000000..350dd97 --- /dev/null +++ b/src/components/brand/Motif.astro @@ -0,0 +1,43 @@ +--- +/** + * Motif.astro + * --------------------------------------------------------------------------- + * A Patiun brand motif ("The Alchemist's Instrument") as a decorative image. + * Files live in public/motifs/ and are copied from branding/motifs/svg with + * their ring text and symbols outlined to paths, so they render without the + * Cinzel or Noto Sans Symbols fonts. `-light` files are the Starlight-ground + * recolor (deep teal, deep gold, Midnight symbols); the rest are drawn for the + * night sky. + * + * Brand rules: one focal motif per surface, and keep motifs faint behind + * content (they are texture, not illustration). + * + * Usage: + * + */ +export interface Props { + name: + | "layered-seal" + | "astrolabe" + | "transmutation-seal-light" + | "tria-prima-array-seal-light" + | "zodiac-seal-light" + | "craft-seal-print-light" + | "squared-circle-seal-light" + | "kepler-nest-seal-light"; + class?: string; + style?: string; +} +const { name, class: className, style } = Astro.props; +--- + + diff --git a/src/components/brand/PageSeal.astro b/src/components/brand/PageSeal.astro new file mode 100644 index 0000000..ac968b2 --- /dev/null +++ b/src/components/brand/PageSeal.astro @@ -0,0 +1,29 @@ +--- +/** + * PageSeal.astro + * --------------------------------------------------------------------------- + * A faint Patiun seal behind the top-right of a page header, for pages + * without a night-sky hero (those already carry the turning layered seal). + * Sits behind content (-z-10) and is clipped so it never widens the page. + * + * Usage (first thing inside the page): + */ +import Motif from "@components/brand/Motif.astro"; +import type { Props as MotifProps } from "@components/brand/Motif.astro"; + +interface Props { + name: MotifProps["name"]; +} +const { name } = Astro.props; +--- + + diff --git a/src/components/cards/DeckCard.astro b/src/components/cards/DeckCard.astro index 0d87250..e584b1f 100644 --- a/src/components/cards/DeckCard.astro +++ b/src/components/cards/DeckCard.astro @@ -96,13 +96,13 @@ const updated = updatedAt ? new Date(updatedAt).toLocaleDateString('en-US', {

{name}

{formatLabel && {formatLabel}} diff --git a/src/components/cards/GameCard.astro b/src/components/cards/GameCard.astro index 99325b0..87286b3 100644 --- a/src/components/cards/GameCard.astro +++ b/src/components/cards/GameCard.astro @@ -67,7 +67,7 @@ const alt = artAlt ?? title; {year && ( {year} @@ -75,7 +75,7 @@ const alt = artAlt ?? title; )}
-

{title}

+

{title}

{blurb} diff --git a/src/components/cards/InterestCard.astro b/src/components/cards/InterestCard.astro index 7575e67..77181e9 100644 --- a/src/components/cards/InterestCard.astro +++ b/src/components/cards/InterestCard.astro @@ -41,7 +41,7 @@ const { icon, title, status, currently = false, class: className = '' } = Astro. {currently && ( - + Active @@ -50,7 +50,7 @@ const { icon, title, status, currently = false, class: className = '' } = Astro. {status} )}

-

{title}

+

{title}

diff --git a/src/components/cards/MediaCard.astro b/src/components/cards/MediaCard.astro index b85f934..cc8e126 100644 --- a/src/components/cards/MediaCard.astro +++ b/src/components/cards/MediaCard.astro @@ -81,7 +81,7 @@ const detail = [year ? String(year) : null, count].filter(Boolean).join(' \u00b7
-

+

{title}

{status && {status}} @@ -89,7 +89,7 @@ const detail = [year ? String(year) : null, count].filter(Boolean).join(' \u00b7 { detail && ( {detail} diff --git a/src/components/hero/AnimatedBackground.tsx b/src/components/hero/AnimatedBackground.tsx index ffc0280..7d3460e 100644 --- a/src/components/hero/AnimatedBackground.tsx +++ b/src/components/hero/AnimatedBackground.tsx @@ -6,8 +6,8 @@ * 1. A CSS-driven night-sky gradient (deep blue, darker at top → lighter near * horizon) plus a diagonal Milky Way galaxy band and teal/violet nebula * clouds. GPU-friendly, animated via `animate-gradient-shift` keyframes. - * 2. A faint static SVG ornament layer (astrolabe + sacred geometry) for - * esoteric texture. + * 2. The Patiun layered magic seal, faint and slowly turning in the top-left + * corner (the surface's one focal motif). * 3. An optional star field: a dense field of slowly-twinkling stars * with thin constellation lines between near neighbors, plus the occasional * shooting star. The WHOLE field rotates together very slowly around the @@ -85,17 +85,16 @@ export default function AnimatedBackground({ // Resolve star colors from CSS variables so the field matches the theme. const gold = - getComputedStyle(document.documentElement).getPropertyValue('--color-amber').trim() || - '#e8b54a'; - const violet = - getComputedStyle(document.documentElement).getPropertyValue('--color-violet').trim() || - '#8b7bd8'; + getComputedStyle(document.documentElement).getPropertyValue('--color-gold').trim() || + '#c9a24a'; + // Nebula Violet is background light only, so violet stars stay sparse; teal stars use the on-dark teal so they read at dot size. + const violet = '#6a2fe0'; const teal = - getComputedStyle(document.documentElement).getPropertyValue('--color-teal').trim() || - '#6fb6ad'; + getComputedStyle(document.documentElement).getPropertyValue('--color-teal-bright').trim() || + '#2bc2b7'; const white = - getComputedStyle(document.documentElement).getPropertyValue('--color-cream').trim() || - '#f4f1e8'; + getComputedStyle(document.documentElement).getPropertyValue('--color-starlight').trim() || + '#f4f2ed'; const hueColor = (h: Star['hue']) => (h === 'gold' ? gold : h === 'violet' ? violet : h === 'teal' ? teal : white); @@ -214,7 +213,7 @@ export default function AnimatedBackground({ const proximity = 1 - Math.sqrt(d2) / LINK_DIST; const pulse = 0.5 + 0.5 * Math.sin(now / 1400 + (i + j) * 0.7); const alpha = proximity * 0.22 * (0.55 + 0.45 * pulse); - ctx.strokeStyle = `rgba(232, 181, 74, ${alpha.toFixed(3)})`; + ctx.strokeStyle = `rgba(201, 162, 74, ${alpha.toFixed(3)})`; ctx.beginPath(); ctx.moveTo(A.x, A.y); ctx.lineTo(B.x, B.y); @@ -270,8 +269,8 @@ export default function AnimatedBackground({ const grad = ctx.createLinearGradient(sh.x, sh.y, tailX, tailY); const headA = Math.max(0, Math.min(1, sh.life)); grad.addColorStop(0, `rgba(244, 241, 232, ${headA.toFixed(3)})`); - grad.addColorStop(0.4, `rgba(232, 181, 74, ${(headA * 0.6).toFixed(3)})`); - grad.addColorStop(1, 'rgba(232, 181, 74, 0)'); + grad.addColorStop(0.4, `rgba(201, 162, 74, ${(headA * 0.6).toFixed(3)})`); + grad.addColorStop(1, 'rgba(201, 162, 74, 0)'); ctx.strokeStyle = grad; ctx.lineWidth = 1.6; ctx.beginPath(); @@ -332,7 +331,7 @@ export default function AnimatedBackground({ className="absolute inset-0" style={{ background: - 'linear-gradient(180deg, #04061a 0%, #070b24 32%, #0a1230 58%, #0e1a3e 82%, #12224a 100%)', + 'linear-gradient(180deg, #080c14 0%, #0b111c 32%, #0e1522 58%, #131c2b 82%, #1a2a3a 100%)', }} /> {/* Milky Way galaxy band — a soft diagonal luminous streak with a denser @@ -341,10 +340,10 @@ export default function AnimatedBackground({ className="animate-gradient-shift absolute inset-0 opacity-90" style={{ backgroundImage: ` - radial-gradient(38% 70% at 68% 38%, rgba(111, 182, 173, 0.22), transparent 62%), - radial-gradient(30% 55% at 72% 44%, rgba(139, 123, 216, 0.26), transparent 60%), - radial-gradient(22% 40% at 76% 50%, rgba(232, 181, 74, 0.12), transparent 60%), - linear-gradient(115deg, transparent 30%, rgba(236, 233, 255, 0.06) 45%, rgba(236, 233, 255, 0.09) 52%, rgba(236, 233, 255, 0.05) 60%, transparent 72%) + radial-gradient(38% 70% at 68% 38%, rgba(20, 163, 154, 0.22), transparent 62%), + radial-gradient(30% 55% at 72% 44%, rgba(106, 47, 224, 0.26), transparent 60%), + radial-gradient(22% 40% at 76% 50%, rgba(201, 162, 74, 0.12), transparent 60%), + linear-gradient(115deg, transparent 30%, rgba(236, 233, 226, 0.06) 45%, rgba(236, 233, 226, 0.09) 52%, rgba(236, 233, 226, 0.05) 60%, transparent 72%) `, backgroundSize: '200% 200%', }} @@ -354,67 +353,29 @@ export default function AnimatedBackground({ className="absolute inset-0" style={{ backgroundImage: ` - radial-gradient(45% 55% at 12% 12%, rgba(139, 123, 216, 0.18), transparent 60%), - radial-gradient(40% 50% at 88% 88%, rgba(111, 182, 173, 0.16), transparent 62%) + radial-gradient(45% 55% at 12% 12%, rgba(106, 47, 224, 0.18), transparent 60%), + radial-gradient(40% 50% at 88% 88%, rgba(20, 163, 154, 0.16), transparent 62%) `, }} /> - {/* Faint astrolabe + sacred-geometry ornaments for esoteric texture. */} - - + decoding="async" + draggable={false} + className="pointer-events-none absolute -left-40 -top-40 h-[34rem] w-[34rem] animate-spin-slow select-none opacity-[0.2]" + /> {/* Subtle vignette for text legibility. */}
{/* Canvas star field (skipped under reduced motion). */} diff --git a/src/components/layout/Footer.astro b/src/components/layout/Footer.astro index 2552294..2915456 100644 --- a/src/components/layout/Footer.astro +++ b/src/components/layout/Footer.astro @@ -3,11 +3,11 @@ * Footer.astro * --------------------------------------------------------------------------- * Minimal footer on a deep night-sky surface: a faint static starfield accent, - * a StarBurst mark beside the name, social links (mdi icons), copyright, and + * the Patiun seal beside the name, social links, the copyright with the + * "a Patiun LLC company" line, and * the spec microcopy "Built with intention. Powered by caffeine." No emojis. */ import Icon from '@components/Icon.astro'; -import StarBurst from '@components/mystic/StarBurst.astro'; import StarField from '@components/mystic/StarField.astro'; import { socials, footerMicrocopy, siteIdentity } from '@lib/site'; const year = new Date().getFullYear(); @@ -16,7 +16,7 @@ const socialList = Object.values(socials);
{/* Faint static starfield — carries the night-sky treatment into the footer. */}
- +
-

+

{siteIdentity.name}

-

+

{footerMicrocopy}

@@ -56,6 +56,6 @@ const socialList = Object.values(socials);
- © {year} {siteIdentity.name}. All rights reserved. + © {year} {siteIdentity.name} · {siteIdentity.lockupLine}. All rights reserved.
diff --git a/src/components/layout/InterestHero.astro b/src/components/layout/InterestHero.astro index c50a900..046f259 100644 --- a/src/components/layout/InterestHero.astro +++ b/src/components/layout/InterestHero.astro @@ -6,7 +6,7 @@ * Milky Way field: a back-to-hub breadcrumb, a small icon mark, the title, and * the italic tagline. * - * Tuned for the dark starfield: text uses bright cream tones (not the dim + * Tuned for the dark starfield: text uses bright Starlight tones (not the dim * --color-text-subtle/--color-text which vanish on the deep sky). The title is * h2-sized (the page is a sub-page, not Home) so it doesn't dominate. An * optional banner image sits above the heading. @@ -39,7 +39,7 @@ const { } = Astro.props; --- -
+
@@ -54,8 +54,8 @@ const { {eyebrow} @@ -74,8 +74,8 @@ const {

{title}

@@ -84,7 +84,7 @@ const {

{tagline}

@@ -97,7 +97,7 @@ const {
diff --git a/src/components/layout/Placeholder.astro b/src/components/layout/Placeholder.astro index 84a3ced..70d421c 100644 --- a/src/components/layout/Placeholder.astro +++ b/src/components/layout/Placeholder.astro @@ -40,7 +40,7 @@ const { label, hint, class: className = '' } = Astro.props;
- + TODO · {label} {hint &&

{hint}

} diff --git a/src/components/layout/RelatedInterests.astro b/src/components/layout/RelatedInterests.astro index f3f6178..6e875cf 100644 --- a/src/components/layout/RelatedInterests.astro +++ b/src/components/layout/RelatedInterests.astro @@ -23,7 +23,7 @@ const { items } = Astro.props; ---
-

+

You might also like

diff --git a/src/components/layout/SectionHeader.astro b/src/components/layout/SectionHeader.astro index f30ec3d..9c5a03e 100644 --- a/src/components/layout/SectionHeader.astro +++ b/src/components/layout/SectionHeader.astro @@ -39,8 +39,8 @@ const { } = Astro.props; const isHero = tone === "hero"; -const titleColor = isHero ? "var(--color-cream)" : undefined; -const subtitleColor = isHero ? "var(--color-cream)" : "var(--color-text-muted)"; +const titleColor = isHero ? "var(--color-starlight)" : undefined; +const subtitleColor = isHero ? "var(--color-starlight)" : "var(--color-text-muted)"; ---
{icon && } diff --git a/src/components/layout/SplitTransition.astro b/src/components/layout/SplitTransition.astro index 45e1823..7377f98 100644 --- a/src/components/layout/SplitTransition.astro +++ b/src/components/layout/SplitTransition.astro @@ -39,7 +39,7 @@ const { /> The professional wing @@ -59,7 +59,7 @@ const { > The personal wing diff --git a/src/components/media/CategoryList.astro b/src/components/media/CategoryList.astro index 46f6e15..773e830 100644 --- a/src/components/media/CategoryList.astro +++ b/src/components/media/CategoryList.astro @@ -29,13 +29,13 @@ const { groups, pillIcon = 'play-circle' } = Astro.props;

{group.category}

{group.items.length} @@ -51,7 +51,7 @@ const { groups, pillIcon = 'play-circle' } = Astro.props; {item.title} {item.status && ( {item.status} @@ -59,7 +59,7 @@ const { groups, pillIcon = 'play-circle' } = Astro.props; )} {item.year && ( {item.year} diff --git a/src/components/mystic/AlchemicalDivider.astro b/src/components/mystic/AlchemicalDivider.astro index 5b88a92..d0ba5c5 100644 --- a/src/components/mystic/AlchemicalDivider.astro +++ b/src/components/mystic/AlchemicalDivider.astro @@ -2,16 +2,13 @@ /** * AlchemicalDivider.astro * --------------------------------------------------------------------------- - * A horizontal section divider built from a thin rule with alchemical / - * celestial symbols along it: a central sun/star flanked by a crescent moon - * and small sparkles, with hairlines tapering to the edges. Replaces plain - * vertical gaps between sections on Home / About / Interests. - * - * Decorative: aria-hidden, inherits currentColor (set to --color-accent or - * --color-violet at the call site). + * Section break in the Patiun star-line style: a dotted (faint) run leading + * into a solid (main) run on each side, each stopping short of the stars, with + * a gold four-point star at the center flanked by two small ones. Inherits + * currentColor; call sites pass Alchemist Gold. * * Usage: - * + * */ interface Props { class?: string; @@ -28,30 +25,12 @@ const { class: className = '', style = '' } = Astro.props; stroke="currentColor" stroke-linecap="round" > - {/* Tapered hairlines either side of the central cluster. */} - - - - - - {/* Crescent moon (left). */} - - - {/* Central radiant sun/star (alchemical sun: circle + rays). */} - - - - - - - - - - - - - {/* Small sparkles. */} - - + {/* Faint links: dotted runs at the outer ends. */} + + {/* Main figure: solid runs that stop short of the stars. */} + + + +
diff --git a/src/components/mystic/Astrolabe.astro b/src/components/mystic/Astrolabe.astro deleted file mode 100644 index 04fc6e8..0000000 --- a/src/components/mystic/Astrolabe.astro +++ /dev/null @@ -1,76 +0,0 @@ ---- -/** - * Astrolabe.astro - * --------------------------------------------------------------------------- - * Inline-SVG astrolabe / celestial-chart line art: concentric rings, tick - * marks like a degree scale, zodiac-like division lines, and a star at the - * pivot. Reads as a "mystic instrument" silhouette. Intended as a hero-corner - * ornament where it can slowly rotate (animate-spin-slow). - * - * Decorative: aria-hidden, pointer-events none, inherits currentColor. Apply - * opacity + color at the call site so it reads as a faint engraving. - * - * Usage: - * - */ -interface Props { - class?: string; - style?: string; -} -const { class: className = '', style = '' } = Astro.props; - -// Degree ticks every 10deg around the outer ring (r=48, on a 100x100 canvas). -const ticks: { x1: number; y1: number; x2: number; y2: number; major: boolean }[] = []; -const cx = 50; -const cy = 50; -for (let deg = 0; deg < 360; deg += 10) { - const rad = (deg * Math.PI) / 180; - const major = deg % 30 === 0; - const outer = 48; - const inner = major ? 43 : 45.5; - ticks.push({ - x1: cx + outer * Math.cos(rad), - y1: cy + outer * Math.sin(rad), - x2: cx + inner * Math.cos(rad), - y2: cy + inner * Math.sin(rad), - major, - }); -} -// Zodiac-like spokes (12 divisions). -const spokes: [number, number][] = []; -for (let i = 0; i < 12; i++) { - const rad = (i * 30 * Math.PI) / 180; - spokes.push([cx + 40 * Math.cos(rad), cy + 40 * Math.sin(rad)]); -} ---- - diff --git a/src/components/mystic/CelestialFrame.astro b/src/components/mystic/CelestialFrame.astro index ea0dcca..316315f 100644 --- a/src/components/mystic/CelestialFrame.astro +++ b/src/components/mystic/CelestialFrame.astro @@ -36,7 +36,7 @@ const innerPx = Math.max(0, outerPx - bw);
{/* Faint sacred-geometry tint behind the image (fills the full figure). */}
- {/* Corner star-burst flourishes (sit on the border corners). */} + {/* Corner four-point stars in Alchemist Gold (sit on the border corners). */}
diff --git a/src/components/mystic/CelestialImage.astro b/src/components/mystic/CelestialImage.astro index bd3d80c..86d1d9f 100644 --- a/src/components/mystic/CelestialImage.astro +++ b/src/components/mystic/CelestialImage.astro @@ -80,7 +80,7 @@ const objectFit = fit === "contain" ? "object-contain" : "object-cover";
{alt} diff --git a/src/components/mystic/CircuitField.tsx b/src/components/mystic/CircuitField.tsx index 388e806..272a390 100644 --- a/src/components/mystic/CircuitField.tsx +++ b/src/components/mystic/CircuitField.tsx @@ -56,9 +56,9 @@ export default function CircuitField({ let traces: Trace[] = []; let nodes: Node[] = []; - const gold = '#e8b54a'; - const violet = '#8b7bd8'; - const teal = '#6fb6ad'; + const gold = '#c9a24a'; + const violet = '#6a2fe0'; + const teal = '#2bc2b7'; function build() { if (!canvas || !ctx) return; @@ -116,7 +116,7 @@ export default function CircuitField({ for (let i = 0; i < traces.length; i++) { const t = traces[i]; // Base trace — clearly visible violet conductor line. - ctx.strokeStyle = 'rgba(168, 158, 220, 0.55)'; + ctx.strokeStyle = 'rgba(43, 194, 183, 0.55)'; ctx.lineWidth = 1.4; ctx.beginPath(); ctx.moveTo(t.x1, t.y1); @@ -140,7 +140,7 @@ export default function CircuitField({ ctx.stroke(); // Bright pulse head dot. ctx.globalAlpha = 1; - ctx.fillStyle = '#fff4d6'; + ctx.fillStyle = '#fbf3dc'; ctx.beginPath(); ctx.arc(px, py, 1.8, 0, Math.PI * 2); ctx.fill(); @@ -172,7 +172,7 @@ export default function CircuitField({ if (!ctx) return; ctx.clearRect(0, 0, width, height); for (const t of traces) { - ctx.strokeStyle = 'rgba(168, 158, 220, 0.5)'; + ctx.strokeStyle = 'rgba(43, 194, 183, 0.5)'; ctx.lineWidth = 1.4; ctx.beginPath(); ctx.moveTo(t.x1, t.y1); @@ -243,7 +243,7 @@ export default function CircuitField({ className="absolute inset-0" style={{ background: - 'linear-gradient(180deg, #04061a 0%, #070b24 32%, #0a1230 58%, #0e1a3e 82%, #12224a 100%)', + 'linear-gradient(180deg, #080c14 0%, #0b111c 32%, #0e1522 58%, #131c2b 82%, #1a2a3a 100%)', }} /> {/* Circuit traces + nodes + signal pulses. */} diff --git a/src/components/mystic/ConstellationField.tsx b/src/components/mystic/ConstellationField.tsx index 44cd174..6414883 100644 --- a/src/components/mystic/ConstellationField.tsx +++ b/src/components/mystic/ConstellationField.tsx @@ -67,10 +67,10 @@ export default function ConstellationField({ } let stars: Star[] = []; - const gold = '#e8b54a'; - const violet = '#8b7bd8'; - const teal = '#6fb6ad'; - const white = '#f4f1e8'; + const gold = '#c9a24a'; + const violet = '#6a2fe0'; + const teal = '#2bc2b7'; + const white = '#f4f2ed'; const accent = tint === 'violet' ? violet : tint === 'teal' ? teal : gold; // One full rotation every ~10 minutes — barely perceptible, "planet turning". @@ -168,7 +168,7 @@ export default function ConstellationField({ const proximity = 1 - Math.sqrt(d2) / LINK_DIST; const pulse = 0.5 + 0.5 * Math.sin(now / 1600 + (i + j) * 0.7); const alpha = proximity * 0.24 * (0.55 + 0.45 * pulse); - ctx.strokeStyle = `rgba(232, 181, 74, ${alpha.toFixed(3)})`; + ctx.strokeStyle = `rgba(201, 162, 74, ${alpha.toFixed(3)})`; ctx.beginPath(); ctx.moveTo(A.x, A.y); ctx.lineTo(B.x, B.y); diff --git a/src/components/mystic/SacredGeometry.astro b/src/components/mystic/SacredGeometry.astro deleted file mode 100644 index 3a9f086..0000000 --- a/src/components/mystic/SacredGeometry.astro +++ /dev/null @@ -1,85 +0,0 @@ ---- -/** - * SacredGeometry.astro - * --------------------------------------------------------------------------- - * Inline-SVG sacred-geometry line art: a flower-of-life / metatron's-cube - * inspired figure rendered as thin gold strokes. Used as an extremely faint - * (low-opacity) decorative background behind hero blocks and section openers — - * it should read as texture, never compete with content. - * - * Purely decorative: aria-hidden, pointer-events none, inherits currentColor. - * Apply opacity + sizing + color at the call site. - * - * Usage: - * - */ -interface Props { - class?: string; - style?: string; - /** Which figure to draw. */ - figure?: 'flower' | 'metatron'; -} -const { class: className = '', style = '', figure = 'flower' } = Astro.props; - -// Flower of life: a central circle surrounded by 6, then 12, then edge circles -// of the same radius, all r=10 on a 100x100 canvas centered at 50,50. -const r = 10; -const cx = 50; -const cy = 50; -const rings: [number, number][] = []; -// Ring 1: 6 circles around center. -for (let i = 0; i < 6; i++) { - const a = (Math.PI / 3) * i; - rings.push([cx + r * Math.cos(a), cy + r * Math.sin(a)]); -} -// Ring 2: 6 more, one step further on alternating angles (the classic pattern). -for (let i = 0; i < 6; i++) { - const a = (Math.PI / 3) * i + Math.PI / 6; - rings.push([cx + r * Math.sqrt(3) * Math.cos(a), cy + r * Math.sqrt(3) * Math.sin(a)]); -} -// Ring 3 (outer partial): completes the visible flower. -for (let i = 0; i < 6; i++) { - const a = (Math.PI / 3) * i; - rings.push([cx + 2 * r * Math.cos(a), cy + 2 * r * Math.sin(a)]); -} -const flowerCircles: [number, number][] = [[cx, cy], ...rings]; - -// Metatron's cube: 13 circles on a triangular grid + all internal connecting lines. -const metatronCenters: [number, number][] = [[cx, cy]]; -for (let i = 0; i < 6; i++) { - const a = (Math.PI / 3) * i; - metatronCenters.push([cx + 2 * r * Math.cos(a), cy + 2 * r * Math.sin(a)]); -} -for (let i = 0; i < 6; i++) { - const a = (Math.PI / 3) * i + Math.PI / 6; - metatronCenters.push([cx + 2 * r * Math.sqrt(3) * Math.cos(a), cy + 2 * r * Math.sqrt(3) * Math.sin(a)]); -} ---- - diff --git a/src/components/mystic/StarBurst.astro b/src/components/mystic/StarBurst.astro index 4fe1453..c3505ec 100644 --- a/src/components/mystic/StarBurst.astro +++ b/src/components/mystic/StarBurst.astro @@ -11,7 +11,7 @@ * - `outline`: stroke-only, lighter * * Usage: - * + * * */ interface Props { @@ -34,6 +34,7 @@ const sw = variant === 'outline' ? 1.4 : 0; stroke-linejoin="round" aria-hidden="true" > - {/* Four-point sparkle: two perpendicular sharp diamonds + small inner core. */} - + {/* The Patiun four-point star: thin straight arms (inner radius 0.3 of the + outer), the same star used on the seal, the icons and the favicon. */} + diff --git a/src/components/mystic/StarField.astro b/src/components/mystic/StarField.astro index e9ad5af..e00475f 100644 --- a/src/components/mystic/StarField.astro +++ b/src/components/mystic/StarField.astro @@ -10,7 +10,7 @@ * cheap. Pointer-events disabled; inherits `currentColor`. * * Usage: - * + * */ interface Props { class?: string; diff --git a/src/components/nav/MobileMenu.tsx b/src/components/nav/MobileMenu.tsx index b976da7..f3ad27a 100644 --- a/src/components/nav/MobileMenu.tsx +++ b/src/components/nav/MobileMenu.tsx @@ -12,6 +12,7 @@ */ import { useEffect, useRef, useState } from 'react'; import { AnimatePresence, motion } from 'framer-motion'; +import BrandIcon from '@components/brand/BrandIcon'; export interface MobileNavItem { label: string; @@ -28,31 +29,9 @@ interface Props { currentPath: string; } -// Small inline mdi-like icons keyed by name (keeps the menu self-contained). -const ICON_PATHS: Record = { - home: 'M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z', - account: 'M12 4a4 4 0 1 0 0 8 4 4 0 0 0 0-8zm0 10c-4.4 0-8 2.2-8 5v1h16v-1c0-2.8-3.6-5-8-5z', - briefcase: - 'M10 16h4a1 1 0 0 0 1-1v-1H7a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h2V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v1h2a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-1v1a3 3 0 0 1-3 3h-4a3 3 0 0 1-3-3v-1z', - 'dice-multiple': - 'M6 3h5v5H6V3zm7 0h5v5h-5V3zM3 11h5v5H3v-5zm7 0h5v5h-5v-5zm7 0h-5v5h5v-5z', - email: - 'M4 4h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2zm8 7L4 6v1l8 5 8-5V6l-8 5z', - // Store nav icons (kept here so the store mobile menu is self-contained). - store: 'M4 7h16l-1 13H5L4 7zm5-3a3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0 3 3', - 'cards-playing': 'M5 3h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2zm3 4v3m6 7v-3', - 'printer-3d-nozzle': - 'M7 2h10v4l3 3-4 2H8L4 9l3-3V2zm5 11v9', - 'clipboard-list': - 'M9 3h6v2H9V3zm-2 0v2H6a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-1V3M7 11h2m4 0h4M7 15h2m4 0h4', -}; - +// Patiun brand icons, resolved by the same names the nav config uses. function Icon({ name, className }: { name: string; className?: string }) { - return ( - - ); + return ; } function isActive(href: string, path: string): boolean { @@ -90,17 +69,13 @@ export default function MobileMenu({ groups, currentPath }: Props) { aria-expanded={open} aria-controls="mobile-menu" aria-label={open ? 'Close menu' : 'Open menu'} - className="inline-flex h-10 w-10 items-center justify-center rounded-lg border" - style={{ color: 'var(--color-text)', borderColor: 'var(--color-border)' }} + className="relative z-[60] inline-flex h-10 w-10 items-center justify-center rounded-lg border" + style={{ color: 'var(--color-starlight)', borderColor: 'color-mix(in srgb, var(--color-gold) 45%, transparent)' }} > {open ? ( - - - + ) : ( - - - + )} @@ -124,7 +99,11 @@ export default function MobileMenu({ groups, currentPath }: Props) { exit={{ x: '100%' }} transition={{ type: 'tween', duration: 0.28 }} className="fixed right-0 top-0 z-50 flex h-[100dvh] w-[min(82vw,22rem)] flex-col gap-6 overflow-y-auto p-6 pt-20 shadow-2xl" - style={{ backgroundColor: 'var(--color-surface-raised)' }} + style={{ + // Night-sky drawer to match the nav it opens from. + backgroundColor: 'var(--color-midnight)', + borderLeft: '1px solid color-mix(in srgb, var(--color-gold) 45%, transparent)', + }} > {groups.map((group, gi) => (
-

+

{c.name}

{c.issuer}

{c.year} diff --git a/src/components/professional/ContactForm.tsx b/src/components/professional/ContactForm.tsx index edf3cbc..e43423b 100644 --- a/src/components/professional/ContactForm.tsx +++ b/src/components/professional/ContactForm.tsx @@ -16,6 +16,7 @@ * skipped entirely so the form still works. */ import { useState, useRef, useEffect, type FormEvent } from 'react'; +import BrandIcon from '@components/brand/BrandIcon'; type Status = 'idle' | 'submitting' | 'success' | 'error'; @@ -219,11 +220,9 @@ export default function ContactForm({ turnstileSiteKey }: Props) { style={{ background: 'var(--color-accent)', color: 'var(--color-accent-contrast)' }} aria-hidden="true" > - - - + -

+

Message sent.

diff --git a/src/components/professional/EducationHistory.astro b/src/components/professional/EducationHistory.astro index 3c4c488..c5580a6 100644 --- a/src/components/professional/EducationHistory.astro +++ b/src/components/professional/EducationHistory.astro @@ -45,7 +45,7 @@ const entries: EduEntry[] = [

-

+

{e.credential}

{e.period} diff --git a/src/components/professional/ProjectCard.astro b/src/components/professional/ProjectCard.astro index 08641c5..0be0cb3 100644 --- a/src/components/professional/ProjectCard.astro +++ b/src/components/professional/ProjectCard.astro @@ -33,7 +33,7 @@ const links = [

{d.title}

-

+

{d.role}

diff --git a/src/components/professional/SectionNav.astro b/src/components/professional/SectionNav.astro index aa91501..cdc561f 100644 --- a/src/components/professional/SectionNav.astro +++ b/src/components/professional/SectionNav.astro @@ -8,7 +8,7 @@ * * Three bugs previously fixed here: * 1. Contrast: the rail used surface-relative tokens (--color-surface-raised / - * --color-cream) which collapsed to the same tone on light surfaces (the + * --color-starlight) which collapsed to the same tone on light surfaces (the * interest-surface cream made icons/text invisible). The rail now uses * FIXED dark colors regardless of the page's surface tone. * 2. Progress line clipping: the line sat at the icon column's horizontal @@ -41,7 +41,7 @@ const sections = [ for the progress line, then the icon+label list. */}
{/* --- Left gutter: the progress track + fill. Sits LEFT of the icons. --- */}
@@ -69,11 +69,11 @@ const sections = [ href={`#${s.id}`} data-section-link={s.id} class="group relative flex items-center gap-2.5 rounded-lg px-2.5 py-2 font-sans text-sm font-semibold transition-all" - style="color: #e8e6f5;" + style="color: #ece9e2;" > @@ -92,19 +92,19 @@ const sections = [ } .pro-section-nav a[data-section-link]:hover { opacity: 1; - background: rgba(232, 181, 74, 0.08); + background: rgba(201, 162, 74, 0.08); } /* Active link: bright accent text + accent wash. */ .pro-section-nav a[data-active="true"] { opacity: 1 !important; color: var(--color-accent) !important; - background: rgba(232, 181, 74, 0.14); + background: rgba(201, 162, 74, 0.14); } /* Active dot: filled accent, dark icon, glow ring. */ .pro-section-nav a[data-active="true"] [data-section-dot] { background: var(--color-accent) !important; - color: #0b1026 !important; - box-shadow: 0 0 12px rgba(232, 181, 74, 0.65); + color: #131c2b !important; + box-shadow: 0 0 12px rgba(201, 162, 74, 0.65); } diff --git a/src/components/professional/SkillGrid.astro b/src/components/professional/SkillGrid.astro index 2422aac..b9ef569 100644 --- a/src/components/professional/SkillGrid.astro +++ b/src/components/professional/SkillGrid.astro @@ -72,7 +72,7 @@ const techStack = [
-

+

Core Competencies