Use Patiun icons, motifs, seal logo and gold accents across the site

- Icons: Patiun stroke icon set (13 approved + 73 new) in src/lib/brand-icons.ts;
  Icon.astro and a React BrandIcon resolve mdi names to brand icons, keeping
  mdi only for third-party logos. Inline island icons (mobile menu, carousel,
  form success, board game shelf, product tile) switched too.
- Motifs: layered seal turns in the hero corner; astrolabe on the Professional
  hero; Starlight recolors of the transmutation seal and tria prima array
  behind light sections (outlined ring text, no fonts needed). Removed the
  generic sacred-geometry and astrolabe drawings.
- Gold accents: image frames and corner stars, quote bars, dividers (new
  star-line divider), nav group divider, scrolled nav rule, footer rule.
- Nav and footer use the Patiun seal; nav tagline back to "Developer. Maker.
  Storyteller."; "Web Development · a Patiun LLC company" moved to the
  footer copyright line.
- Mobile menu: Midnight drawer, visible close button.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012aSbo2D1qP8cMFQCykf7kx
This commit is contained in:
Claude
2026-10-11 02:20:55 +00:00
parent 01431468e4
commit 9ecd4d0e59
35 changed files with 528 additions and 420 deletions
+14 -35
View File
@@ -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<string, string> = {
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 (
<svg className={className} width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d={ICON_PATHS[name] ?? ''} />
</svg>
);
return <BrandIcon name={name} className={className} />;
}
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 ? (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
<path d="M6 6l12 12M18 6L6 18" />
</svg>
<BrandIcon name="close" size={22} />
) : (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
<path d="M4 7h16M4 12h16M4 17h16" />
</svg>
<BrandIcon name="menu" size={22} />
)}
</button>
@@ -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) => (
<ul key={gi} className="flex flex-col gap-1">
@@ -137,9 +116,9 @@ export default function MobileMenu({ groups, currentPath }: Props) {
onClick={() => setOpen(false)}
className="flex items-center gap-3 rounded-lg px-3 py-3 text-lg font-medium transition-colors"
style={{
color: active ? 'var(--color-accent)' : 'var(--color-text)',
color: active ? 'var(--color-teal-bright)' : 'var(--color-starlight)',
backgroundColor: active
? 'color-mix(in srgb, var(--color-accent) 14%, transparent)'
? 'color-mix(in srgb, var(--color-teal-bright) 14%, transparent)'
: 'transparent',
}}
>