From 12b6544a7d1cd56bd9dcc4f08038b634dda43696 Mon Sep 17 00:00:00 2001
From: Cursor Agent
Date: Fri, 10 Jul 2026 01:04:56 +0000
Subject: [PATCH 1/3] Fix unreadable Xanga mobile-nav links caused by an
overly-broad substring selector
html[data-theme="xanga"] body a[class*="bg-accent"] was meant to fix
contrast for links with a literal, resting bg-accent background, but
[class*=...] does substring matching against the whole class string - so
it also matched inactive mobile-nav links whose only accent-flavored class
was the hover-prefixed "hover:bg-accent-orange", forcing dark
--on-accent text onto them even at rest (on top of their actual dark navy
background), making Home/Blog/Contact/Hub/Links/V2ME/Learning/Projects
unreadable in the mobile menu.
Excludes any element whose class also contains "hover:bg-accent" from
this always-on rule, matching the same guard already used for the
analogous hover-only overrides a few lines down.
Co-authored-by: Thomas Bohn
---
app/globals.css | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/app/globals.css b/app/globals.css
index 11e61fc..59e59e4 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -270,15 +270,20 @@ html[data-theme="xanga"] body header nav a:focus-visible * {
on top of that background. This is deliberately not scoped to "header"
only: the mobile nav menu is a sibling of
diff --git a/app/globals.css b/app/globals.css
index 11e61fc..aff2b12 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -362,10 +362,23 @@ html[data-theme="xanga"] body [class*="text-text-secondary"] {
color: var(--text-secondary) !important;
}
-html[data-theme="xanga"] body [class*="text-accent"] {
+/* [class*="text-accent"] is a substring match, so without the :not() guards
+ it would also catch "text-accent-hover" and "text-accent-orange" (both
+ contain "text-accent") and force them to var(--accent) too, instead of
+ their own distinct shade - the same class of bug fixed above for
+ a[class*="bg-accent"]. */
+html[data-theme="xanga"] body [class*="text-accent"]:not([class*="text-accent-hover"]):not([class*="text-accent-orange"]) {
color: var(--accent) !important;
}
+html[data-theme="xanga"] body [class*="text-accent-hover"] {
+ color: var(--accent-hover) !important;
+}
+
+html[data-theme="xanga"] body [class*="text-accent-orange"] {
+ color: var(--accent-orange) !important;
+}
+
/* Input and form elements */
html[data-theme="xanga"] body input,
html[data-theme="xanga"] body textarea,
diff --git a/app/page.tsx b/app/page.tsx
index d40efa1..37d6657 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -80,7 +80,7 @@ export default function Home() {
{/* Bottom border accent with gradient */}
-
+
diff --git a/components/projects/ProjectArtifact.tsx b/components/projects/ProjectArtifact.tsx
index 5d588f9..9b6fbca 100644
--- a/components/projects/ProjectArtifact.tsx
+++ b/components/projects/ProjectArtifact.tsx
@@ -13,11 +13,14 @@ const typeLabels: Record = {
example: 'Example',
}
+// Uses theme-aware tokens (instead of hardcoded Tableau hex values) so these
+// badges shift with the active theme like everything else, rather than
+// staying frozen at their light-mode colors in dark/Xanga.
const typeColors: Record = {
- artifact: 'bg-[#1170aa]/10 text-[#1170aa] border-[#1170aa]/20', // Tableau Dark Blue
- deliverable: 'bg-[#5fa2ce]/10 text-[#5fa2ce] border-[#5fa2ce]/20', // Tableau Medium Blue
- phase: 'bg-[#57606c]/10 text-[#57606c] border-[#57606c]/20', // Tableau Dark Gray
- example: 'bg-[#fc7d0b]/10 text-[#fc7d0b] border-[#fc7d0b]/20', // Tableau Bright Orange
+ artifact: 'bg-accent/10 text-accent border-accent/20',
+ deliverable: 'bg-accent-hover/10 text-accent-hover border-accent-hover/20',
+ phase: 'bg-text-secondary/10 text-text-secondary border-text-secondary/20',
+ example: 'bg-accent-orange/10 text-accent-orange border-accent-orange/20',
}
export function ProjectArtifact({ artifact }: ProjectArtifactProps) {
diff --git a/tailwind.config.ts b/tailwind.config.ts
index 7291029..5d02e1e 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -1,5 +1,20 @@
import type { Config } from 'tailwindcss'
+// Our theme colors are plain CSS custom properties (e.g. `var(--accent)`)
+// rather than static hex/rgb values, since their actual value changes per
+// theme (light/dark/xanga). Tailwind can only generate opacity-modifier
+// utilities (e.g. `bg-accent/10`, `border-accent-orange/40`) for colors it
+// can decompose into RGB channels at build time - a bare `var(--x)` doesn't
+// qualify, so those classes were silently generating no CSS at all (fully
+// transparent, invisible borders) anywhere they were used. Wrapping each
+// color in `color-mix()` with the `` placeholder lets Tailwind
+// substitute the requested opacity at build time while still resolving the
+// actual color from the CSS variable at runtime. See:
+// https://github.com/tailwindlabs/tailwindcss/discussions/12824
+function withOpacity(cssVariable: string) {
+ return `color-mix(in srgb, var(${cssVariable}) calc( * 100%), transparent)`
+}
+
const config: Config = {
content: [
'./pages/**/*.{js,ts,jsx,tsx,mdx}',
@@ -9,22 +24,22 @@ const config: Config = {
theme: {
extend: {
colors: {
- 'bg-primary': 'var(--bg-primary)',
- 'bg-secondary': 'var(--bg-secondary)',
- 'text-primary': 'var(--text-primary)',
- 'text-secondary': 'var(--text-secondary)',
- 'accent': 'var(--accent)',
- 'accent-hover': 'var(--accent-hover)',
- 'accent-orange': 'var(--accent-orange)',
- 'accent-orange-hover': 'var(--accent-orange-hover)',
- 'accent-blue': 'var(--accent-blue)',
- 'accent-blue-hover': 'var(--accent-blue-hover)',
- 'on-accent': 'var(--on-accent)',
- 'on-accent-orange': 'var(--on-accent-orange)',
- 'on-accent-blue': 'var(--on-accent-blue)',
- 'border': 'var(--border)',
- 'link': 'var(--link)',
- 'link-hover': 'var(--link-hover)',
+ 'bg-primary': withOpacity('--bg-primary'),
+ 'bg-secondary': withOpacity('--bg-secondary'),
+ 'text-primary': withOpacity('--text-primary'),
+ 'text-secondary': withOpacity('--text-secondary'),
+ 'accent': withOpacity('--accent'),
+ 'accent-hover': withOpacity('--accent-hover'),
+ 'accent-orange': withOpacity('--accent-orange'),
+ 'accent-orange-hover': withOpacity('--accent-orange-hover'),
+ 'accent-blue': withOpacity('--accent-blue'),
+ 'accent-blue-hover': withOpacity('--accent-blue-hover'),
+ 'on-accent': withOpacity('--on-accent'),
+ 'on-accent-orange': withOpacity('--on-accent-orange'),
+ 'on-accent-blue': withOpacity('--on-accent-blue'),
+ 'border': withOpacity('--border'),
+ 'link': withOpacity('--link'),
+ 'link-hover': withOpacity('--link-hover'),
},
},
},