- Add SF Symbol icons to nav links (book for Docs, </> for GitHub)
- Fix theme button onClick broken by hydration mismatch: start with
null on both server and client, sync via useEffect after mount
- Active theme dot pulses with 3s ease-in-out glow animation
- Stronger glow on active theme indicator (triple-layer box-shadow)
- COLS truncation now counts visible characters only (ignores HTML tags),
preventing broken markup when tags get cut off mid-pair
- typeSystem() types content between paired tags char-by-char while tags
appear instantly as complete open/close pairs
- Empty lines render with non-breaking space for correct row height,
fixing premature scrolling when blank lines consumed ROWS budget
- Stable line keys (monotonic counter) prevent React DOM thrashing
- terminal-parser bold regex uses negative lookahead to skip ***
Parser now supports basic Markdown syntax in all text fields:
- **bold** → <strong> with bold font weight
- __underline__ → <span> with underline decoration
- ~~strikethrough~~ → <span> with line-through
- *italic* → <em> with italic style
Implementation:
- Regex-based parser converts Markdown to HTML-like tags
- TerminalScreen component parses tags and renders as React nodes
- Styling via Tailwind classes (font-bold, underline, etc.)
- Works in all sequences: Boot, School, Joshua, UNIX commands
Examples added to terminal-script.md:
- **BIOS** in boot sequence
- __AUTHORIZED USE ONLY__ message
Build-time processing ensures no runtime overhead.
- Add preload links for all 5 audio files in layout head
- Browser downloads sounds during page load
- Eliminates delay when power button is clicked
- Improves user experience with immediate sound response
Files preloaded:
- power-on.mp3 (beep)
- hard-drive-boot.m4a
- hard-drive-spin.m4a
- hard-drive-seek1.m4a
- hard-drive-power-off.m4a
Lint Fixes:
- Fix setState in useEffect warnings by using lazy initialization and useLayoutEffect
- Remove unused parameters and variables (patterns, zoomed)
- Add eslint-disable comments for legitimate patterns (hydration, cleanup)
- Fix ref mutation warnings in cleanup functions
Code Optimizations:
- Remove dead Patterns interface and regex objects from CodePreview
- Simplify tokenizeLine to use combined regex directly
- Use lazy state initialization in ThemeProvider to avoid SSR mismatch
- Split audio preload and mount state into separate effects
- Use useLayoutEffect for synchronous DOM updates (terminalOpacity reset)
- Improve cleanup by copying ref values before use
- Add proper cancelAnimationFrame cleanup for fade animation
Result: ✓ All lint errors fixed, production build successful
- Remove 'as const' from generated terminal-data.ts
- Add type assertion for INTERACTIONS array to fix TypeScript error
- Fixes production build failure with readonly type mismatch
- Create terminal-parser.ts to parse terminal-script.md
- Add build script (generate-terminal-data.ts) to convert markdown to TypeScript
- Refactor TerminalScreen.tsx to use generated data instead of hardcoded arrays
- Add prebuild script to package.json for automatic data generation
- Install tsx and @types/howler dev dependencies
- Fix parser to preserve spacing in COUNTER prefix (Memory Test: )
- Update terminal-script.md documentation with [INLINE] tag explanation
Now terminal content can be edited in markdown without touching TypeScript:
1. Edit terminal-script.md
2. Run: npx tsx scripts/generate-terminal-data.ts
3. Reload browser - changes are live
Adds realistic CRT monitor scanline sweep effect to terminal:
**Visual Effect:**
- Sharp bottom edge (cathode ray current position)
- Trailing phosphor glow upward (150px trail)
- Gradient: transparent → 0.02 → 0.04 → 0.08 → 0.1
- Sharp edge: 0.08 opacity, no blur
- Trail: blur(3px) for smooth phosphor decay
**Animation:**
- 15s linear infinite
- Moves from top to bottom within terminal area only
- Minimal pause between cycles
- Only active when terminal is powered on
**Implementation:**
- Container (150px) with gradient + sharp 2px bottom edge
- Uses transform: translateY() for smooth animation
- CSS @keyframes crt-scanline-move
- Positioned within CRT glow layer (z-index 3)
Inspired by real CRT electron beam behavior where the
cathode ray sweeps the screen with phosphor persistence
trailing behind.
- Increased scanline height from 3px to 8px
- Set animation directly in style instead of via Tailwind class
to ensure 30s duration is applied correctly
The old 'background-position' animation was still present and
overriding the new slower 'translateY' version. Now only the
30s animation remains active.
- Removed AudioContext setup and management
- Removed playCrtPowerOnSound() function (95 lines)
- Removed audio unlock listeners
- Cleaned up handlePowerOn comment
Audio caused issues with browser autoplay policies and added
unnecessary complexity. Terminal animation works fine without it.
- Make playCrtPowerOnSound() async with proper AudioContext.resume()
- Add AudioContext unlock on first user interaction (click/touchstart)
- Add error handling for audio failures
- Ensures sound works in all browsers with autoplay restrictions
- Remove SN Pro Google Font import from globals.css
- Add Nunito font import with weights 400, 500, 600, 700
- Update CSS variables to use --font-nunito
- Apply Nunito as primary font family for body text
- Keep Geist Mono for monospace elements
- Add robots.txt and sitemap.xml (static files for export mode)
- Add OG image (1200x630) with terminal icon + branding
- Add Twitter Card meta tags (summary_large_image)
- Add canonical URL via metadataBase
- Add JSON-LD structured data (SoftwareSourceCode schema)
- Add <main> landmark and skip-navigation link for accessibility
- Add preconnect hints for Google Fonts, Google Static, and Umami
- Add web app manifest (site.webmanifest)
- Add meta keywords for secondary search engines
- Add aria-hidden on decorative SF Symbol icons
- Powered-off terminal shows no text (realistic CRT behavior)
- Add permanent glass sheen with diagonal specular highlight in theme color
- Glass overlay covers full screen area with vignette effect
- Reduce Palette protocol from 18 to 13 essential properties
- Add BlockPalette protocol with surfaceBackground, surfaceHeaderBackground, elevatedBackground
- BlockPalette defaults compute via lighter(by:) from background
- Add Color.rgbComponents for universal ANSI/256/RGB conversion
- Make lighter(by:), darker(by:), opacity() work on all color types
- Migrate views to use BlockPalette accessors
- Remove NCursesPalette (to be reworked later)
- Update all 6 palette structs to BlockPalette conformance
- Update DocC articles, topic index, and palette-preview.html
- All 492 tests in 83 suites passing
- Move media queries after base styles (fixes 2-column on mobile)
- Fix hue bar losing gradient in vertical layout (flex: none + width: 100%)
- Add statusBarBackground to Backgrounds swatch group
- Add foregroundPlaceholder to all palettes and Foregrounds group
- Remove deleted properties from palette data and swatchGroups
- Update existing palettes with correct SDK values including Violet HSL hex
Remove borderFocused, separator, selection, selectionBackground, disabled,
statusBarForeground, statusBarHighlight from Palette protocol and all
consumers. Views now use palette essentials directly (e.g. palette.accent
instead of palette.borderFocused, palette.foregroundTertiary instead of
palette.disabled). Update tests and DocC articles accordingly.
Remove explicit borderFocused, selection, selectionBackground,
statusBarForeground, statusBarHighlight from all palette implementations.
These remain as default-derived properties on the protocol extension.
Add foregroundPlaceholder as 4th foreground level for input field
placeholder text, dimmer than foregroundTertiary.
Fix SwiftLint force_try violations in luminance tests.