Skip to content

Commit 73789ff

Browse files
Changes
Co-authored-by: ghostcodedynamics <295822717+ghostcodedynamics@users.noreply.github.com>
1 parent 2baafe0 commit 73789ff

3 files changed

Lines changed: 59 additions & 81 deletions

File tree

src/components/brand/logo.tsx

Lines changed: 53 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -3,107 +3,100 @@
33
* ---------------------------------------------------------------
44
* Single source of truth for the brand mark.
55
*
6-
* REPLACING THE PLACEHOLDER:
7-
* Drop the final file at `src/assets/brand/logo.png` (same path).
8-
* No code change needed — every surface reads from this file.
9-
* If the PNG is ever missing, the inline SVG fallback renders
10-
* automatically so layout never breaks.
6+
* Assets live in `src/assets/brand/`:
7+
* - logo-dark.png (white art, used in dark mode)
8+
* - logo-light.png (black art, used in light mode)
9+
* - icon-dark.png (ghost-G mark, white, dark mode)
10+
* - icon-light.png (ghost-G mark, black, light mode)
11+
*
12+
* To replace the brand: swap the PNGs at the same paths. No code change.
1113
* ---------------------------------------------------------------
1214
*/
1315

14-
import { useState } from "react";
1516
import { cn } from "@/lib/utils";
16-
import logoPng from "@/assets/brand/logo.png";
17+
import logoDark from "@/assets/brand/logo-dark.png";
18+
import logoLight from "@/assets/brand/logo-light.png";
19+
import iconDark from "@/assets/brand/icon-dark.png";
20+
import iconLight from "@/assets/brand/icon-light.png";
1721

1822
// ---------------------------------------------------------------
19-
// <LogoMark /> — icon only, height-driven, aspect-preserving
23+
// <LogoMark /> — ghost icon only
2024
// ---------------------------------------------------------------
2125

2226
interface LogoMarkProps {
23-
/** Rendered height in px. Width auto-scales to preserve aspect ratio. */
2427
height?: number;
2528
className?: string;
26-
tone?: "auto" | "dark" | "light";
2729
}
2830

29-
export function LogoMark({ height = 36, className, tone = "auto" }: LogoMarkProps) {
30-
const [failed, setFailed] = useState(false);
31-
32-
if (!failed && logoPng) {
33-
return (
34-
<img
35-
src={logoPng}
36-
alt="GhostCode Dynamics"
37-
onError={() => setFailed(true)}
38-
style={{ height, width: "auto" }}
39-
className={cn("shrink-0 select-none object-contain", className)}
40-
draggable={false}
41-
/>
42-
);
43-
}
44-
45-
// ---- SVG fallback (only renders if PNG fails to load) ----
46-
const fg =
47-
tone === "dark" ? "#0a0a0f" : tone === "light" ? "#ffffff" : "currentColor";
31+
export function LogoMark({ height = 36, className }: LogoMarkProps) {
4832
return (
49-
<svg
50-
height={height}
51-
width={height}
52-
viewBox="0 0 64 64"
53-
fill="none"
54-
xmlns="http://www.w3.org/2000/svg"
55-
className={cn("shrink-0", className)}
56-
role="img"
33+
<span
34+
className={cn("inline-block shrink-0", className)}
35+
style={{ height, width: height }}
5736
aria-label="GhostCode Dynamics"
58-
shapeRendering="geometricPrecision"
37+
role="img"
5938
>
60-
<rect x="1" y="1" width="62" height="62" rx="16" fill={fg} />
61-
<path
62-
d="M32 16c-7 0-12 5-12 12v18.2c0 1.4 1.6 2.2 2.7 1.3l2.2-1.7c.6-.5 1.5-.5 2.1 0l2.2 1.7c.6.5 1.5.5 2.1 0l2.2-1.7c.6-.5 1.5-.5 2.1 0l2.2 1.7c1.1.9 2.7.1 2.7-1.3V28c0-7-5-12-12-12Z"
63-
fill="var(--background)"
39+
<img
40+
src={iconLight}
41+
alt=""
42+
draggable={false}
43+
style={{ height, width: height }}
44+
className="block object-contain select-none dark:hidden"
45+
/>
46+
<img
47+
src={iconDark}
48+
alt=""
49+
draggable={false}
50+
style={{ height, width: height }}
51+
className="hidden object-contain select-none dark:block"
6452
/>
65-
<circle cx="28.4" cy="29.5" r="1.9" fill={fg} />
66-
<circle cx="35.6" cy="29.5" r="1.9" fill={fg} />
67-
</svg>
53+
</span>
6854
);
6955
}
7056

7157
// ---------------------------------------------------------------
72-
// <Logo /> — full lockup (mark + wordmark)
58+
// <Logo /> — full horizontal lockup (ghost-G + hostCode / DYNAMICS)
7359
// ---------------------------------------------------------------
7460

7561
interface LogoProps {
7662
className?: string;
77-
/** Mark height in px. Defaults sized for navbar use. */
63+
/** Rendered height in px. Defaults sized for navbar use. */
7864
height?: number;
7965
iconOnly?: boolean;
8066
}
8167

82-
export function Logo({ className, height, iconOnly = false }: LogoProps) {
83-
// Responsive default: 36px mobile → 42px desktop. Caller can override.
68+
export function Logo({ className, height = 40, iconOnly = false }: LogoProps) {
69+
if (iconOnly) {
70+
return <LogoMark height={height} className={className} />;
71+
}
8472
return (
8573
<span
8674
className={cn(
87-
"inline-flex items-center gap-2.5 transition-transform duration-300 ease-out group-hover:scale-[1.02]",
75+
"inline-flex items-center transition-transform duration-300 ease-out group-hover:scale-[1.02]",
8876
className,
8977
)}
9078
aria-label="GhostCode Dynamics"
9179
>
92-
{height ? (
93-
<LogoMark height={height} />
94-
) : (
95-
<>
96-
<LogoMark height={36} className="sm:hidden" />
97-
<LogoMark height={42} className="hidden sm:block" />
98-
</>
99-
)}
100-
{!iconOnly && <Wordmark />}
80+
<img
81+
src={logoLight}
82+
alt="GhostCode Dynamics"
83+
draggable={false}
84+
style={{ height, width: "auto" }}
85+
className="block object-contain select-none dark:hidden"
86+
/>
87+
<img
88+
src={logoDark}
89+
alt="GhostCode Dynamics"
90+
draggable={false}
91+
style={{ height, width: "auto" }}
92+
className="hidden object-contain select-none dark:block"
93+
/>
10194
</span>
10295
);
10396
}
10497

10598
// ---------------------------------------------------------------
106-
// <LogoCompact /> — icon + "GCD"
99+
// <LogoCompact /> — ghost icon + "GCD"
107100
// ---------------------------------------------------------------
108101

109102
export function LogoCompact({ className, height = 32 }: LogoProps) {
@@ -123,21 +116,4 @@ export function LogoCompact({ className, height = 32 }: LogoProps) {
123116
);
124117
}
125118

126-
// ---------------------------------------------------------------
127-
// Wordmark
128-
// ---------------------------------------------------------------
129-
130-
function Wordmark() {
131-
return (
132-
<span className="font-display text-[1.02rem] leading-none tracking-tight text-foreground">
133-
<span className="font-semibold">Ghost</span>
134-
<span className="font-medium text-foreground/85">Code</span>
135-
<span className="mx-1 text-muted-foreground/60">·</span>
136-
<span className="font-medium tracking-[0.02em] text-muted-foreground">
137-
Dynamics
138-
</span>
139-
</span>
140-
);
141-
}
142-
143119
export { LogoMark as GhostIcon };

src/components/site-footer.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ export function SiteFooter() {
88
<div className="container-prose py-16">
99
<div className="grid gap-12 md:grid-cols-12">
1010
<div className="md:col-span-5">
11-
<Logo height={38} />
12-
<p className="mt-4 max-w-sm text-sm leading-relaxed text-muted-foreground">
11+
<Logo height={56} />
12+
<p className="mt-5 max-w-sm text-sm leading-relaxed text-muted-foreground">
1313
Building digital solutions for businesses while empowering the next generation of tech professionals.
1414
</p>
1515
<div className="mt-6 flex items-center gap-2">

src/routes/__root.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,10 @@ export const Route = createRootRouteWithContext<{ queryClient: QueryClient }>()(
113113
],
114114
links: [
115115
{ rel: "stylesheet", href: appCss },
116-
{ rel: "icon", href: "/favicon.png", type: "image/png" },
117-
{ rel: "icon", href: "/favicon.svg", type: "image/svg+xml" },
116+
{ rel: "icon", href: "/favicon.png", type: "image/png", sizes: "any" },
117+
{ rel: "icon", href: "/favicon-32x32.png", type: "image/png", sizes: "32x32" },
118+
{ rel: "icon", href: "/favicon-16x16.png", type: "image/png", sizes: "16x16" },
119+
{ rel: "apple-touch-icon", href: "/apple-touch-icon.png", sizes: "180x180" },
118120
],
119121
}),
120122
shellComponent: RootShell,

0 commit comments

Comments
 (0)