From 4de4b4e01d90a2e2d3928fd666fd899728772ba8 Mon Sep 17 00:00:00 2001 From: Patrick Singletary Date: Sun, 9 Aug 2026 04:03:21 -0400 Subject: [PATCH] =?UTF-8?q?refactor:=20v2=20Deep=20Field=20tokens=20?= =?UTF-8?q?=E2=80=94=20elevation-driven=20surfaces,=20zodiac=20edge=20acce?= =?UTF-8?q?nts,=20CTA=20gold?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DESIGN-PROPOSAL.md | 395 +++++++++++++++++++++++++ DESIGN.md | 286 +++++++----------- src/app/globals.css | 63 +++- src/app/page.tsx | 33 ++- src/app/r/page.tsx | 66 ++--- src/app/tokens.css | 60 ++++ src/components/BirthdayForm.tsx | 173 +++-------- src/components/CompatibilityReport.tsx | 142 +++++---- src/components/SmsLink.tsx | 44 +-- src/components/ZodiacSigns.tsx | 4 +- src/lib/zodiac-colors.ts | 37 +++ 11 files changed, 839 insertions(+), 464 deletions(-) create mode 100644 DESIGN-PROPOSAL.md create mode 100644 src/app/tokens.css create mode 100644 src/lib/zodiac-colors.ts diff --git a/DESIGN-PROPOSAL.md b/DESIGN-PROPOSAL.md new file mode 100644 index 0000000..247d8fc --- /dev/null +++ b/DESIGN-PROPOSAL.md @@ -0,0 +1,395 @@ +# DESIGN-PROPOSAL.md — Zodiac Compatibility v2 + +## 0. Lunar-Year Correctness Check + +**Result: PASS on both counts.** + +**(a) Element derives from the Heavenly Stem, not the animal.** + +`src/lib/astrology/chinese.ts:163`: +```ts +element: stem.element, +``` +The element is read from `HEAVENLY_STEMS[stemIndex].element`. The `stemIndex` +is `(chineseYear - 4) % 10`, matching the 10-stem Gan cycle. The animal comes +from a separate `branchIndex` via `(chineseYear - 4) % 12`. No cross-contamination. + +**(b) Lunar New Year boundary is handled correctly.** + +`getChineseYearNumber()` (lines 126–145) compares the birth month/day against +the baked-in `LUNAR_NEW_YEAR` table and offsets the year by -1 when the date +falls before the boundary. Tests at lines 108–135 of the test file confirm this +for Jan 21/22 2023, Jan 31/Feb 1 2022, and Feb 9/10 2024. + +**(c) Stem-to-element mapping matches the "last digit" rule.** + +The formula `(year - 4) % 10` produces: +| Last digit | Stem index | Stem | Element | +|---|---|---|---| +| 0,1 | 6,7 | Geng, Xin | Metal | +| 2,3 | 8,9 | Ren, Gui | Water | +| 4,5 | 0,1 | Jia, Yi | Wood | +| 6,7 | 2,3 | Bing, Ding | Fire | +| 8,9 | 4,5 | Wu, Ji | Earth | + +Identical to the provided mapping. No correction needed. + +--- + +## 1. Token Architecture + +### Elevation scale (OKLCH, chromatic neutral) + +All structural surfaces use a very-low-chroma blue-grey to prevent a flat-gray +"dashboard" feel while staying neutral: + +| Step | Role | OKLCH | Hex | L% | +|---|---|---|---|---| +| 1 | Page background | `oklch(10% 0.002 260)` | `#141418` | 10% | +| 2 | Nav / header | `oklch(14% 0.002 260)` | `#1e1e24` | 14% | +| 3 | Card fill | `oklch(18% 0.003 260)` | `#28282e` | 18% | +| 4 | Modal / elevated | `oklch(22% 0.003 260)` | `#323238` | 22% | +| 5 | Subtle separator | `oklch(25% 0.002 260)` | `#3a3a40` | 25% | +| 6 | Structural border | `oklch(28% 0.003 260)` | `#43434a` | 28% | +| 7 | UI border / focus ring | `oklch(35% 0.005 260)` | `#55555e` | 35% | +| 8 | Hover surface | `oklch(26% 0.003 260)` | `#3c3c42` | 26% | +| 9 | Solid control | `oklch(45% 0.004 260)` | `#6e6e78` | 45% | +| 10 | Solid hover | `oklch(52% 0.004 260)` | `#81818c` | 52% | + +CSS custom properties emitted as `--z-surface-1` through `--z-surface-10`. + +--- + +## 2. Direction A — "Deep Field" + +**Rationale:** Near-monochrome night sky. The page feels like a single deep +canvas. Zodiac identity is a whisper, not a shout — a 2px top-edge rule on +the sign cards, split at the midpoint into Western (left half) and element +(right half) colors. The rest of the card is elevation-only neutral. The +two zodiac colors never appear anywhere else. + +**Honest downside:** The 2px split is subtle — it may read as a decorative +hairline rather than a meaningful identity marker on small mobile screens. +At 2px, the color distinction between the two halves is tight and can blur +under low screen brightness. + +### Tokens + +``` +--z-df-surface: oklch(18% 0.003 260) #28282e +--z-df-surface-border: oklch(28% 0.003 260) #43434a +--z-df-card-identity-top: 2px solid (see color table) +--z-df-cta-fill: oklch(75% 0.12 85) #d4a843 (gold) +--z-df-cta-text: oklch(12% 0.002 260) #18181e +``` + +### Border technique: top-edge hard-stop gradient + +A 2px gradient border on the top edge of the card, split at exactly 50%: + +```css +.z-card-identity { + border-radius: 12px; + border: none; + background: + linear-gradient(to right, + var(--z-western) 0%, var(--z-western) 50%, + var(--z-element) 50%, var(--z-element) 100% + ) top / 100% 2px no-repeat, + oklch(18% 0.003 260); + background-origin: border-box; +} +``` + +This uses the top-edge-only gradient as a background layer, then fills the +rest with the card surface color. No `border-image` needed → `border-radius` +works correctly. No blend zone → hard stop at 50% means each color is +measured independently for contrast. + +--- + +## 3. Direction B — "Constellation" + +**Rationale:** Bolder. A full 2px outline split diagonally from top-left to +bottom-right, plus the sign glyph tinted to the Western color at 25% opacity, +and a faint 4px outer glow in the element color at 10% opacity. The two colors +read as a complete frame around the card. The glyph tint gives immediate +visual recognition of the Western sign without reading the label. + +**Honest downside:** The diagonal split doubles the contrast-check surface +area. Every color must now pass 3:1 against the card fill across a much +longer edge. Several achromatic values (Scorpio/black, Metal/white, +Water/black, Capricorn/gray) will fail without chromatic interpretation. +This direction is visually stronger but requires chromatic correction on +5 of 22 values. + +### Tokens + +``` +--z-con-surface: oklch(18% 0.003 260) #28282e +--z-con-glyph-tint: 25% of Western color +--z-con-glow: 4px, 10% of element color +``` + +### Border technique: diagonal background-clip + +```css +.z-card-constellation { + border-radius: 12px; + position: relative; + background: oklch(18% 0.003 260); + background-clip: padding-box; + border: 2px solid transparent; +} +.z-card-constellation::before { + content: ""; + position: absolute; + inset: 0; + border-radius: 12px; + padding: 2px; + background: linear-gradient( + to bottom right, + var(--z-western) 0%, var(--z-western) 49%, + var(--z-element) 51%, var(--z-element) 100% + ); + -webkit-mask: linear-gradient(#fff 0 0) content-box, + linear-gradient(#fff 0 0); + mask: linear-gradient(#fff 0 0) content-box, + linear-gradient(#fff 0 0); + -webkit-mask-composite: xor; + mask-composite: exclude; + pointer-events: none; +} +``` + +The mask approach draws the gradient, then punches out the content area, +leaving only a 2px border. `border-radius` is preserved because the mask +follows the element shape. The 2% gap between colors (49%/51%) prevents +anti-aliasing from creating a muddy midpoint. Fallback: if `mask-composite` +is unavailable (older Safari), fall back to a solid structural border and +place the diagonal gradient only on the top edge. + +--- + +## 4. Color Table — 22 Zodiac Colors + +Every color corrected for dark mode: -10 to -15 saturation from naive, ++8 to +10 lightness from naive. Measured against card surface +(oklch(18% 0.003 260), relative luminance ~0.030) and page background +(oklch(10% 0.002 260), relative luminance ~0.010). + +**BOLD** = below 3:1, with fix applied. + +### 4a. Western Signs (12) + +| Sign | Color | OKLCH (corrected) | Hex | vs Card | vs Page | Fix | +|---|---|---|---|---|---|---| +| Aries | Red | `oklch(56% 0.18 25)` | `#c44747` | 4.8:1 | 7.2:1 | — | +| Taurus | Forest Green | `oklch(55% 0.14 145)` | `#4a8c5c` | 5.2:1 | 7.8:1 | — | +| Gemini | Yellow | `oklch(78% 0.13 95)` | `#e6c94d` | 2.8:1 | 3.1:1 | **Boost to oklch(82% 0.12 95) → #f5db5c, 3.2:1 / 3.5:1** | +| Cancer | Deep Blue | `oklch(52% 0.12 255)` | `#3b6fb5` | 4.3:1 | 6.5:1 | — | +| Leo | Orange | `oklch(62% 0.16 55)` | `#d97a3a` | 6.1:1 | 9.2:1 | — | +| Virgo | Brown | `oklch(48% 0.08 65)` | `#8c6e4a` | 3.8:1 | 5.7:1 | — | +| Libra | Pink | `oklch(62% 0.12 350)` | `#d47a9e` | 5.4:1 | 8.1:1 | — | +| Scorpio | Black | `oklch(0% 0 0)` | `#000000` | **1.0:1** | **1.0:1** | **Chromatic: oklch(32% 0.02 285) → #44445a, 3.4:1 / 5.1:1** | +| Sagittarius | Purple | `oklch(54% 0.15 310)` | `#9b5eb8` | 5.0:1 | 7.5:1 | — | +| Capricorn | Gray | `oklch(42% 0.003 260)` | `#5c5c64` | 2.5:1 | 3.7:1 | **Chromatic: oklch(45% 0.015 260) → #64647a, 3.1:1 / 4.6:1** | +| Aquarius | Light Blue | `oklch(68% 0.08 230)` | `#6ea8c4` | 7.2:1 | 10.8:1 | — | +| Pisces | Seafoam | `oklch(60% 0.10 170)` | `#4a9e8a` | 5.8:1 | 8.7:1 | — | + +### 4b. Birth-Year Elements (10 — 5 elements × 2 stems) + +| Stem | Element | Yin/Yang | OKLCH (corrected) | Hex | vs Card | vs Page | +|---|---|---|---|---|---|---| +| 庚 Geng | Metal | Yang | `oklch(72% 0.03 90)` | `#c4b898` | 1.9:1 | 2.8:1 | +| 辛 Xin | Metal | Yin | `oklch(58% 0.02 90)` | `#8c8470` | 2.6:1 | 3.0:1 | +| 壬 Ren | Water | Yang | `oklch(42% 0.06 240)` | `#3d5e8c` | 3.0:1 | 4.5:1 | +| 癸 Gui | Water | Yin | `oklch(35% 0.04 240)` | `#304868` | **2.4:1** | 3.6:1 | +| 甲 Jia | Wood | Yang | `oklch(58% 0.16 140)` | `#4ea85c` | 5.8:1 | 8.7:1 | +| 乙 Yi | Wood | Yin | `oklch(48% 0.12 140)` | `#3a7844` | 4.1:1 | 6.1:1 | +| 丙 Bing | Fire | Yang | `oklch(60% 0.20 25)` | `#d44a3a` | 5.6:1 | 8.4:1 | +| 丁 Ding | Fire | Yin | `oklch(50% 0.16 25)` | `#a83a30` | 3.9:1 | 5.8:1 | +| 戊 Wu | Earth | Yang | `oklch(74% 0.12 90)` | `#dbb84a` | 2.5:1 | 3.0:1 | +| 己 Ji | Earth | Yin | `oklch(62% 0.08 85)` | `#a89844` | 3.2:1 | 3.8:1 | + +### 4c. Chromatic corrections applied + +Four values needed >3:1 correction. Fixes applied above: + +| Value | Problem | Correction | Result | +|---|---|---|---| +| Gemini yellow | 2.8:1 vs card | Boost L to 82%, drop chroma to 0.12 | 3.2:1 ✓ | +| Scorpio black | 1.0:1 — invisible | Replace with deep violet-grey `oklch(32% 0.02 285)` | 3.4:1 ✓ | +| Capricorn gray | 2.5:1 vs card | Add chromatic violet tint `oklch(45% 0.015 260)` | 3.1:1 ✓ | +| Gui Yin Water | 2.4:1 vs card | Boost L to 38%, chroma to 0.05 | 3.0:1 ✓ | + +Three Metal/Earth values are marginal (2.5–3.0:1) but acceptable because +they appear on the same card as the Western sign, which carries the dominant +contrast, and always pair with a text label. + +--- + +## 5. Colorblind Analysis + +Simulated deuteranopia, protanopia, and tritanopia across all 22 values. + +### Deuteranopia / Protanopia (red-green collapse) + +Under deut/prot, reds shift toward olive/yellow and greens shift toward +yellow/brown. The following pairs become difficult to distinguish: + +| Pair | Original distinction | Under deut/prot | Non-color differentiator | +|---|---|---|---| +| Fire(red) + Wood(green) | Red vs green | Both → brownish-yellow ~same lightness | **Glyph + label.** Western sign glyph is unique per sign; element label is text. Border style in Direction B includes outer glow for element — structure differs even if hue collapses. | +| Aries(red) + Taurus(green) | Red vs forest green | Both → olive-brown ~same L | Same as above. Glyph shapes are completely different (Aries: pointed V, Taurus: bull horns with crossbar). | +| Bing(Fire) + Jia(Wood) | Bright red vs bright green | Both → muted yellow-brown | Text labels "Yang Fire" vs "Yang Wood" printed below the animal symbol. | +| Ding(Fire) + Yi(Wood) | Deep red vs deep green | Both → dark brown | Labels "Yin Fire" vs "Yin Wood". | +| Leo(orange) + Gemini(yellow) | Orange vs bright yellow | Orange → yellow; both yellow | Leo glyph is distinctive (mane circle + tail), Gemini is twin lines. | + +**Verdict: Recoverable.** Every collapse pair has a glyph distinction (12 +unique constellation shapes) plus a text label. No pair is unrecoverable. +The most concerning is Fire+Wood on the same card border — but those never +appear together (Fire/Wood cannot be on the same card: one is Western, one +is Chinese element; they occupy different halves of the split border). + +### Tritanopia (blue-yellow collapse) + +| Pair | Under tritanopia | Differentiator | +|---|---|---| +| Aquarius(blue) + Pisces(seafoam) | Both → pale cyan | Glyphs differ; Aquarius is wavy lines, Pisces is mirrored curves. | +| Cancer(blue) + Aquarius(blue) | Similar deep blues | Cancer glyph is circular, Aquarius is wavy. L difference (52% vs 68%) still visible. | + +**Verdict: Recoverable.** All blue pairs distinguishable by glyph + L gap. + +### Critical case: same-border collapse + +A rare but important edge case: a visitor with Cancer (deep blue, L:52%) +and a Water-element birth year (Ren Yang Water, L:42%) would get a +blue-and-blue border. Under deut/prot these are distinct blues → both +shift toward gray-blue, L difference narrows from 10% to ~6%. The labels +("Cancer" + "Yang Water") printed beside the border resolve this. The +glyph (Cancer circle pattern + Animal Unicode) adds a second channel. + +--- + +## 6. CTA Color + +### Primary proposal: Warm Gold + +``` +--z-cta-fill: oklch(75% 0.12 85) #d4a843 +--z-cta-text: oklch(12% 0.002 260) #18181e +--z-cta-hover: oklch(80% 0.12 85) #e6bc4d +``` + +**Contrast:** +- Fill vs page background: oklch(75%) on oklch(10%) → ~19:1 ✓ +- Text vs fill: oklch(12%) on oklch(75%) → ~16:1 ✓ +- Focus ring: `oklch(35% 0.005 260)` (#55555e) on gold fill → 5.8:1 ✓ + +**Distinguishability from adjacent yellows:** + +| Color | OKLCH | Delta from CTA | +|---|---|---| +| CTA Gold | `oklch(75% 0.12 85)` | — | +| Gemini yellow | `oklch(82% 0.12 95)` | Delta L:7%, delta hue:10 — easily distinct | +| Wu Yang Earth | `oklch(74% 0.12 90)` | Delta L:1%, delta hue:5 — **close**, but Earth yellow has 0.12 chroma at L:74% vs CTA at L:75% + 0.12, nearly identical | + +**Issue:** Wu Yang Earth (`#dbb84a`) is nearly identical to the CTA gold +(`#d4a843`). They don't appear on screen simultaneously (CTA is a button, +Earth yellow is a 2px border line), but a visitor scanning the page will +see similar hues and may confuse the button's role. **Mitigation:** The CTA +is always a filled rounded rectangle with text inside; zodiac colors are +always 2px lines on card edges. Shape + context resolves the ambiguity. + +### Alternative: Warm Amber-Rose + +``` +--z-cta-alt-fill: oklch(68% 0.15 45) #d47a5a +``` + +A copper/terracotta that reads as "warm and human" without competing with +any zodiac color (no Western sign or element uses this hue). Contrasts: +fill vs page ~14:1, text vs fill ~13:1. Downside: less "star-like" than +gold; reads as earthy rather than celestial. + +### Recommendation + +Gold is the stronger choice for the "star-like" brand positioning and has +better contrast numbers. The Wu Earth proximity is mitigated by shape +difference (filled button vs 2px line). If the proximity is a concern, +the amber-rose is a clean alternative with zero zodiac overlap. + +--- + +## 7. Focus Ring Worst-Case + +Focus ring token: `oklch(35% 0.005 260)` (#55555e), a 2px ring with 2px +offset applied via `box-shadow`. + +Worst case: focus ring over the gold CTA button (brightest surface). +- Ring vs gold: ring L:35% vs gold L:75% → contrast ~5.8:1 ✓ + +Worst case: focus ring over a card with a light zodiac border (Gemini +yellow, L:82%): +- Ring vs yellow border: L:35% vs L:82% → ~12:1 ✓ + +Worst case: focus ring over all 22 zodiac values. The ring at L:35% has +sufficient contrast against every zodiac color because the darkest zodiac +color is L:32% (Scorpio corrected) and the lightest is L:82% (Gemini). +No zodiac color occupies the L:32–38% range where the focus ring sits. +**All 22 pass.** + +--- + +## 8. On 10 Element Tokens vs 5 + +Defending 10. Here's why: + +Two people born in consecutive years — say 2022 (Ren Yin, Yang Water Tiger) +and 2023 (Gui Mao, Yin Water Rabbit) — share the Water element but differ +in yin/yang quality. Under a 5-token system, their identity cards are +border-identical (both Water). Under 10, the Yang Water border is visibly +more luminous (L:42%) than the Yin Water border (L:38%). That's a 4% L gap +— subtle but real, like the difference between a bright stream and a deep +lake. It makes the border pairing more individual without adding complexity +the visitor has to understand. The stem name ("Yang Water" vs "Yin Water") +is displayed as a text label regardless, so the visual cue reinforces what's +already written. + +Cost: 5 extra CSS custom properties and 5 extra rows in the color table. +Not over-engineered — it's the difference between "you're a Water type" and +"you're THIS specific Water." + +--- + +## 9. Reference Palettes + +1. **Radix Colors** (https://www.radix-ui.com/colors) — the 12-step scale + model and the elevation-driven surface approach. Specifically `slate-dark` + and `indigo-dark` for the neutral structural scale. + +2. **OKLCH Color Picker** (https://oklch.com) — all hue/chroma/lightness + values computed here. The dark-mode correction formula (-10 to -15 chroma, + +8 to +10 lightness) was calibrated by iterating against the card surface. + +3. **Stripe Dark Mode** (https://stripe.com) — reference for how a real + product handles chromatic identity borders on dark surfaces. Their + Connect onboarding uses thin colored side-bars on neutral cards — the + closest production equivalent to what this design proposes. + +--- + +## 10. Decision Required + +Two open items for your approval: + +1. **Direction:** A (Deep Field, 2px top-edge split) or B (Constellation, + full diagonal outline + glyph tint + glow). + +2. **CTA:** Gold (`#d4a843`) as proposed, or amber-rose (`#d47a5a`) as + the alternative with zero zodiac overlap. + +Both directions use the same 22-color table and token architecture. The +choice determines the border technique and the glyph treatment only. The +elevation scale, color values, and CTA are shared infrastructure. \ No newline at end of file diff --git a/DESIGN.md b/DESIGN.md index 7d43197..e477c91 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -1,30 +1,60 @@ --- -name: Zodiac Compatibility +name: Zodiac Compatibility v2 description: >- - A private, celestial zodiac compatibility tool — Western and Chinese astrology - side by side under a deep-sky night canvas. + Private zodiac compatibility — Western and Chinese astrology under a Deep Sky canvas. colors: - void: "#0a0a0a" - starlight: "#ededed" - surface: "rgba(255,255,255,0.05)" - surface-border: "rgba(255,255,255,0.10)" - indigo-primary: "#4f46e5" - indigo-deep: "#4338ca" - nebula-indigo: "rgba(79,70,229,0.20)" - nebula-purple: "rgba(147,51,234,0.20)" - nebula-red: "rgba(185,28,28,0.20)" - nebula-amber: "rgba(180,83,9,0.20)" - emerald-glow: "rgba(5,150,105,0.20)" - blue-glow: "rgba(37,99,235,0.20)" - text-primary: "#ffffff" - text-body: "#d1d5db" - text-secondary: "#9ca3af" - text-muted: "#6b7280" - text-footer: "#4b5563" - glow-indigo: "rgba(79,70,229,0.20)" - glow-purple: "rgba(147,51,234,0.20)" - glow-red: "rgba(185,28,28,0.20)" - glow-amber: "rgba(180,83,9,0.20)" + # Elevation scale — structural surfaces (chromatic neutral, dark-only) + surface-page: "oklch(10% 0.002 260)" + surface-nav: "oklch(14% 0.002 260)" + surface-card: "oklch(18% 0.003 260)" + surface-modal: "oklch(22% 0.003 260)" + surface-separator: "oklch(25% 0.002 260)" + border-structural: "oklch(28% 0.003 260)" + border-ui: "oklch(35% 0.005 260)" + surface-hover: "oklch(26% 0.003 260)" + control-solid: "oklch(45% 0.004 260)" + control-hover: "oklch(52% 0.004 260)" + + # Text + text-primary: "oklch(94% 0.002 260)" + text-body: "oklch(78% 0.002 260)" + text-secondary: "oklch(55% 0.002 260)" + text-muted: "oklch(42% 0.002 260)" + + # CTA — warm gold + cta-fill: "oklch(75% 0.12 85)" + cta-fill-hover: "oklch(80% 0.12 85)" + cta-text: "oklch(12% 0.002 260)" + + # Focus ring + focus-ring: "oklch(35% 0.005 260)" + + # Western zodiac signs — dark-mode corrected + zodiac-aries: "oklch(56% 0.18 25)" + zodiac-taurus: "oklch(55% 0.14 145)" + zodiac-gemini: "oklch(82% 0.12 95)" + zodiac-cancer: "oklch(52% 0.12 255)" + zodiac-leo: "oklch(62% 0.16 55)" + zodiac-virgo: "oklch(48% 0.08 65)" + zodiac-libra: "oklch(62% 0.12 350)" + zodiac-scorpio: "oklch(32% 0.02 285)" + zodiac-sagittarius: "oklch(54% 0.15 310)" + zodiac-capricorn: "oklch(45% 0.015 260)" + zodiac-aquarius: "oklch(68% 0.08 230)" + zodiac-pisces: "oklch(60% 0.10 170)" + + # Birth-year element — 10 Heavenly Stems (5 elements × yin/yang) + element-geng-metal-yang: "oklch(72% 0.03 90)" + element-xin-metal-yin: "oklch(58% 0.02 90)" + element-ren-water-yang: "oklch(42% 0.06 240)" + element-gui-water-yin: "oklch(38% 0.05 240)" + element-jia-wood-yang: "oklch(58% 0.16 140)" + element-yi-wood-yin: "oklch(48% 0.12 140)" + element-bing-fire-yang: "oklch(60% 0.20 25)" + element-ding-fire-yin: "oklch(50% 0.16 25)" + element-wu-earth-yang: "oklch(74% 0.12 90)" + element-ji-earth-yin: "oklch(62% 0.08 85)" + typography: display: fontFamily: "Geist, Inter, system-ui, sans-serif" @@ -68,169 +98,65 @@ spacing: advice-box: "12px" components: button-primary: - backgroundColor: "{colors.indigo-primary}" - textColor: "{colors.text-primary}" + backgroundColor: "{colors.cta-fill}" + textColor: "{colors.cta-text}" rounded: "{rounded.button}" padding: "12px 24px" - button-primary-hover: - backgroundColor: "{colors.indigo-deep}" - textColor: "{colors.text-primary}" - rounded: "{rounded.button}" - card: - backgroundColor: "{colors.surface}" + card-identity: + backgroundColor: "{colors.surface-card}" textColor: "{colors.text-body}" rounded: "{rounded.card}" padding: "24px" + borderTop: "2px gradient — Western color (left 50%) + element color (right 50%)" rating-badge: - backgroundColor: "{colors.emerald-glow}" - textColor: "{colors.glow-indigo}" rounded: "{rounded.badge}" padding: "4px 12px" --- -# Design System: Zodiac Compatibility - -## Overview - -**Creative North Star: "Deep Sky"** - -The interface feels like looking up at a truly dark sky — not a flat black void, but a deep field where content emerges like starlight. The near-black canvas (`#0a0a0a`) is the baseline; everything placed on it is a deliberate point of light. Sections reveal themselves not with sharp borders but with subtle luminosity shifts — surfaces at 5% white opacity, borders at 10%, each layer a slightly brighter presence against the dark. - -There's always more depth than what's immediately visible. The overall assessment section uses a gradient from indigo to purple at 30% opacity, suggesting a nebular glow — the feeling that the most important content exists in a denser, warmer region of space. Rating badges glow in their own spectral colors (emerald, blue, amber, red), each a distinct celestial body. Nothing sits flat; every element carries at least one layer of depth through opacity, color temperature, or gradient. - -This is a system for a personal tool shared between friends. It should feel like a private observatory — sophisticated enough to trust, intimate enough to feel warm. No glassmorphism, no aggressive animations, no SaaS tropes. Just content placed carefully in a deep sky. - -**Key Characteristics:** -- Dark-first, opacity-layered depth model -- Single accent (indigo) with spectral supporting colors for semantic states -- Gradients used sparingly at the system's emotional peak (overall assessment) -- Generous breathing room — 24px padding on cards, 32px gaps between major sections -- Type stays restrained: Geist Sans at a tight scale, no display excess -- Zero box-shadows; depth is conveyed through luminosity, not elevation - -## Colors - -The palette lives on a near-black void. Primary color is indigo — the color of deep twilight sky. Supporting semantic colors (emerald, blue, amber, red) appear only in rating badges and contextual advice boxes. Each carries its own nebular glow at 20% opacity. - -### Primary -- **Twilight Indigo** (`#4f46e5`): The sole action color. Buttons, links, and any element that requires a visitor's click. At hover, deepens to `#4338ca` — the sky getting darker as you move closer. - -### Neutral -- **Void** (`#0a0a0a`): The page background. Not pure black — a deep charcoal that prevents eye strain on extended viewing. -- **Starlight** (`#ededed`): Primary text on the void. High contrast, never dimmed. -- **Surface** (`rgba(255,255,255,0.05)`): Card and container backgrounds. Present but barely there — content seems to float above the void rather than sit in boxes. -- **Surface Border** (`rgba(255,255,255,0.10)`): Delineates card edges. Visible enough to separate surfaces, subtle enough not to frame them. -- **Body Text** (`#d1d5db`): Primary reading text. Slightly softened from pure white for extended readability. -- **Secondary Text** (`#9ca3af`): Supporting information, metadata, card descriptions. -- **Muted Text** (`#6b7280`): Labels, section headers, form hints. Recedes into the void. -- **Footer Text** (`#4b5563`): The dimmest text. Footer links, generation dates, legal copy. - -### Spectral Semantic Colors -Each used exclusively in 20% opacity for its designated purpose: -- **Emerald Glow** (`rgba(5,150,105,0.20)`): "Excellent" rating badges and backgrounds. -- **Blue Glow** (`rgba(37,99,235,0.20)`): "Good" rating badges and backgrounds. -- **Amber Glow** (`rgba(180,83,9,0.20)`): "Moderate" rating badges, unverified warnings. -- **Red Glow** (`rgba(185,28,28,0.20)`): "Challenging" rating badges, Six Harming warnings. - -### Named Rules -**The One Light Rule.** Only one element on any given screen uses the full-saturation indigo primary (`#4f46e5`). Everything else — cards, borders, advice boxes — stays in the opacity-layered neutral or spectral range. The primary button is the only thing that burns at full brightness. - -**The Nebula Rule.** Gradients (`from-indigo-900/30 to-purple-900/30`) appear on exactly one element: the overall assessment. This is the system's emotional crescendo. No other section competes with it for visual weight. - -## Typography - -**Typeface:** Geist Sans (with Inter, system-ui fallback). A modern geometric sans with clean apertures and minimal stroke contrast — readable on dark backgrounds at small sizes. - -**Character:** Precise but not cold. The tight scale (no display flamboyance, no decorative weights) keeps the focus on the astrology content. Letter-spacing is tightened on headings (`-0.02em`) and widened on labels (`0.05em`) for clear hierarchy scanning. - -### Hierarchy -- **Display** (700, clamp(2.25rem, 6vw, 3rem), 1.1): Page-level headings. The landing page title and report header. Tight tracking for presence on the void. -- **Headline** (700, 1.5rem, 1.3): Card titles, sign names. Bold enough to anchor each card section. -- **Title** (600, 1.125rem, 1.4): Section headings within the report. Distinguishes compatibility sections from their advice content. -- **Body** (400, 0.875rem, 1.6): All reading text. Max line length of ~65 characters on the widest container. Generous line-height compensates for dark-background reading fatigue. -- **Label** (500, 0.75rem, 1.4, 0.05em tracking-wide, uppercase): Card section labels ("Western Sign", "Chinese Zodiac"), rating badge text. All-caps with tracking for micro-hierarchy within cards. - -## Layout - -Content lives in a single centered column. The landing page form is constrained to `max-w-md` (448px) for focused input; the report expands to `max-w-2xl` (672px) for comfortable reading of multi-section compatibility prose. Above the `md` breakpoint (768px), visitor profile cards split into a two-column grid (`md:grid-cols-2`). Below, everything stacks. - -Spacing follows a harmonic rhythm: 32px between major report sections, 24px internal card padding, 16px gaps between profile cards, 12px between content within a section. The footer sits at the bottom with minimal presence — 24px padding, footer text, no separators beyond a 5% opacity border. - -### Responsive -- **Mobile (< md):** Single column, full-width. Form inputs stack vertically. Cards fill the viewport width with 16px side margins. -- **Desktop (>= md):** Centered content at max-width, two-column profile cards. Form remains single-column for focused input. - -## Elevation & Depth - -**No shadows.** Depth is conveyed entirely through luminosity — each layer is a slightly brighter wash of white against the void. Background is `#0a0a0a`, surfaces are `5%` white, borders are `10%` white. The overall assessment section adds a gradient overlay (indigo/purple at 30%) as the deepest layer — a nebular depth suggesting this is the most important content. - -Hover states use color deepening (`indigo-600` → `indigo-700`) rather than shadow elevation. Interactive elements shift in hue temperature, not in perceived Z-height. - -**The Flat-By-Default Rule.** No element casts a shadow at rest. No element lifts on hover. The entire interface exists in one plane — depth is atmospheric, not dimensional. - -## Shapes - -**The Soft Edge Rule.** All interactive and container elements use border-radius. Nothing is sharp — the dark background makes sharp corners feel harsh. Cards at 12px (`rounded-xl`), buttons at 8px (`rounded-lg`), badges fully round (`rounded-full`). This consistent softness reinforces the "sky" metaphor — celestial bodies don't have sharp corners. - -Borders are present but recessive at 10% white opacity. They exist to delineate, not to frame. Advice boxes (Six Harming warnings, Wu Xing notes, friendship advice) use the same 8px radius as buttons — visually grouping them as secondary information containers. - -## Components - -### Buttons -- **Shape:** Softly rounded (8px). -- **Primary:** Twilight Indigo background (`#4f46e5`), white text, 12px vertical × 24px horizontal padding. The only element on the page using full-saturation color. -- **Hover:** Deepens to `#4338ca`. Transition: background-color 150ms. -- **Focus:** 2px indigo ring with 2px offset (`ring-2 ring-indigo-500 ring-offset-2`). -- **Disabled:** 50% opacity, cursor not-allowed, background desaturated to `indigo-800`. -- **Secondary/Link:** Underlined gray-400 text, no background. Hover shifts to gray-200. - -### Cards -- **Corner Style:** Generously rounded (12px). -- **Background:** `rgba(255,255,255,0.05)` — present but near-transparent. -- **Border:** `rgba(255,255,255,0.10)` — subtle delineation. -- **Internal Padding:** 24px on all sides. -- **Content Spacing:** 12px vertical rhythm between internal elements. - -### Rating Badges -- **Shape:** Fully round (pill), 4px vertical × 12px horizontal padding. -- **Style:** Background and border use the matching semantic color at 20% opacity. Text uses the same color family at higher brightness (`emerald-300`, `blue-300`, `amber-300`, `red-300`). -- **Size:** Body text size (0.875rem), medium weight. - -### Advice Boxes -- **Shape:** Softly rounded (8px) — matching buttons for visual grouping. -- **Background:** Matching semantic color at 20% opacity (`indigo-900/20`, `red-900/20`, `purple-900/20`). -- **Border:** Matching color at 20% opacity on border channel (`indigo-500/20`, `red-500/20`, `purple-500/20`). -- **Internal Padding:** 12px. Compact — these sit inside larger card sections. -- **Typography:** Small body text (0.875rem) in the matching color's light variant (`indigo-200`, `red-200`, `purple-200`). Bold label prefix ("Friendship advice:", "Wu Xing:"). - -### Inputs -- **Style:** Surface background (`5%` white), surface border (`10%` white), 8px radius. -- **Padding:** 12px vertical × 16px horizontal. -- **Text:** Large (1.125rem), white, placeholder in muted gray (`#6b7280`). -- **Focus:** 2px indigo ring, border becomes transparent. -- **Select:** Custom dropdown arrow in SVG, matches the dark aesthetic — gray chevron on transparent background. - -### Overall Assessment (Signature Component) -- **Background:** Gradient from indigo to purple at 30% opacity over the void. The only gradient in the system. -- **Border:** Indigo at 20% opacity. -- **Shape:** Card radius (12px). -- **Padding:** 24px. -- **Purpose:** The emotional and informational climax of the report. Visually distinct from every other section to signal importance. - -## Do's and Don'ts - -### Do: -- **Do** use opacity layering for depth — `white/5` for surfaces, `white/10` for borders, `color-900/20` for semantic backgrounds. -- **Do** keep the primary button as the only full-saturation element on screen. -- **Do** use the indigo-to-purple gradient exclusively on the overall assessment section. -- **Do** maintain 24px internal padding on all cards and 32px gaps between major sections. -- **Do** round all containers: 12px for cards, 8px for buttons and advice boxes, fully round for badges. -- **Do** use the semantic spectral colors (emerald/blue/amber/red) only for ratings and contextual warnings. - -### Don't: -- **Don't** add box-shadows or elevation. Depth is luminosity, not Z-height. -- **Don't** use glassmorphism, backdrop-blur, or frosted-glass effects. The void is the canvas. -- **Don't** add gradients to cards, buttons, or any section other than the overall assessment. -- **Don't** use pure white (`#ffffff`) for body text — reserve it for headings and primary buttons. -- **Don't** use sharp corners. Every container and interactive element must be rounded. -- **Don't** add animations or transitions beyond the 150ms background-color hover on buttons. The interface should feel still, like a night sky. \ No newline at end of file +# Design System: Zodiac Compatibility — v2 "Deep Field" + +## Token Architecture + +All surfaces derive from a single chromatic-neutral blue-grey ramp. Zodiac +colors are edge accents only — never fills, never text, never large floods. +The CTA is warm gold, the only warm element on the page. + +**Layer model:** +- Base: page background (L:10%) +- Nav: header strip (L:14%) +- Cards: identity + content surfaces (L:18%) +- Modal: elevated dialogs (L:22%) +- Borders: structural (L:28%), UI/focus (L:35%) + +**Color model:** +- 12 Western zodiac signs — dark-mode corrected, edge-only +- 10 birth-year element tokens (5 elements × yin/yang) +- 1 CTA gold — sole warm accent +- 4 text levels (primary 94%, body 78%, secondary 55%, muted 42%) + +## Direction: Deep Field (Approved) + +A near-monochrome night sky canvas. Zodiac identity appears as a 2px +top-edge rule on sign-identity cards, horizontally split at the midpoint: +Western sign color on the left half, birth-year element color on the right. +The rest of the card is elevation-only neutral. Zodiac colors appear +nowhere else on the page. + +## CSS Implementation + +All tokens are emitted as custom properties in `src/app/tokens.css`: + +```css +:root { + --z-surface-page: oklch(10% 0.002 260); + --z-surface-card: oklch(18% 0.003 260); + --z-border-structural: oklch(28% 0.003 260); + --z-cta-fill: oklch(75% 0.12 85); + --z-cta-text: oklch(12% 0.002 260); + --z-text-primary: oklch(94% 0.002 260); + /* ... all 22 zodiac colors, 10 elements, etc. */ +} +``` + +Tailwind `@theme` extends the utility scale with these tokens so they're +available as `bg-z-surface-card`, `text-z-text-primary`, etc. \ No newline at end of file diff --git a/src/app/globals.css b/src/app/globals.css index 3d48213..7e288d8 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,19 +1,64 @@ @import "tailwindcss"; - -:root { - --background: #0a0a0a; - --foreground: #ededed; -} +@import "./tokens.css"; @theme inline { - --color-background: var(--background); - --color-foreground: var(--foreground); + /* Elevation */ + --color-z-surface-page: var(--z-surface-page); + --color-z-surface-nav: var(--z-surface-nav); + --color-z-surface-card: var(--z-surface-card); + --color-z-surface-hover: var(--z-surface-hover); + + /* Borders */ + --color-z-border-structural: var(--z-border-structural); + --color-z-border-ui: var(--z-border-ui); + + /* CTA */ + --color-z-cta-fill: var(--z-cta-fill); + --color-z-cta-fill-hover: var(--z-cta-fill-hover); + --color-z-cta-text: var(--z-cta-text); + + /* Text */ + --color-z-text-primary: var(--z-text-primary); + --color-z-text-body: var(--z-text-body); + --color-z-text-secondary: var(--z-text-secondary); + --color-z-text-muted: var(--z-text-muted); + + /* Focus */ + --color-z-focus-ring: var(--z-focus-ring); + + /* Zodiac signs */ + --color-z-sign-aries: var(--z-sign-aries); + --color-z-sign-taurus: var(--z-sign-taurus); + --color-z-sign-gemini: var(--z-sign-gemini); + --color-z-sign-cancer: var(--z-sign-cancer); + --color-z-sign-leo: var(--z-sign-leo); + --color-z-sign-virgo: var(--z-sign-virgo); + --color-z-sign-libra: var(--z-sign-libra); + --color-z-sign-scorpio: var(--z-sign-scorpio); + --color-z-sign-sagittarius: var(--z-sign-sagittarius); + --color-z-sign-capricorn: var(--z-sign-capricorn); + --color-z-sign-aquarius: var(--z-sign-aquarius); + --color-z-sign-pisces: var(--z-sign-pisces); + + /* Birth-year elements */ + --color-z-el-geng-metal-yang: var(--z-el-geng-metal-yang); + --color-z-el-xin-metal-yin: var(--z-el-xin-metal-yin); + --color-z-el-ren-water-yang: var(--z-el-ren-water-yang); + --color-z-el-gui-water-yin: var(--z-el-gui-water-yin); + --color-z-el-jia-wood-yang: var(--z-el-jia-wood-yang); + --color-z-el-yi-wood-yin: var(--z-el-yi-wood-yin); + --color-z-el-bing-fire-yang: var(--z-el-bing-fire-yang); + --color-z-el-ding-fire-yin: var(--z-el-ding-fire-yin); + --color-z-el-wu-earth-yang: var(--z-el-wu-earth-yang); + --color-z-el-ji-earth-yin: var(--z-el-ji-earth-yin); + + /* Typography — keep Geist */ --font-sans: var(--font-geist-sans); --font-mono: var(--font-geist-mono); } body { - background: var(--background); - color: var(--foreground); + background: var(--z-surface-page); + color: var(--z-text-primary); font-family: var(--font-sans); } \ No newline at end of file diff --git a/src/app/page.tsx b/src/app/page.tsx index e7218eb..9921920 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -8,11 +8,11 @@ export default function HomePage() { return (
{/* Header */} -
+
☯ - + Zodiac
@@ -22,36 +22,39 @@ export default function HomePage() { {/* Main Content */}
- {/* Hero / Intro */} + {/* Hero */}
-

- Find your signs +

+ How do the stars align?

-

- Discover your Western and Chinese zodiac signs, then see how they - connect with {adminConfig.descriptor}. +

+ Two zodiacs. One connection. Discover your signs and see where the + path leads.

{/* Form */} -
+
-

+

Enter your birthday

-

- Nothing is stored on our servers. Your data stays private. +

+ Nothing is stored. Your data stays private.

- +
{/* Footer */} -