Dark mode bug: hardcoded rgba(10,10,10,0.3) used as text color
on dark backgrounds — unreadable.
Fix: html.dark overrides for:
- .marquee-track .ts
- .fx-marquee-track .ts
- .fx-log .ts
- .fx-footer-bottom
All now use rgba(250,238,200,0.4) (warm cream, legible on dark)
User reported: 'header menu มีบรรทัดเกิน แปลกๆ' — the 'หน้าแรก'
active link had 2 horizontal lines under it (coral ::after + gray border-bottom).
ROOT CAUSE: v7-5 .fx-nav-menu>li had border-bottom: 1px solid meant
for MOBILE menu (separating stacked items) but the rule escaped
the @media block during Phase 6.2 refactor and now applied to
ALL viewports.
FIX: Add .fx-nav-menu>li { border-bottom: none; } in base CSS
(placed AFTER the original v7-5 rule so cascade applies it).
Mobile @media block below still re-enables border-bottom:1px
for stacked menu.
Verified in built CSS: 12 .fx-nav-menu rules, override present
and last. Build: 22 pages, 2.06s.
ROOT CAUSE found via build artifact analysis:
- Built CSS files (dist/_astro/Base.*.css) had ZERO [data-theme='dark']
selectors even though source had 17. Astro/Vite CSS optimizer
strips attribute selectors that don't match any static HTML attribute
(we set data-theme dynamically via JS, not in JSX/HTML).
- Also stripped: all html { } and body { } rules from source.
- Result: dark mode visually did nothing. Body stayed white.
FIX:
- Replace [data-theme='dark'] with html.dark (17 occurrences in
fx-system.css). Vite keeps .dark class selectors because the
anti-flash script (in Base.astro <head>) sets a class, not an
attribute, which Vite sees as 'used'.
- Update anti-flash script in Base.astro: classList.add/remove
instead of setAttribute('data-theme', ...).
- Update UtilityBar.astro applyTheme() to use classList too.
- Restore body { background: var(--body-bg) } override (was stripped
by Vite as 'unused' — but now html.dark applies to it correctly).
ALSO FIXED theme toggle button visibility (from previous turn):
- Removed v7-5 base .fx-theme-toggle rule (rgba(0.1) opacity made
button invisible — only visible on hover).
- Consolidated into single rule with proper contrast for both modes.
Verified by:
- Build complete: 22 pages, 1.97s
- Built CSS: 17 html.dark selectors present (was 0)
- Body background override present in built CSS
- HTTP server on :4322 serving correct artifacts
User reported 2 issues after Phase 6.2:
1. 'marquee ควรต้องเลื่อนด้วย' — ROOT CAUSE: v7-5 source CSS included
override at end of <style> block:
.fx-marquee-track{animation:none}
.fx-faq-a::after{display:none}
.fx-hero::after{display:none}
These were 'no-op' overrides from the mockup library (which doesn't
actually animate things in showcase mode). Copied verbatim when I
extracted fx-system.css in Phase 1.1, killing marquee + 2 other
animations.
FIX: replaced with the real animations (marquee 40s, blink-cursor,
hero noise overlay). All 3 now actually run.
2. 'เราต้องการ light and dark mode ด้วย โดยมีปุ่มเปลี่ยน mode ได้' —
Implemented full light/dark theme system:
- Added [data-theme='dark'] block in fx-system.css overriding 11
CSS tokens (--ink, --paper, --line, --text-dim, + 5 new
--utility-bg/--nav-bg/--hero-content-bg/etc.)
- Refactored .fx-utility-bar to use --utility-bg/--fg vars instead
of hardcoded #0A0A0A (so it inverts correctly in dark mode)
- Refactored .fx-nav, .fx-hero-content, .fx-hero-side, .fx-faq-item
to use theme-aware vars
- Added 13 [data-theme='dark'] overrides for elements needing
extra contrast tweaks (pricing featured, callout, portfolio name,
process/service numbers, prose)
- Added smooth 0.3s transition on theme change (no jarring swap)
3. Theme toggle button (UtilityBar.astro):
- Replaced text-only indicator with <button id='fx-theme-toggle'>
- 3 modes cycle: auto (follow OS) → light → dark → auto
- Persists to localStorage 'moreminimore-theme'
- Default = 'auto' (follows system preference)
- Button label changes: '◐ auto' / '☀ light' / '☾ dark'
- Mode indicator shows user's chosen mode
- Listens to OS preference change live (when in 'auto' mode)
- ARIA label + title for accessibility
4. Anti-flash inline script in Base.astro <head>:
- Runs synchronously before first paint
- Reads localStorage → applies data-theme
- If 'auto' or unset, follows prefers-color-scheme
- Prevents white→dark flash on first load
Build: 22 pages, 0 errors, 2.11s.
CSS: 545/545 braces, 9 keyframes, 13 dark-mode selectors.
- UtilityBar.astro (v6-utility): phone, clock, date, email from site settings
Clock updated by fxClock() in src/lib/fx-animations.ts
- Marquee.astro (v6-marquee): log ticker with 4 entries (animated horizontally)
Content duplicated for seamless loop
- Navigation.astro (v6-nav): REPLACED legacy. Adds 'บริการ' dropdown
(4 services) + 'บทความ' link per plan round 2. Click-to-toggle on mobile.
- src/data/nav.ts: single source of truth for mainLinks + servicesDropdown
- fx-system.css: +27 lines for dropdown styles + active link underline
(v6-nav originally had no dropdown — we added per spec)
Refs: .hermes/plans/2026-06-13_124000-moreminimore-v7-5-migration.md Task 2.1-2.4
teal-soft: #ccfbf1 (pale teal-green) → #bae6fd (pale sky blue)
mint-soft: #d1fae5 (pale green) — unchanged
Now the two tiles are clearly different: one is green-mint, the other is blue-cyan
Before: .tile-link-overlay contained the .mega-cta text. Both overlay and .mega-objective were positioned at the bottom of the tile, causing visual overlap.
After: .mega-cta is a normal-flow <span> in tile-body (pushed to bottom via margin-top: auto). .tile-link-overlay is now an empty click target (no inner content, no padding, no flex).
The home service section had each bento-tile wrapped in an
<a href="/services/..."> tag. This caused two problems:
1. The <a> became the grid item instead of the .bento-tile,
so the .bento-tile's grid-column: span 3 was ignored.
The <a> defaulted to display: block and stretched to
100% width, so all 4 tiles in a row had the same wide
width — but the grid was no longer dividing them equally.
2. Astro's scoped CSS only applies to elements with the
matching data-astro-cid attribute. The <a> wrapper had
its own scope, and the .bento-grid > a selector wasn't
styled — so the grid layout didn't propagate correctly.
Fix: remove the <a> wrapper. Make the whole tile clickable
by adding an absolutely-positioned <a class="tile-link-overlay">
inside the tile (covers the entire tile, sits behind text via
z-index). The .bento-tile is now a direct child of .bento-grid
and grid-column: span 3 works as expected.
Result: 4 tiles width 3/12 each, exactly filling one row,
clickable from anywhere on the tile.
Co-Authored-By: Claude <noreply@anthropic.com>
Scoped CSS in BentoTile.astro was supposed to enforce
min-width: 0 + width: 100%, but the tiles were still
rendering at different widths in the same row.
Adding a global !important override in global.css that
applies to ALL .bento-tile instances regardless of
scoping, plus a flex column layout so tile-body fills
available space and pushes the CTA to the bottom.
This guarantees equal width + equal height in the row.
Co-Authored-By: Claude <noreply@anthropic.com>
--container-max was 1400px which left visible whitespace on
screens 1600px+ wide. Bump to 1600px so service/problem bento
tiles fill more of the viewport.
Co-Authored-By: Claude <noreply@anthropic.com>
Layout redesign:
- Add BentoGrid, BentoTile, DecoOrb components
- Add accent palette (purple/teal/mint/coral) to global tokens
- Rewrite about.astro using Bento Grid (12-col, surface variants)
- Decorative parallax blur orbs in 4 sections
- Value/process tiles use numerals 01-04 instead of emoji
Content updates per user feedback:
- Remove "Soloprenuer" emphasis
- Remove TOC ("เนื้อหาในหน้านี้") — not needed for short content
- Outsource + bot acknowledged as part of approach
- Replace AI stack with marketing intelligence tools
(ad spy, SEO gap, trend tracking)
- No fabricated stat numbers — placeholders show "—"
(only "5+ ปี" kept as verifiable, founded 2020)
- Post-delivery: small changes free, charge only for new features
- No Sprint methodology — flexible timeline, demo when ready
Co-Authored-By: Claude <noreply@anthropic.com>
- Add --font-display, --font-body, --font-mono CSS variables in :root
(they were referenced everywhere but never defined; Kanit wasn't loading)
- Remove Noto Sans Thai import (Kanit handles Latin + Thai natively)
- Fix hero/PageHero line-height: 1/1.1 → 1.3 to prevent Thai vowel clipping
(was caused by overflow:hidden on .word-wrapper combined with line-height:1)
- Replace .word-wrapper overflow:hidden with padding so Thai descenders
stay visible during kinetic-title animation
- Bump word translateY from 100% → 110% so word slides up cleanly
- Bump global h1-h6 line-height from 1.1 → 1.25
Build: 18 pages, 0 errors
- global.css: rewrite all CSS variables for light-first theme
- White bg, dark text, yellow accent (preserved)
- New --color-bg, --color-bg-soft, --color-bg-alt tokens
- All button variants audited: btn-primary (yellow/black, never matches
any white/yellow/soft bg), btn-dark (black/white, safe on yellow/light),
btn-outline-dark, btn-outline-light (only on dark), btn-outline-yellow
- Form inputs: white bg, dark text, gray border, yellow focus ring
- Nav: white bg, dark text, yellow hover underline
- Footer: white bg, dark text, social icons on soft bg
- Section variants: .section-soft, .section-yellow (utility classes)
- Removed dark variants: .section-dark, .btn-dark-as-section-bg
- Base.astro: theme-color = #fed400 (yellow)
- Hero.astro: kinetic hero on WHITE bg with yellow badge + dark text
- PageHero.astro: light hero with yellow accent line at bottom
- Navigation.astro: white bg, dark links, yellow CTA, white logo banner
with /images/logo-long-black.png (works on light/yellow)
- Footer.astro: white bg, dark text, social icons, yellow CTA
- Card components: white bg, gray border, yellow hover state
- Added gradient transitions between sections in global.css
- Portfolio section now has gradient-top (dark to white fade)
- Blog section now has gradient-bottom (white fade from dark)
- Reduced portfolio overlay opacity from 0.85 to 0.65
- Added border to blog cards for white-on-white visibility
- Blog cards now have primary color accent on hover