Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ node_modules
/app/assets/builds/*
!/app/assets/builds/.keep
node_modules/
yarn.lock
335 changes: 335 additions & 0 deletions App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,335 @@
#root {
max-width: 1280px;
margin: 0 auto;
padding: 0.5rem;
text-align: center;
}

.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #cc0000aa);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #336791aa);
}

@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}

/* Terminal and code styling */
.terminal-output::-webkit-scrollbar {
width: 4px;
}

.terminal-output::-webkit-scrollbar-track {
background: #1a1a1a;
}

.terminal-output::-webkit-scrollbar-thumb {
background: #444;
border-radius: 2px;
}

.ascii-art {
font-family: monospace;
white-space: pre;
font-size: 0.7rem;
line-height: 1;
}

/* Matrix animation - kept for reference but not used in new design */
.matrix-container {
display: none;
}

/* Analog noise overlay */
.noise-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.1'/%3E%3C/svg%3E");
pointer-events: none;
opacity: 0.06;
z-index: 10;
}

/* Audio waveform divider */
.waveform-divider {
height: 20px;
background: url("data:image/svg+xml,%3Csvg width='100%25' height='20' viewBox='0 0 1200 20' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 10 Q 25 5, 50 10 T 100 10 T 150 10 T 200 10 T 250 10 T 300 10 T 350 10 T 400 10 T 450 10 T 500 10 T 550 10 T 600 10 T 650 10 T 700 10 T 750 10 T 800 10 T 850 10 T 900 10 T 950 10 T 1000 10 T 1050 10 T 1100 10 T 1150 10 T 1200 10' stroke='%23555' fill='none' stroke-width='1'/%3E%3C/svg%3E");
margin: 1.5rem 0;
opacity: 0.5;
}

/* Ruby on Rails and Postgres inspired colors */
.rails-red {
color: #CC0000 !important;
}

.postgres-blue {
color: #336791 !important;
}

.card-rails {
border-color: rgba(204, 0, 0, 0.3) !important;
}

.card-postgres {
border-color: rgba(51, 103, 145, 0.3) !important;
}

/* Mechanical key styling */
.mech-key {
font-family: 'JetBrains Mono', monospace;
padding: 3px 8px;
background: #222;
border: 1px solid #444;
border-radius: 3px;
box-shadow: 0 2px 0 #111;
color: #eee;
display: inline-block;
margin: 0 2px;
}

/* Various animation styles */
/* Analog VU meter animation */
@keyframes vu-meter {
0% { width: 20%; }
20% { width: 60%; }
40% { width: 40%; }
60% { width: 80%; }
80% { width: 30%; }
100% { width: 50%; }
}

.vu-meter {
height: 4px;
background: linear-gradient(90deg, #39ff14, #f3d611, #f33611);
animation: vu-meter 4s ease-in-out infinite;
border-radius: 2px;
margin: 8px 0;
}

/* Loading bar animation */
@keyframes loading-bar {
0% { width: 0%; background-position: 0% 50%; }
50% { width: 100%; background-position: 100% 50%; }
100% { width: 0%; background-position: 0% 50%; }
}

.loading-bar {
height: 3px;
background: linear-gradient(90deg, #39ff14, #bc13fe, #336791, #CC0000);
background-size: 300% 300%;
animation: loading-bar 8s ease infinite;
border-radius: 2px;
margin: 8px 0;
}

/* Sine wave animation */
@keyframes sine-wave {
0% {
clip-path: path('M0,10 Q5,5 10,10 T20,10 T30,10 T40,10 T50,10 T60,10 T70,10 T80,10 T90,10 T100,10');
}
25% {
clip-path: path('M0,10 Q5,15 10,10 T20,10 T30,10 T40,10 T50,10 T60,10 T70,10 T80,10 T90,10 T100,10');
}
50% {
clip-path: path('M0,10 Q5,10 10,5 T20,10 T30,5 T40,10 T50,15 T60,10 T70,5 T80,10 T90,15 T100,10');
}
75% {
clip-path: path('M0,10 Q5,5 10,15 T20,5 T30,15 T40,5 T50,15 T60,5 T70,15 T80,5 T90,15 T100,10');
}
100% {
clip-path: path('M0,10 Q5,5 10,10 T20,10 T30,10 T40,10 T50,10 T60,10 T70,10 T80,10 T90,10 T100,10');
}
}

.sine-wave {
background: linear-gradient(90deg, #39ff14, #cc0000);
animation: sine-wave 4s ease-in-out infinite;
border-radius: 2px;
margin: 8px 0;
}

/* Pulse dot animation */
@keyframes pulse-dot {
0% { transform: scale(0.8); opacity: 0.5; }
50% { transform: scale(1.2); opacity: 1; }
100% { transform: scale(0.8); opacity: 0.5; }
}

.pulse-dot {
width: 6px;
height: 6px;
background: #39ff14;
border-radius: 50%;
margin: 8px auto;
animation: pulse-dot 2s ease-in-out infinite;
}

/* Glitchy text effect */
@keyframes glitch-text {
0% { text-shadow: -1px -1px 0 rgba(255,0,0,0.3), 1px 1px 0 rgba(0,255,255,0.3); }
25% { text-shadow: 1px -1px 0 rgba(255,0,0,0.3), -1px 1px 0 rgba(0,255,255,0.3); }
50% { text-shadow: -1px 1px 0 rgba(255,0,0,0.3), 1px -1px 0 rgba(0,255,255,0.3); }
75% { text-shadow: 1px 1px 0 rgba(255,0,0,0.3), -1px -1px 0 rgba(0,255,255,0.3); }
100% { text-shadow: -1px -1px 0 rgba(255,0,0,0.3), 1px 1px 0 rgba(0,255,255,0.3); }
}

.text-glitch:hover {
animation: glitch-text 0.3s ease-in-out infinite;
}

/* Server status pulse animation */
@keyframes server-pulse {
0%, 100% { opacity: 1; box-shadow: 0 0 5px currentColor; }
50% { opacity: 0.6; box-shadow: 0 0 10px currentColor; }
}

/* Server status indicators */
.server-status {
width: 8px;
height: 8px;
border-radius: 50%;
display: inline-block;
margin-right: 6px;
animation: server-pulse 2s ease-in-out infinite;
}

.server-online {
background-color: #0f9d58;
}

.server-issue {
background-color: #f4b400;
}

.server-offline {
background-color: #db4437;
}

/* Terminal status indicators that match Tailwind classes */
.status-indicator {
width: 8px;
height: 8px;
border-radius: 50%;
display: inline-block;
margin-right: 6px;
animation: server-pulse 2s ease-in-out infinite;
}

/* Terminal window macOS style */
.terminal-header {
height: 24px;
background-color: #2a2a2a;
border-bottom: 1px solid #444;
border-top-left-radius: 6px;
border-top-right-radius: 6px;
display: flex;
align-items: center;
padding: 0 8px;
}

.terminal-dot {
width: 12px;
height: 12px;
border-radius: 50%;
margin-right: 6px;
}

.terminal-dot-red {
background-color: #ff5f56;
}

.terminal-dot-yellow {
background-color: #ffbd2e;
}

.terminal-dot-green {
background-color: #27c93f;
}

.terminal-title {
color: #aaa;
font-size: 12px;
margin-left: 4px;
font-family: 'JetBrains Mono', monospace;
}

/* MacOS window styling for bento boxes */
.macos-window {
border-radius: 6px;
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.3);
overflow: hidden;
backdrop-filter: blur(8px);
}

.macos-header {
height: 26px;
background: linear-gradient(to bottom, #3a3a3a, #2a2a2a);
border-bottom: 1px solid #444;
display: flex;
align-items: center;
padding: 0 10px;
}

.macos-buttons {
display: flex;
gap: 6px;
}

.macos-button {
width: 12px;
height: 12px;
border-radius: 50%;
}

.macos-button-close {
background-color: #ff5f56;
border: 1px solid #e0443e;
}

.macos-button-minimize {
background-color: #ffbd2e;
border: 1px solid #dea123;
}

.macos-button-expand {
background-color: #27c93f;
border: 1px solid #1aab29;
}

.macos-content {
padding: 10px;
background-color: rgba(30, 30, 30, 0.8);
}

/* Blink animation (caret) */
@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}

.animate-blink {
animation: blink 1s step-end infinite;
}
50 changes: 50 additions & 0 deletions App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from "react";
import "./App.css";
import "./index.css";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Navigation from "./components/Navigation";
import Index from "./pages/Index";
import Blog from "./pages/Blog";
import Work from "./pages/Work";
import Contact from "./pages/Contact";
import Fun from "./pages/Fun";
import Games from "./pages/Games";
import NotFound from "./pages/NotFound";

// Background texture overlay
const BackgroundTexture = () => (
<div className="fixed inset-0 z-[-1] pointer-events-none">
<div className="absolute inset-0 bg-terminal-black"></div>
<div className="absolute inset-0 noise-overlay opacity-15"></div>
<div className="absolute inset-0" style={{
backgroundImage: `
radial-gradient(rgba(75, 0, 130, 0.075) 1px, transparent 0),
radial-gradient(rgba(75, 0, 130, 0.075) 1px, transparent 0)
`,
backgroundSize: '30px 30px',
backgroundPosition: '0 0, 15px 15px'
}}></div>
<div className="absolute inset-0 bg-matrix-pattern bg-[30px_30px]"></div>
</div>
);

// App component with cleaner design
const App = () => (
<React.Fragment>
<BrowserRouter basename="/new">
<BackgroundTexture />
<Navigation />
<Routes>
<Route path="/" element={<Index />} />
<Route path="blog" element={<Blog />} />
<Route path="work" element={<Work />} />
<Route path="contact" element={<Contact />} />
<Route path="fun" element={<Fun />} />
<Route path="games" element={<Games />} />
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
</React.Fragment>
);

export default App;
2 changes: 1 addition & 1 deletion Procfile.dev
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
web: bin/rails server
css: bin/rails tailwindcss:watch
vite: npm run dev
Loading
Loading