diff --git a/about.html b/about.html index 36e1722..235f5b5 100644 --- a/about.html +++ b/about.html @@ -1,12 +1,12 @@ - + About — Ertunç Özbay - + @@ -21,21 +21,29 @@ - +
+
+ + + +
- + + + +
@@ -145,7 +153,7 @@ - + diff --git a/assets/css/style.css b/assets/css/style.css index ce46f7c..7cc3836 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -1,99 +1,153 @@ /* ========================================================================== - Ertunç Özbay — Personal Workshop, Project Lab & Technical Notebook - Vibrant Luminous Engineering Studio + Daylight Theme Support - Plain CSS • Accessible • Responsive • Reduced-Motion Ready + Ertunç Özbay — Engineering Studio, Hardware Lab & Open-Source Hub + Multi-Theme System: + 1. 🎨 Colorful Studio (DEFAULT — Bright, Vibrant, Multi-Color Engineering UI) + 2. 🌈 Cyber Neon (Rich Indigo/Violet Synthwave Night Theme) + 3. 📐 Blueprint Lab (Crisp Technical Paper & Cobalt Schematic Theme) + Plain CSS • Accessible • Responsive • Copyable Code & Command Blocks ========================================================================== */ -:root { - /* Luminous Indigo-Slate Canvas (Brighter, Richer, Colorful) */ - --bg-primary: #111827; - --bg-secondary: #182235; - --bg-card: #1e293b; - --bg-card-hover: #243248; - --bg-code: #0f172a; - --bg-header: rgba(17, 24, 39, 0.88); - - /* Crisp Borders & Hairlines */ - --border-subtle: #334155; - --border-strong: #475569; - --border-accent: #f59e0b; - - /* High-Contrast Typography */ - --text-primary: #f8fafc; - --text-secondary: #cbd5e1; - --text-muted: #94a3b8; - - /* Multi-Color Engineering Accents */ - --accent-amber: #f59e0b; - --accent-amber-soft: rgba(245, 158, 11, 0.16); - --accent-teal: #06b6d4; - --accent-teal-soft: rgba(6, 182, 212, 0.16); - --accent-emerald: #10b981; - --accent-emerald-soft: rgba(16, 185, 129, 0.16); - --accent-magenta: #ec4899; - --accent-magenta-soft: rgba(236, 72, 153, 0.16); - --accent-violet: #8b5cf6; - --accent-violet-soft: rgba(139, 92, 246, 0.16); - --accent-coral: #f43f5e; - --accent-coral-soft: rgba(244, 63, 94, 0.16); - --accent-blue: #38bdf8; - --accent-youtube: #ff0033; - - /* Gradients */ - --grad-hero: linear-gradient(135deg, rgba(30, 41, 59, 0.96) 0%, rgba(24, 34, 53, 0.96) 55%, rgba(36, 28, 62, 0.92) 100%); - --grad-brand: linear-gradient(135deg, #f59e0b 0%, #ec4899 55%, #06b6d4 100%); - --grad-amber: linear-gradient(90deg, #f59e0b, #f97316); - --grad-synth: linear-gradient(90deg, #ec4899, #8b5cf6, #06b6d4); - --grad-emerald: linear-gradient(90deg, #10b981, #06b6d4); - --grad-coral: linear-gradient(90deg, #f43f5e, #fb923c); - - /* Typography & Rhythm */ - --font-sans: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; - --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; - - --max-width: 1100px; - --max-reading-width: 74ch; - --radius-sm: 8px; - --radius-md: 14px; - --radius-lg: 18px; - --shadow-panel: 0 12px 32px rgba(2, 6, 23, 0.42); - --shadow-card: 0 8px 24px rgba(2, 6, 23, 0.28); -} - -/* Optional Sunlit Studio Light Mode */ -[data-theme="light"] { - --bg-primary: #f8fafc; - --bg-secondary: #f1f5f9; +:root, +[data-theme="colorful"] { + /* 1. DEFAULT: Vibrant Colorful Studio (Bright, Energetic, Non-Dark!) */ + --bg-primary: #f3f6fc; + --bg-secondary: #eaf0fa; --bg-card: #ffffff; - --bg-card-hover: #f8fafc; + --bg-card-hover: #f8faff; --bg-code: #0f172a; - --bg-header: rgba(255, 255, 255, 0.90); + --bg-header: rgba(255, 255, 255, 0.92); - --border-subtle: #e2e8f0; - --border-strong: #cbd5e1; - --border-accent: #d97706; + /* Crisp Structural Borders */ + --border-subtle: #d8e2f0; + --border-strong: #b8c7de; + --border-accent: #6366f1; + /* High-Contrast Typography on Bright Canvas */ --text-primary: #0f172a; --text-secondary: #334155; - --text-muted: #64748b; + --text-muted: #5b6b82; - --accent-amber: #d97706; - --accent-amber-soft: rgba(217, 119, 6, 0.12); - --accent-teal: #0891b2; - --accent-teal-soft: rgba(8, 145, 178, 0.12); + /* Vivid Multi-Color Accents */ + --accent-amber: #ea580c; + --accent-amber-soft: rgba(234, 88, 12, 0.12); + --accent-teal: #0284c7; + --accent-teal-soft: rgba(2, 132, 199, 0.12); --accent-emerald: #059669; --accent-emerald-soft: rgba(5, 150, 105, 0.12); --accent-magenta: #db2777; --accent-magenta-soft: rgba(219, 39, 119, 0.12); - --accent-violet: #7c3aed; - --accent-violet-soft: rgba(124, 58, 237, 0.12); + --accent-violet: #6d28d9; + --accent-violet-soft: rgba(109, 40, 217, 0.12); --accent-coral: #e11d48; --accent-coral-soft: rgba(225, 29, 72, 0.12); - --accent-blue: #0284c7; + --accent-blue: #2563eb; - --grad-hero: linear-gradient(135deg, #ffffff 0%, #f0f9ff 50%, #fdf4ff 100%); - --shadow-panel: 0 12px 32px rgba(15, 23, 42, 0.08); - --shadow-card: 0 6px 20px rgba(15, 23, 42, 0.06); + /* Colorful Studio Gradients */ + --grad-hero: linear-gradient(135deg, #ffffff 0%, #eef2ff 45%, #fdf2f8 78%, #fff7ed 100%); + --grad-brand: linear-gradient(135deg, #ff512f 0%, #dd2476 50%, #4f46e5 100%); + --grad-title: linear-gradient(90deg, #0f172a 0%, #4f46e5 38%, #db2777 72%, #ea580c 100%); + --body-bg-image: + radial-gradient(circle at 8% 12%, rgba(56, 189, 248, 0.22), transparent 36%), + radial-gradient(circle at 92% 10%, rgba(244, 114, 182, 0.22), transparent 36%), + radial-gradient(circle at 85% 85%, rgba(251, 146, 60, 0.18), transparent 38%), + radial-gradient(circle at 15% 88%, rgba(52, 211, 153, 0.18), transparent 38%), + radial-gradient(rgba(99, 102, 241, 0.10) 1px, transparent 1px); + + --shadow-panel: 0 14px 36px rgba(30, 41, 59, 0.09); + --shadow-card: 0 8px 24px rgba(30, 41, 59, 0.07); + + /* Typography & Layout Tokens */ + --font-sans: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; + --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; + --max-width: 1140px; + --max-reading-width: 75ch; + --radius-sm: 8px; + --radius-md: 14px; + --radius-lg: 20px; +} + +/* 2. 🌈 Cyber Neon Theme (Rich Violet-Indigo Synthwave — Never Flat Gray!) */ +[data-theme="neon"] { + --bg-primary: #131129; + --bg-secondary: #1b1738; + --bg-card: #221d46; + --bg-card-hover: #2b2458; + --bg-code: #0b091b; + --bg-header: rgba(19, 17, 41, 0.90); + + --border-subtle: #38306b; + --border-strong: #524699; + --border-accent: #f472b6; + + --text-primary: #f8fafc; + --text-secondary: #dcd7fe; + --text-muted: #a59de6; + + --accent-amber: #fbbf24; + --accent-amber-soft: rgba(251, 191, 36, 0.18); + --accent-teal: #22d3ee; + --accent-teal-soft: rgba(34, 211, 238, 0.18); + --accent-emerald: #34d399; + --accent-emerald-soft: rgba(52, 211, 153, 0.18); + --accent-magenta: #f472b6; + --accent-magenta-soft: rgba(244, 114, 182, 0.18); + --accent-violet: #c084fc; + --accent-violet-soft: rgba(192, 132, 252, 0.18); + --accent-coral: #fb7185; + --accent-coral-soft: rgba(251, 113, 133, 0.18); + --accent-blue: #60a5fa; + + --grad-hero: linear-gradient(135deg, rgba(40, 31, 84, 0.96) 0%, rgba(59, 25, 84, 0.94) 55%, rgba(22, 46, 79, 0.94) 100%); + --grad-title: linear-gradient(90deg, #ffffff 0%, #22d3ee 35%, #f472b6 70%, #fbbf24 100%); + --body-bg-image: + radial-gradient(circle at 12% 12%, rgba(236, 72, 153, 0.24), transparent 36%), + radial-gradient(circle at 88% 15%, rgba(6, 182, 212, 0.22), transparent 36%), + radial-gradient(circle at 50% 85%, rgba(139, 92, 246, 0.22), transparent 42%), + radial-gradient(rgba(192, 132, 252, 0.12) 1px, transparent 1px); + + --shadow-panel: 0 16px 40px rgba(5, 3, 20, 0.55); + --shadow-card: 0 10px 28px rgba(5, 3, 20, 0.42); +} + +/* 3. 📐 Blueprint Lab Theme (Warm Technical Paper & Cobalt Schematic) */ +[data-theme="blueprint"] { + --bg-primary: #fdfbf7; + --bg-secondary: #f3efe6; + --bg-card: #ffffff; + --bg-card-hover: #f7f4ec; + --bg-code: #172554; + --bg-header: rgba(253, 251, 247, 0.94); + + --border-subtle: #d6d0c2; + --border-strong: #aca391; + --border-accent: #1d4ed8; + + --text-primary: #172554; + --text-secondary: #334155; + --text-muted: #64748b; + + --accent-amber: #d97706; + --accent-amber-soft: rgba(217, 119, 6, 0.14); + --accent-teal: #1d4ed8; + --accent-teal-soft: rgba(29, 78, 216, 0.12); + --accent-emerald: #047857; + --accent-emerald-soft: rgba(4, 120, 87, 0.12); + --accent-magenta: #be185d; + --accent-magenta-soft: rgba(190, 24, 93, 0.12); + --accent-violet: #4338ca; + --accent-violet-soft: rgba(67, 56, 202, 0.12); + --accent-coral: #b91c1c; + --accent-coral-soft: rgba(185, 28, 28, 0.12); + --accent-blue: #1d4ed8; + + --grad-hero: linear-gradient(135deg, #ffffff 0%, #eff6ff 55%, #fef3c7 100%); + --grad-title: linear-gradient(90deg, #172554 0%, #1d4ed8 50%, #d97706 100%); + --body-bg-image: + linear-gradient(rgba(29, 78, 216, 0.05) 1px, transparent 1px), + linear-gradient(90deg, rgba(29, 78, 216, 0.05) 1px, transparent 1px); + + --shadow-panel: 0 10px 28px rgba(23, 37, 84, 0.08); + --shadow-card: 0 6px 18px rgba(23, 37, 84, 0.06); } /* Base Reset */ @@ -115,17 +169,18 @@ body { font-family: var(--font-sans); line-height: 1.68; background-color: var(--bg-primary); - background-image: - radial-gradient(circle at 12% 10%, rgba(6, 182, 212, 0.14), transparent 34%), - radial-gradient(circle at 88% 14%, rgba(236, 72, 153, 0.13), transparent 34%), - radial-gradient(circle at 50% 85%, rgba(245, 158, 11, 0.10), transparent 40%), - radial-gradient(rgba(148, 163, 184, 0.08) 1px, transparent 1px); - background-size: 100% 100%, 100% 100%, 100% 100%, 28px 28px; + background-image: var(--body-bg-image); + background-size: 100% 100%, 100% 100%, 100% 100%, 100% 100%, 26px 26px; background-attachment: fixed; color: var(--text-primary); min-height: 100vh; display: flex; flex-direction: column; + transition: background-color 0.2s ease, color 0.2s ease; +} + +[data-theme="blueprint"] body { + background-size: 24px 24px, 24px 24px; } /* Accessibility: Skip Link */ @@ -134,8 +189,8 @@ body { top: -100px; left: 1rem; z-index: 1000; - background: var(--grad-amber); - color: #0f172a; + background: var(--grad-brand); + color: #ffffff; padding: 0.65rem 1.1rem; font-weight: 700; border-radius: var(--radius-sm); @@ -145,11 +200,11 @@ body { .skip-link:focus { top: 1rem; - outline: 3px solid #ffffff; + outline: 3px solid var(--accent-teal); outline-offset: 2px; } -/* Accessibility: Visible Keyboard Focus States */ +/* Focus States */ a:focus-visible, button:focus-visible, input:focus-visible, @@ -177,7 +232,7 @@ h1 { } .gradient-title { - background: linear-gradient(90deg, var(--text-primary) 0%, #38bdf8 48%, #f59e0b 100%); + background: var(--grad-title); -webkit-background-clip: text; background-clip: text; color: transparent; @@ -213,42 +268,105 @@ li { strong { color: var(--text-primary); - font-weight: 650; + font-weight: 700; } code, pre { font-family: var(--font-mono); - font-size: 0.9em; + font-size: 0.89em; } code { - background-color: rgba(15, 23, 42, 0.75); - color: #38bdf8; - padding: 0.16rem 0.45rem; + background-color: var(--accent-teal-soft); + color: var(--accent-teal); + padding: 0.15rem 0.45rem; border-radius: 5px; - border: 1px solid var(--border-subtle); -} - -[data-theme="light"] code { - background-color: #f1f5f9; - color: #0369a1; + border: 1px solid rgba(2, 132, 199, 0.22); + font-weight: 600; } pre { background-color: var(--bg-code); color: #f8fafc; - padding: 1.1rem 1.25rem; - border-radius: var(--radius-sm); + padding: 1.15rem 1.25rem; + border-radius: 0 0 var(--radius-sm) var(--radius-sm); border: 1px solid var(--border-subtle); overflow-x: auto; line-height: 1.55; + margin: 0; } pre code { background: none; border: none; padding: 0; - color: inherit; + color: #e2e8f0; + font-weight: 400; +} + +/* Interactive Code & Terminal Window Component */ +.code-window { + margin: 1.15rem 0 1.65rem; + border-radius: var(--radius-sm); + overflow: hidden; + box-shadow: var(--shadow-card); + border: 1px solid var(--border-strong); +} + +.code-window-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.75rem; + background: linear-gradient(90deg, #1e293b 0%, #0f172a 100%); + color: #f8fafc; + padding: 0.55rem 1rem; + font-family: var(--font-mono); + font-size: 0.78rem; + border-bottom: 1px solid rgba(255, 255, 255, 0.12); +} + +.code-window-title { + display: inline-flex; + align-items: center; + gap: 0.5rem; + font-weight: 700; + color: #38bdf8; +} + +.code-dots { + display: inline-flex; + gap: 0.35rem; +} + +.code-dot { + width: 10px; + height: 10px; + border-radius: 50%; + display: inline-block; +} + +.code-dot.red { background: #fb7185; } +.code-dot.amber { background: #fbbf24; } +.code-dot.green { background: #34d399; } + +.copy-code-btn { + background: rgba(255, 255, 255, 0.1); + color: #f8fafc; + border: 1px solid rgba(255, 255, 255, 0.22); + border-radius: 6px; + padding: 0.25rem 0.65rem; + font-family: var(--font-mono); + font-size: 0.74rem; + font-weight: 700; + cursor: pointer; + transition: all 0.15s ease; +} + +.copy-code-btn:hover { + background: #38bdf8; + color: #0f172a; + border-color: #38bdf8; } a { @@ -259,7 +377,7 @@ a { } a:hover { - color: var(--accent-amber); + color: var(--accent-magenta); } img { @@ -282,10 +400,10 @@ img { main { flex: 1; - padding: 2.5rem 0 4.5rem; + padding: 2.35rem 0 4.5rem; } -/* Header & Navigation */ +/* Header, Navigation & Always-Visible Theme Switcher */ .site-header { background-color: var(--bg-header); border-bottom: 1px solid var(--border-subtle); @@ -293,22 +411,26 @@ main { top: 0; z-index: 100; backdrop-filter: blur(14px); + box-shadow: 0 4px 16px rgba(15, 23, 42, 0.05); } .site-header::before { content: ""; display: block; - height: 3px; + height: 4px; width: 100%; - background: linear-gradient(90deg, #06b6d4 0%, #8b5cf6 35%, #ec4899 68%, #f59e0b 100%); + background: linear-gradient(90deg, #06b6d4 0%, #6366f1 28%, #ec4899 58%, #f59e0b 82%, #10b981 100%); } .header-inner { display: flex; align-items: center; justify-content: space-between; - min-height: 4.4rem; - gap: 1rem; + min-height: 4.5rem; + gap: 0.85rem; + flex-wrap: wrap; + padding-top: 0.4rem; + padding-bottom: 0.4rem; } .site-brand { @@ -329,30 +451,75 @@ main { display: inline-flex; align-items: center; justify-content: center; - width: 2.25rem; - height: 2.25rem; + width: 2.35rem; + height: 2.35rem; background: var(--grad-brand); border-radius: var(--radius-sm); font-family: var(--font-mono); - font-size: 0.88rem; + font-size: 0.9rem; font-weight: 800; color: #ffffff; - box-shadow: 0 4px 12px rgba(236, 72, 153, 0.3); + box-shadow: 0 4px 12px rgba(221, 36, 118, 0.35); } .brand-subtitle { display: block; font-family: var(--font-mono); font-size: 0.72rem; - font-weight: 500; - color: var(--accent-teal); + font-weight: 600; + color: var(--accent-magenta); } -/* Mobile Navigation Button & Theme Button */ -.nav-toggle, -.theme-toggle { +/* Header Controls Wrapper (Nav + Prominent Theme Switcher) */ +.header-controls { + display: flex; + align-items: center; + gap: 0.75rem; + flex-wrap: wrap; +} + +/* Prominent Multi-Theme Switcher Pill Bar */ +.theme-switcher { display: inline-flex; align-items: center; + gap: 0.25rem; + background-color: var(--bg-secondary); + border: 1px solid var(--border-strong); + padding: 0.22rem; + border-radius: 999px; + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.06); +} + +.theme-btn { + display: inline-flex; + align-items: center; + gap: 0.3rem; + border: none; + background: transparent; + color: var(--text-secondary); + font-family: var(--font-mono); + font-size: 0.75rem; + font-weight: 700; + padding: 0.32rem 0.68rem; + border-radius: 999px; + cursor: pointer; + transition: all 0.15s ease; +} + +.theme-btn:hover { + color: var(--text-primary); +} + +.theme-btn[aria-pressed="true"] { + background: var(--grad-brand); + color: #ffffff; + box-shadow: 0 2px 8px rgba(221, 36, 118, 0.35); +} + +/* Mobile Navigation Button */ +.nav-toggle { + display: none; + align-items: center; gap: 0.4rem; background-color: var(--bg-card); color: var(--text-primary); @@ -361,26 +528,14 @@ main { padding: 0.45rem 0.75rem; font-family: var(--font-mono); font-size: 0.8rem; - font-weight: 600; + font-weight: 700; cursor: pointer; - transition: all 0.15s ease; -} - -.nav-toggle { - display: none; -} - -.nav-toggle:hover, -.theme-toggle:hover { - border-color: var(--accent-teal); - color: var(--accent-teal); - transform: translateY(-1px); } .nav-list { display: flex; align-items: center; - gap: 0.35rem; + gap: 0.3rem; list-style: none; margin: 0; padding: 0; @@ -392,11 +547,11 @@ main { .nav-link { display: inline-block; - padding: 0.45rem 0.85rem; + padding: 0.42rem 0.8rem; color: var(--text-secondary); text-decoration: none; - font-size: 0.95rem; - font-weight: 600; + font-size: 0.94rem; + font-weight: 650; border-radius: var(--radius-sm); border: 1px solid transparent; transition: all 0.15s ease; @@ -404,18 +559,21 @@ main { .nav-link:hover { color: var(--text-primary); - background-color: var(--bg-card); + background-color: var(--bg-secondary); border-color: var(--border-subtle); } .nav-link[aria-current="page"] { - color: #ffffff; - background: linear-gradient(135deg, rgba(6, 182, 212, 0.28), rgba(139, 92, 246, 0.28)); - border-color: rgba(6, 182, 212, 0.55); + color: var(--accent-violet); + background-color: var(--accent-violet-soft); + border-color: rgba(109, 40, 217, 0.35); + font-weight: 750; } -[data-theme="light"] .nav-link[aria-current="page"] { - color: #0f172a; +[data-theme="neon"] .nav-link[aria-current="page"] { + color: #ffffff; + background: linear-gradient(135deg, rgba(6, 182, 212, 0.32), rgba(236, 72, 153, 0.32)); + border-color: rgba(34, 211, 238, 0.6); } /* Workshop Hero / Intro Panel */ @@ -423,7 +581,7 @@ main { position: relative; background: var(--grad-hero); border: 1px solid var(--border-strong); - border-left: 5px solid var(--accent-teal); + border-left: 6px solid var(--accent-magenta); border-radius: var(--radius-lg); padding: clamp(1.65rem, 3.8vw, 2.75rem); margin-bottom: 2.75rem; @@ -431,53 +589,33 @@ main { overflow: hidden; } -.workshop-hero::after { - content: ""; - position: absolute; - top: -60px; - right: -60px; - width: 240px; - height: 240px; - background: radial-gradient(circle, rgba(6, 182, 212, 0.18) 0%, rgba(236, 72, 153, 0.10) 50%, transparent 70%); - pointer-events: none; -} - .workshop-eyebrow { display: inline-flex; align-items: center; gap: 0.5rem; font-family: var(--font-mono); - font-size: 0.8rem; - font-weight: 700; - color: var(--accent-teal); - background-color: var(--accent-teal-soft); - border: 1px solid rgba(6, 182, 212, 0.45); - padding: 0.28rem 0.75rem; + font-size: 0.78rem; + font-weight: 800; + color: #ffffff; + background: linear-gradient(90deg, #4f46e5 0%, #db2777 100%); + padding: 0.3rem 0.85rem; border-radius: 999px; margin-bottom: 1rem; + box-shadow: 0 4px 12px rgba(79, 70, 229, 0.25); } .hero-lead { font-size: clamp(1.12rem, 2.1vw, 1.32rem); color: var(--text-primary); - max-width: 66ch; + max-width: 68ch; margin-bottom: 1rem; - font-weight: 500; -} - -.hero-supporting-line { - font-family: var(--font-mono); - font-size: 0.92rem; - color: var(--accent-amber); - margin-top: 1.1rem; - margin-bottom: 1.5rem; font-weight: 600; } /* Stats / Quick Highlights Bar */ .stats-strip { display: grid; - grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); + grid-template-columns: repeat(auto-fit, minmax(185px, 1fr)); gap: 0.9rem; margin-top: 1.65rem; padding-top: 1.35rem; @@ -485,20 +623,22 @@ main { } .stat-pill { - background-color: rgba(15, 23, 42, 0.45); + background-color: var(--bg-card); border: 1px solid var(--border-subtle); + border-left: 4px solid var(--accent-teal); border-radius: var(--radius-sm); - padding: 0.75rem 1rem; + padding: 0.8rem 1rem; + box-shadow: var(--shadow-card); } -[data-theme="light"] .stat-pill { - background-color: rgba(255, 255, 255, 0.8); -} +.stat-pill:nth-child(2) { border-left-color: var(--accent-amber); } +.stat-pill:nth-child(3) { border-left-color: var(--accent-magenta); } +.stat-pill:nth-child(4) { border-left-color: var(--accent-emerald); } .stat-value { display: block; font-family: var(--font-mono); - font-size: 1.15rem; + font-size: 1.12rem; font-weight: 800; color: var(--accent-teal); } @@ -510,6 +650,7 @@ main { .stat-label { font-size: 0.82rem; color: var(--text-muted); + font-weight: 500; } /* Buttons */ @@ -526,7 +667,7 @@ main { justify-content: center; gap: 0.45rem; padding: 0.62rem 1.15rem; - font-size: 0.94rem; + font-size: 0.92rem; font-weight: 700; border-radius: var(--radius-sm); text-decoration: none; @@ -536,26 +677,38 @@ main { } .btn-primary { - background: linear-gradient(135deg, #f59e0b 0%, #f97316 100%); - color: #0f172a; - box-shadow: 0 4px 14px rgba(245, 158, 11, 0.3); + background: linear-gradient(135deg, #4f46e5 0%, #db2777 100%); + color: #ffffff; + box-shadow: 0 4px 14px rgba(219, 39, 119, 0.28); } .btn-primary:hover { - background: linear-gradient(135deg, #fbbf24 0%, #fb923c 100%); - color: #0f172a; + background: linear-gradient(135deg, #4338ca 0%, #be185d 100%); + color: #ffffff; transform: translateY(-1px); - box-shadow: 0 6px 20px rgba(245, 158, 11, 0.45); + box-shadow: 0 6px 20px rgba(219, 39, 119, 0.4); } .btn-cyan { - background: linear-gradient(135deg, #06b6d4 0%, #3b82f6 100%); + background: linear-gradient(135deg, #0284c7 0%, #2563eb 100%); color: #ffffff; - box-shadow: 0 4px 14px rgba(6, 182, 212, 0.3); + box-shadow: 0 4px 14px rgba(2, 132, 199, 0.28); } .btn-cyan:hover { - background: linear-gradient(135deg, #22d3ee 0%, #60a5fa 100%); + background: linear-gradient(135deg, #0369a1 0%, #1d4ed8 100%); + color: #ffffff; + transform: translateY(-1px); +} + +.btn-emerald { + background: linear-gradient(135deg, #059669 0%, #0d9488 100%); + color: #ffffff; + box-shadow: 0 4px 14px rgba(5, 150, 105, 0.28); +} + +.btn-emerald:hover { + background: linear-gradient(135deg, #047857 0%, #0f766e 100%); color: #ffffff; transform: translateY(-1px); } @@ -567,19 +720,19 @@ main { } .btn-youtube:hover { - background: linear-gradient(135deg, #ff1a47 0%, #f43f5e 100%); + background: linear-gradient(135deg, #d9002b 0%, #be123c 100%); color: #ffffff; transform: translateY(-1px); } .btn-secondary { - background-color: var(--bg-secondary); + background-color: var(--bg-card); color: var(--text-primary); border-color: var(--border-strong); } .btn-secondary:hover { - background-color: var(--bg-card-hover); + background-color: var(--bg-secondary); border-color: var(--accent-teal); color: var(--accent-teal); transform: translateY(-1px); @@ -596,7 +749,7 @@ main { align-items: baseline; justify-content: space-between; gap: 0.75rem; - border-bottom: 1px solid var(--border-subtle); + border-bottom: 2px solid var(--border-subtle); padding-bottom: 0.65rem; margin-bottom: 1.45rem; } @@ -604,10 +757,10 @@ main { .section-label { font-family: var(--font-mono); font-size: 0.78rem; - font-weight: 700; + font-weight: 800; text-transform: uppercase; letter-spacing: 0.08em; - color: var(--accent-teal); + color: var(--accent-magenta); display: block; margin-bottom: 0.25rem; } @@ -620,7 +773,7 @@ main { .card-grid-2 { display: grid; - grid-template-columns: repeat(auto-fit, minmax(330px, 1fr)); + grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); gap: 1.35rem; } @@ -629,7 +782,7 @@ main { position: relative; background-color: var(--bg-card); border: 1px solid var(--border-subtle); - border-top: 3px solid var(--accent-teal); + border-top: 5px solid var(--accent-teal); border-radius: var(--radius-md); padding: 1.5rem; display: flex; @@ -640,16 +793,15 @@ main { } .card:hover { - border-color: var(--border-strong); transform: translateY(-3px); box-shadow: var(--shadow-panel); } -.card.card-amber { border-top-color: var(--accent-amber); } -.card.card-synth { border-top-color: var(--accent-magenta); } -.card.card-emerald { border-top-color: var(--accent-emerald); } -.card.card-coral { border-top-color: var(--accent-coral); } -.card.card-violet { border-top-color: var(--accent-violet); } +.card.card-amber { border-top-color: #f97316; } +.card.card-synth { border-top-color: #ec4899; } +.card.card-emerald { border-top-color: #10b981; } +.card.card-coral { border-top-color: #f43f5e; } +.card.card-violet { border-top-color: #6366f1; } .card-top { margin-bottom: 1rem; @@ -661,7 +813,7 @@ main { } .card h3 a:hover { - color: var(--accent-teal); + color: var(--accent-magenta); text-decoration: underline; } @@ -672,7 +824,7 @@ main { gap: 0.5rem; margin-bottom: 0.8rem; font-family: var(--font-mono); - font-size: 0.78rem; + font-size: 0.76rem; color: var(--text-muted); } @@ -683,8 +835,8 @@ main { gap: 0.35rem; font-family: var(--font-mono); font-size: 0.74rem; - font-weight: 700; - padding: 0.22rem 0.6rem; + font-weight: 800; + padding: 0.22rem 0.65rem; border-radius: 999px; border: 1px solid transparent; } @@ -692,31 +844,31 @@ main { .badge-progress { background-color: var(--accent-amber-soft); color: var(--accent-amber); - border-color: rgba(245, 158, 11, 0.45); + border-color: rgba(234, 88, 12, 0.35); } .badge-experimental { background-color: var(--accent-magenta-soft); color: var(--accent-magenta); - border-color: rgba(236, 72, 153, 0.45); + border-color: rgba(219, 39, 119, 0.35); } .badge-active { background-color: var(--accent-emerald-soft); color: var(--accent-emerald); - border-color: rgba(16, 185, 129, 0.45); + border-color: rgba(5, 150, 105, 0.35); } .badge-coral { background-color: var(--accent-coral-soft); color: var(--accent-coral); - border-color: rgba(244, 63, 94, 0.45); + border-color: rgba(225, 29, 72, 0.35); } .badge-draft { background-color: var(--accent-teal-soft); color: var(--accent-teal); - border-color: rgba(6, 182, 212, 0.45); + border-color: rgba(2, 132, 199, 0.35); } .tag-list { @@ -736,7 +888,7 @@ main { display: inline-block; font-family: var(--font-mono); font-size: 0.75rem; - font-weight: 600; + font-weight: 700; color: var(--text-secondary); background-color: var(--bg-secondary); border: 1px solid var(--border-subtle); @@ -744,18 +896,18 @@ main { border-radius: 6px; } -.tag.tag-c { color: #38bdf8; border-color: rgba(56, 189, 248, 0.35); background: rgba(56, 189, 248, 0.1); } -.tag.tag-esp { color: #f59e0b; border-color: rgba(245, 158, 11, 0.35); background: rgba(245, 158, 11, 0.1); } -.tag.tag-rust { color: #fb7185; border-color: rgba(251, 113, 133, 0.35); background: rgba(251, 113, 133, 0.1); } -.tag.tag-python { color: #a78bfa; border-color: rgba(167, 139, 250, 0.35); background: rgba(167, 139, 250, 0.1); } -.tag.tag-hw { color: #34d399; border-color: rgba(52, 211, 153, 0.35); background: rgba(52, 211, 153, 0.1); } -.tag.tag-synth { color: #f472b6; border-color: rgba(244, 114, 182, 0.35); background: rgba(244, 114, 182, 0.1); } +.tag.tag-c { color: var(--accent-teal); border-color: rgba(2, 132, 199, 0.35); background: var(--accent-teal-soft); } +.tag.tag-esp { color: var(--accent-amber); border-color: rgba(234, 88, 12, 0.35); background: var(--accent-amber-soft); } +.tag.tag-rust { color: var(--accent-coral); border-color: rgba(225, 29, 72, 0.35); background: var(--accent-coral-soft); } +.tag.tag-python { color: var(--accent-violet); border-color: rgba(109, 40, 217, 0.35); background: var(--accent-violet-soft); } +.tag.tag-hw { color: var(--accent-emerald); border-color: rgba(5, 150, 105, 0.35); background: var(--accent-emerald-soft); } +.tag.tag-synth { color: var(--accent-magenta); border-color: rgba(219, 39, 119, 0.35); background: var(--accent-magenta-soft); } /* Project Card Learning / Next Step Callouts */ .project-notes { background-color: var(--bg-secondary); border: 1px solid var(--border-subtle); - border-left: 3px solid var(--accent-violet); + border-left: 4px solid var(--accent-violet); border-radius: var(--radius-sm); padding: 0.9rem 1.05rem; margin: 0.85rem 0 1.1rem; @@ -773,7 +925,7 @@ main { .card-actions { display: flex; flex-wrap: wrap; - gap: 0.65rem; + gap: 0.6rem; padding-top: 0.95rem; border-top: 1px solid var(--border-subtle); } @@ -787,11 +939,12 @@ main { .poc-video-card { position: relative; - background: linear-gradient(135deg, rgba(15, 23, 42, 0.95) 0%, rgba(30, 27, 75, 0.92) 50%, rgba(49, 16, 47, 0.9) 100%); - border: 1px solid rgba(244, 63, 94, 0.45); + background: var(--bg-card); + border: 2px solid rgba(225, 29, 72, 0.35); + border-top: 6px solid #ff0033; border-radius: var(--radius-lg); padding: clamp(1.35rem, 3vw, 2.2rem); - box-shadow: 0 14px 36px rgba(244, 63, 94, 0.14); + box-shadow: var(--shadow-panel); overflow: hidden; } @@ -800,10 +953,9 @@ main { aspect-ratio: 16 / 9; width: 100%; background: - radial-gradient(circle at 50% 50%, rgba(255, 0, 51, 0.18), transparent 60%), - repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.02) 0px, rgba(255, 255, 255, 0.02) 1px, transparent 1px, transparent 24px), - linear-gradient(180deg, #090d16 0%, #111827 100%); - border: 1px solid rgba(255, 255, 255, 0.14); + radial-gradient(circle at 50% 50%, rgba(255, 0, 51, 0.22), transparent 60%), + linear-gradient(135deg, #1e1b4b 0%, #31102f 55%, #0f172a 100%); + border: 1px solid rgba(255, 255, 255, 0.18); border-radius: var(--radius-md); display: flex; flex-direction: column; @@ -822,14 +974,14 @@ main { display: inline-flex; align-items: center; justify-content: center; - box-shadow: 0 0 0 8px rgba(255, 0, 51, 0.18), 0 10px 28px rgba(255, 0, 51, 0.45); + box-shadow: 0 0 0 8px rgba(255, 0, 51, 0.22), 0 10px 28px rgba(255, 0, 51, 0.5); margin-bottom: 1rem; transition: transform 0.2s ease, box-shadow 0.2s ease; } .poc-video-screen:hover .poc-play-badge { transform: scale(1.07); - box-shadow: 0 0 0 12px rgba(255, 0, 51, 0.25), 0 14px 32px rgba(255, 0, 51, 0.6); + box-shadow: 0 0 0 12px rgba(255, 0, 51, 0.3), 0 14px 32px rgba(255, 0, 51, 0.65); } .poc-play-triangle { @@ -850,10 +1002,10 @@ main { font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; - color: #fda4af; - background: rgba(244, 63, 94, 0.2); - border: 1px solid rgba(244, 63, 94, 0.45); - padding: 0.25rem 0.7rem; + color: #ffe4e6; + background: rgba(244, 63, 94, 0.28); + border: 1px solid rgba(251, 113, 133, 0.55); + padding: 0.25rem 0.75rem; border-radius: 999px; margin-bottom: 0.6rem; } @@ -866,8 +1018,8 @@ main { } .poc-video-desc { - color: #cbd5e1; - max-width: 56ch; + color: #e2e8f0; + max-width: 58ch; font-size: 0.94rem; margin-bottom: 0; } @@ -876,7 +1028,7 @@ main { .callout-box { background-color: var(--bg-secondary); border: 1px solid var(--border-strong); - border-left: 4px solid var(--accent-teal); + border-left: 5px solid var(--accent-teal); border-radius: var(--radius-md); padding: 1.4rem 1.55rem; margin: 1.5rem 0; @@ -893,7 +1045,7 @@ main { .callout-title { font-family: var(--font-mono); font-size: 0.85rem; - font-weight: 700; + font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em; color: var(--accent-teal); @@ -911,11 +1063,12 @@ main { /* Figure & Schematic Frames + Zoomable Images */ .schematic-frame { - background-color: var(--bg-secondary); - border: 1px solid var(--border-subtle); + background-color: var(--bg-card); + border: 1px solid var(--border-strong); border-radius: var(--radius-md); padding: 1.1rem; margin: 1.6rem 0; + box-shadow: var(--shadow-card); } .schematic-caption { @@ -939,7 +1092,7 @@ main { .lightbox-backdrop { position: fixed; inset: 0; - background: rgba(2, 6, 23, 0.92); + background: rgba(15, 23, 42, 0.92); backdrop-filter: blur(8px); z-index: 2000; display: flex; @@ -974,12 +1127,13 @@ main { position: absolute; top: 1.25rem; right: 1.5rem; - background: var(--bg-card); + background: #ff0033; color: #ffffff; - border: 1px solid var(--border-strong); + border: none; border-radius: var(--radius-sm); - padding: 0.45rem 0.9rem; + padding: 0.5rem 0.95rem; font-family: var(--font-mono); + font-weight: 700; cursor: pointer; } @@ -988,6 +1142,7 @@ main { margin-bottom: 1.25rem; font-family: var(--font-mono); font-size: 0.85rem; + font-weight: 700; } .breadcrumb a { @@ -996,7 +1151,7 @@ main { } .breadcrumb a:hover { - color: var(--accent-amber); + color: var(--accent-magenta); text-decoration: underline; } @@ -1009,14 +1164,14 @@ main { } .filter-btn { - background-color: var(--bg-secondary); + background-color: var(--bg-card); color: var(--text-secondary); - border: 1px solid var(--border-subtle); + border: 1px solid var(--border-strong); padding: 0.45rem 0.9rem; border-radius: var(--radius-sm); font-family: var(--font-mono); font-size: 0.82rem; - font-weight: 600; + font-weight: 700; cursor: pointer; } @@ -1026,10 +1181,9 @@ main { } .filter-btn[aria-pressed="true"] { - background-color: var(--accent-teal-soft); - color: var(--accent-teal); - border-color: var(--accent-teal); - font-weight: 700; + background: var(--grad-brand); + color: #ffffff; + border-color: transparent; } /* Spec / Component Table */ @@ -1038,10 +1192,11 @@ main { border-collapse: collapse; margin: 1rem 0 1.5rem; font-size: 0.95rem; - background-color: var(--bg-secondary); - border: 1px solid var(--border-subtle); + background-color: var(--bg-card); + border: 1px solid var(--border-strong); border-radius: var(--radius-sm); overflow: hidden; + box-shadow: var(--shadow-card); } .spec-table th, @@ -1052,10 +1207,11 @@ main { } .spec-table th { - background-color: var(--bg-card); - color: var(--accent-teal); + background-color: var(--bg-secondary); + color: var(--accent-violet); font-family: var(--font-mono); font-size: 0.8rem; + font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em; } @@ -1067,7 +1223,7 @@ main { /* Footer */ .site-footer { background-color: var(--bg-secondary); - border-top: 1px solid var(--border-subtle); + border-top: 2px solid var(--border-subtle); padding: 2.25rem 0; margin-top: auto; font-size: 0.92rem; @@ -1095,7 +1251,7 @@ main { } /* Responsive Mobile Navigation */ -@media (max-width: 780px) { +@media (max-width: 840px) { .nav-toggle { display: inline-flex; } @@ -1111,12 +1267,6 @@ main { border-top: 1px solid var(--border-subtle); } - .header-inner { - flex-wrap: wrap; - padding-top: 0.6rem; - padding-bottom: 0.6rem; - } - .nav-list { flex-direction: column; align-items: stretch; diff --git a/assets/js/main.js b/assets/js/main.js index ccf7027..59bf886 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -1,56 +1,53 @@ /* ========================================================================== Ertunç Özbay — Workshop & Portfolio Script (Plain JS, No Dependencies) Handles: - 1. Accessible mobile navigation menu toggle (with Escape key support) - 2. Luminous Aurora / Daylight Studio theme switcher (persisted in localStorage) + 1. Prominent Multi-Theme Switcher (🎨 Colorful Studio [Default] | 🌈 Neon | 📐 Blueprint) + 2. Accessible mobile navigation menu toggle (with Escape key support) 3. Static blog category filtering on the Blog page - 4. One-click copy email button on Contact page + 4. One-click copy buttons for Email addresses and Code/Command blocks 5. Image lightbox for hardware prototype photos and schematics ========================================================================== */ (function () { "use strict"; - // 1. Theme Switcher (Vibrant Aurora Default + Daylight Studio Mode) + // 1. Multi-Theme Switcher (Colorful Default, Cyber Neon, Blueprint Lab) var rootEl = document.documentElement; - var savedTheme = null; + var validThemes = ["colorful", "neon", "blueprint"]; + var savedTheme = "colorful"; + try { - savedTheme = localStorage.getItem("eo-theme"); + var stored = localStorage.getItem("eo-studio-theme"); + if (stored && validThemes.indexOf(stored) !== -1) { + savedTheme = stored; + } } catch (e) {} - if (savedTheme === "light" || savedTheme === "dark") { - rootEl.setAttribute("data-theme", savedTheme); - } - - var navList = document.querySelector(".nav-list"); - if (navList && !document.querySelector("[data-theme-toggle]")) { - var li = document.createElement("li"); - var btn = document.createElement("button"); - btn.type = "button"; - btn.className = "theme-toggle"; - btn.setAttribute("data-theme-toggle", ""); - btn.setAttribute("aria-label", "Toggle color theme"); - - function updateThemeBtnLabel() { - var isLight = rootEl.getAttribute("data-theme") === "light"; - btn.textContent = isLight ? "🌙 Aurora" : "☀️ Daylight"; + function applyTheme(themeName) { + if (validThemes.indexOf(themeName) === -1) { + themeName = "colorful"; } - updateThemeBtnLabel(); + rootEl.setAttribute("data-theme", themeName); + try { + localStorage.setItem("eo-studio-theme", themeName); + } catch (e) {} - btn.addEventListener("click", function () { - var isLight = rootEl.getAttribute("data-theme") === "light"; - var nextTheme = isLight ? "dark" : "light"; - rootEl.setAttribute("data-theme", nextTheme); - try { - localStorage.setItem("eo-theme", nextTheme); - } catch (e) {} - updateThemeBtnLabel(); + var buttons = document.querySelectorAll("[data-set-theme]"); + buttons.forEach(function (btn) { + var isTarget = btn.getAttribute("data-set-theme") === themeName; + btn.setAttribute("aria-pressed", isTarget ? "true" : "false"); }); - - li.appendChild(btn); - navList.appendChild(li); } + applyTheme(savedTheme); + + document.addEventListener("click", function (event) { + var themeBtn = event.target.closest("[data-set-theme]"); + if (themeBtn) { + applyTheme(themeBtn.getAttribute("data-set-theme")); + } + }); + // 2. Mobile Navigation Toggle var navToggle = document.querySelector("[data-nav-toggle]"); var siteNav = document.querySelector("[data-site-nav]"); @@ -114,8 +111,8 @@ } // 4. Copy Email to Clipboard Buttons - var copyButtons = document.querySelectorAll("[data-copy-email]"); - copyButtons.forEach(function (btn) { + var copyEmailButtons = document.querySelectorAll("[data-copy-email]"); + copyEmailButtons.forEach(function (btn) { btn.addEventListener("click", function () { var email = btn.getAttribute("data-copy-email"); if (!email || !navigator.clipboard) return; @@ -129,7 +126,25 @@ }); }); - // 5. Image Lightbox for Hardware Photos & Schematics + // 5. Copy Code / Terminal Commands Buttons + var copyCodeButtons = document.querySelectorAll("[data-copy-code]"); + copyCodeButtons.forEach(function (btn) { + btn.addEventListener("click", function () { + var windowEl = btn.closest(".code-window"); + if (!windowEl || !navigator.clipboard) return; + var preEl = windowEl.querySelector("pre"); + if (!preEl) return; + var originalText = btn.textContent; + navigator.clipboard.writeText(preEl.innerText).then(function () { + btn.textContent = "✓ Copied!"; + setTimeout(function () { + btn.textContent = originalText; + }, 2000); + }); + }); + }); + + // 6. Image Lightbox for Hardware Photos & Schematics var zoomImages = document.querySelectorAll(".zoomable-img"); if (zoomImages.length > 0) { var backdrop = document.createElement("div"); diff --git a/blog/index.html b/blog/index.html index 52b3fcd..ba8122a 100644 --- a/blog/index.html +++ b/blog/index.html @@ -1,12 +1,12 @@ - + Blog & Build Notes — Ertunç Özbay - + @@ -21,21 +21,29 @@ - +
+
+ + + +
- + + + +
@@ -121,7 +129,7 @@ - + diff --git a/blog/post-template.html b/blog/post-template.html index a1321fb..b032774 100644 --- a/blog/post-template.html +++ b/blog/post-template.html @@ -1,12 +1,12 @@ - + - [Template] Project Build Log & Technical Note Template — Blog — Ertunç Özbay - + [Template] Project Build Log & Technical Note — Blog — Ertunç Özbay + - + @@ -17,25 +17,33 @@ Ertunç Özbay - workshop // notebook // lab + embedded // hardware // open-source - +
+
+ + + +
- + + + +
@@ -45,91 +53,47 @@ ← Back to Blog - -
- Template • Draft Example - + Template • Draft + • Category: Build Log / Technical Note - • Reading time: X min read
-

[Template] Article Title: What I Tested and Learned on the Bench

+

[Template] Project Build Log & Technical Note Title

- Summary: This page is a clearly labeled static HTML template for future blog posts. Copy this file whenever you want to publish a new build log, C programming note, or circuit experiment. + Copy this file to create a new static build log entry with hardware notes, copyable code windows, and lessons learned.

-
-
- Template Notice -

- This entry is a reusable Template / Draft kept in the repository so creating new posts requires only copying a single HTML file—no CMS, database, or build script needed. -

-
- -
-

1. Goal of the Experiment or Build Step

-

- Write a short paragraph explaining what you set out to build, test, or investigate. Keep it personal and honest—just like explaining the setup to a friend or engineering teammate. -

-
- -
-

2. Hardware & Software Setup

-

- List only the confirmed hardware components, tools, or code files you actually used during this session. -

-
/* Example C code snippet or terminal note */
-// Document register settings, MIDI array structures, or test logic here.
-
- -
-

3. What Worked and What Failed

-

- Documenting what failed is just as valuable as documenting what worked. Note any wiring mistakes, timing bugs, or AI-generated code assumptions that needed manual debugging. -

-
- -
-

4. Next Step & Related Projects

-

- Link this post back to the relevant project detail page so visitors can follow the full story: -

- +
+

1. Goal & Hardware Setup

+

Describe the circuit, microcontroller, or software module under test.

+
+
+ + + c99 — Example Firmware Snippet + + +
+
// Example code block in post template
+void app_main(void) {
+    printf("Hello from ESP-IDF!\n");
+}
+
- - + diff --git a/blog/welcome-to-my-workshop-note.html b/blog/welcome-to-my-workshop-note.html index 7c79599..2fe2e99 100644 --- a/blog/welcome-to-my-workshop-note.html +++ b/blog/welcome-to-my-workshop-note.html @@ -1,12 +1,12 @@ - + - Why I Built This Personal Workshop & Learning Notebook — Blog — Ertunç Özbay + Why I Built This Personal Workshop & Learning Notebook — Blog — Ertunç Özbay - + @@ -17,25 +17,33 @@ Ertunç Özbay - workshop // notebook // lab + embedded // hardware // open-source - +
+
+ + + +
- + + + +
@@ -48,20 +56,19 @@
- Example • Starter Note + Starter Note • Category: Personal Learning Reflections • Reading time: 3 min read
-

Why I Built This Personal Workshop & Learning Notebook

+

Why I Built This Personal Workshop & Learning Notebook

A short starter note on why I want my website to feel like an open engineering workbench rather than a polished corporate résumé.

@@ -78,19 +85,17 @@

Hardware, Software, and Responsibility

- Whether I am working on my MIDI Breadboard Instrument, my Multi-Functional RC Controller, or my RC and Autonomous Vehicle project, my goal is to understand how the physical circuit and the code interact. -

-

- Just like understanding a car’s steering, brakes, and dynamics makes you a more responsible driver, understanding both hardware and software helps me ask better questions, evaluate AI output critically, spot mistakes, and take responsibility for what I build. + Whether I am working on my MIDI Breadboard Instrument, my Multi-Functional RC Controller, my Point Blank Linux Launcher, or my RC and Autonomous Vehicle project, my goal is to understand how the physical circuit and the code interact.

Related Projects

← Back to Blog Index @@ -104,7 +109,7 @@ - + diff --git a/contact.html b/contact.html index 8145413..1960c08 100644 --- a/contact.html +++ b/contact.html @@ -1,12 +1,12 @@ - + Contact & Collaboration — Ertunç Özbay - + - + @@ -21,21 +21,29 @@ - +
+
+ + + +
- + + + +
@@ -45,12 +53,13 @@ ✉️ DIRECT CONTACT // OPEN COLLABORATION

Contact & Collaboration

- Whether you want to talk about ESP32 embedded firmware, circuit design, Linux systems programming, or open-source hardware collaboration, feel free to reach out directly via Gmail, LinkedIn, or GitHub. + Whether you want to talk about ESP32 embedded firmware, circuit design, Linux systems programming, or open-source hardware collaboration, feel free to reach out directly via email, LinkedIn, or GitHub.

@@ -58,29 +67,26 @@
- +
- +
- Primary Inbox • Gmail - Fastest Response + Primary Email + Direct Inbox
-

ertuncozbayh@gmail.com

+

ertunc.ozbay@outlook.com

- My primary personal and engineering Gmail inbox. Ideal for project discussions, schematic/code questions, internship or collaboration inquiries, and fellow student builders. -

-

- Secondary / Git Email (Outlook): ertunc.ozbay@outlook.com + My official engineering and open-source email inbox. Ideal for project discussions, schematic/firmware questions, internship or collaboration inquiries, and fellow student builders.

- Send Email (Gmail) - + Send Email +
@@ -111,7 +117,7 @@
- +

Active Repositories on GitHub

@@ -126,7 +132,9 @@

- Open Repository → + Project Page + ⬇ Download ZIP + GitHub →
@@ -139,7 +147,9 @@

- Open Repository → + Project Page + ⬇ Download ZIP + GitHub →
@@ -152,7 +162,9 @@

- Open Repository → + Project Page + ⬇ Download v1.0.0 Binary + GitHub →
@@ -188,7 +200,7 @@ - + diff --git a/index.html b/index.html index 1ecf054..779e5c6 100644 --- a/index.html +++ b/index.html @@ -1,12 +1,12 @@ - + Ertunç Özbay — Embedded Systems, Hardware Lab & Open-Source Projects - + @@ -21,21 +21,29 @@ - +
+
+ + + +
- + + + +
@@ -48,12 +56,12 @@ I design embedded hardware, write bare-metal C & FreeRTOS firmware, and build open-source systems from the transistor level up to Linux desktop tooling.

- Welcome to my engineering studio and notebook. Here I document my real hardware prototypes—from an ESP32-S3 2.4 GHz Multi-Functional RC Console and a Dual-Core ESP32 16-Track MIDI Synthesizer to a 4WD Autonomous Vehicle and a Standalone Linux Game Launcher written in Rust. + Welcome to my engineering studio and notebook. Here you can inspect my real hardware prototypes, copy build/flash commands, browse source code, and download releases—from my ESP32-S3 2.4 GHz Multi-Functional RC Console and Dual-Core ESP32 16-Track MIDI Synthesizer to my 4WD Autonomous Vehicle and Standalone Linux Game Launcher written in Rust.

- 🚀 Explore All 4 Projects + 🚀 Explore Projects, Code & Downloads 💻 GitHub (@ertunc-ozbay) - ✉️ Contact & Gmail + ✉️ Contact (ertunc.ozbay@outlook.com)
@@ -70,8 +78,8 @@ Custom Python RLE MIDI-to-C Compiler
- Open Source - Schematics, Firmware & Build Logs + Direct Downloads + Pre-Built Binaries, Firmware & Schematics
@@ -79,10 +87,10 @@
- -

Projects on My Bench

+ +

Projects, Commands & Downloads

- View full specifications & PoC video slots → + View all project code, commands & PoC videos →
@@ -101,12 +109,13 @@
  • ESP32-S3-N16R8
  • ESP-IDF C99
  • nRF24L01+ 2.4GHz
  • -
  • KiCad Schematic
  • +
  • KiCad Schematic
  • @@ -129,12 +138,37 @@
    - Project Page & PoC Video - GitHub Repo + Code, Commands & PoC Video + ⬇ Download ZIP + GitHub
    +
    +
    +
    + v1.0.0 Binary Released + Rust • Linux Systems & Wine +
    +

    Point Blank on Linux — Standalone Community Launcher

    +

    + An all-in-one standalone Linux desktop launcher written in Rust that runs Point Blank (Zepetto / TAM) on Linux with 100% unmodified official CheatBlocker anti-cheat, automated Wine prefix provisioning, and DirectX 9 / DirectX 11 support. +

    + +
    +
    + Setup Commands & PoC Video + ⬇ Download v1.0.0 (.tar.gz) + GitHub +
    +
    + +
    @@ -152,39 +186,47 @@
    + + - -
    -
    -
    - v1.0.0 Released - Rust • Linux Systems & Wine -
    -

    Point Blank on Linux — Standalone Community Launcher

    -

    - An all-in-one standalone Linux desktop launcher written in Rust that runs Point Blank (Zepetto / TAM) on Linux with 100% unmodified official CheatBlocker anti-cheat, automated Wine prefix provisioning, and DirectX 9 / DirectX 11 support. -

    - -
    -
    - Project Page & PoC Video - GitHub Repo -
    -
    + +
    +
    +
    + +

    Clone & Run My Open-Source Projects

    +
    +
    + +
    +
    + + + bash — Clone & Launch Repositories (Arch Linux / ESP-IDF v5.2.2) + + +
    +
    # 1. ESP32-S3 Multi-Functional Controller (ESP-IDF v5.2.2)
    +git clone https://github.com/ertunc-ozbay/multi-functional-controller.git
    +cd multi-functional-controller/firmware && source ~/esp/esp-idf/export.sh && idf.py build
    +
    +# 2. ESP32 16-Track MIDI Breadboard Synthesizer & Python RLE Compiler
    +git clone https://github.com/ertunc-ozbay/midi-breadboard-instrument.git
    +cd midi-breadboard-instrument && python3 scripts/midi_to_c.py scripts/midillis/Alla_Turca/Alla_Turca.mid
    +
    +# 3. Point Blank Linux Standalone Launcher (Download Pre-Compiled x86_64 Release)
    +curl -L -O https://github.com/ertunc-ozbay/pointblank-linux/releases/latest/download/pointblank-linux-v1.0.0-linux-x86_64.tar.gz
    +tar -xzf pointblank-linux-v1.0.0-linux-x86_64.tar.gz && cd pointblank-linux-v1.0.0-linux-x86_64 && ./pointblank-linux
    - +

    How I Approach Engineering

    @@ -217,7 +259,7 @@ Direct Contact

    Collaborate & Connect

    - Reach out directly via Gmail (ertuncozbayh@gmail.com), Outlook, LinkedIn, or GitHub to discuss embedded systems, electronics, or open-source builds. + Reach out directly via email at ertunc.ozbay@outlook.com, LinkedIn, or GitHub to discuss embedded systems, electronics, or open-source builds.

    View Contact & Email Details → @@ -231,7 +273,7 @@ - + diff --git a/lab.html b/lab.html index afc17ee..f3039a6 100644 --- a/lab.html +++ b/lab.html @@ -1,15 +1,15 @@ - + Lab & Experiment Notebook — Ertunç Özbay - + - + @@ -69,6 +77,10 @@ While building the 16-Track MIDI Breadboard Instrument, raw MIDI delta-slices caused the LEDs and 1.3" SPI OLED to strobe violently. Writing a custom Run-Length Encoding (RLE) compressor in Python (midi_to_c.py) and transposing bass-heavy tracks like Seven Nation Army +2 octaves solved both flash exhaustion and piezo acoustic roll-off.

    +
    + 🐍 Download midi_to_c.py + Full MIDI Project → +
    @@ -82,6 +94,10 @@ On the Multi-Functional RC Controller, the ESP32-S3-N16R8 reserves GPIO 35–37 for internal Octal PSRAM/Flash. We remapped the shared SPI2 bus (MOSI: 11, MISO: 13, SCK: 12) with dedicated hardware CS lines for the nRF24L01+ (CSN: 10), MicroSD (CS: 39), and ST7789 IPS TFT (CS: 40).

    +
    + 📐 Download KiCad Schematic + Full Controller Page → +
    @@ -106,6 +122,10 @@ In pointblank-linux, we engineered a standalone Rust launcher that automatically provisions a 16-byte TLS-aligned ntdll.dll runtime and vcrun2022 / d3dx11_43 components so Point Blank runs at 200 FPS in DirectX 11 on Linux with unmodified official CheatBlocker anti-cheat.

    +
    + ⬇ Download v1.0.0 Binary + Read Technical Notes → +
    @@ -116,9 +136,12 @@

    RLE MIDI-to-C Struct Compiler (midi_to_c.py)

    - Converts multi-channel `.mid` files into compact C99 SequenceStep struct arrays (`{frequency, duration, kick_drum, hi_hat}`), automatically routing MIDI Channel 10 and low bass notes (`< MIDI 50`) to hardware percussion buzzers. + Converts multi-channel `.mid` files into compact C99 SequenceStep struct arrays ({frequency, duration, kick_drum, hi_hat}), automatically routing MIDI Channel 10 and low bass notes (< MIDI 50) to hardware percussion buzzers.

    +
    + View Script on GitHub → +
    @@ -148,7 +171,7 @@ - + diff --git a/projects/index.html b/projects/index.html index 6fe2c3f..34726a1 100644 --- a/projects/index.html +++ b/projects/index.html @@ -1,12 +1,12 @@ - + - Projects — Ertunç Özbay - + Projects, Code & Downloads — Ertunç Özbay + - + @@ -21,31 +21,39 @@ - +
    +
    + + + +
    - + + + +
    - ⚡ PROJECT SHOWCASE // VERIFIED BUILDS & REPOSITORIES + ⚡ PROJECT SHOWCASE // CODE, COMMANDS, DOWNLOADS & POC VIDEOS

    Engineering Projects & Open-Source Builds

    - Every project documented here is backed by real hardware on my bench or shipped open-source code on my GitHub—complete with verified pinouts, schematics, build photos, and dedicated slots for upcoming YouTube Proof-of-Concept (PoC) demonstration videos. + Every project documented here includes verified hardware pinouts, build photos, copyable terminal commands, source code snippets, direct download links, and a dedicated YouTube Proof-of-Concept (PoC) video showcase.

    @@ -67,7 +75,7 @@

    Multi-Functional RC Controller (MFC)

    - A custom 2.4 GHz wireless remote controller and multi-purpose embedded console built around the ESP32-S3-N16R8 and nRF24L01+ PA+LNA transceiver. Currently built as an early Rev 0.1 perfboard carrier and transitioning into a DT-100 (190×137×59 mm) desktop console with dual K-Silver Hall-effect gimbals and a 1.3" ST7789 IPS TFT display. + A custom 2.4 GHz wireless remote controller and multi-purpose embedded console built around the ESP32-S3-N16R8 and nRF24L01+ PA+LNA transceiver. Includes C99 ESP-IDF firmware, KiCad 9.0 schematics, Rev 0.1 perfboard photos, and Phase 2 DT-100 console BOM.

    -

    Includes on page: 3 early prototype build photos, full KiCad SVG schematic, verified ESP32-S3 GPIO pinout, Phase 2 DT-100 BOM, and 🎬 YouTube PoC Video Placeholder.

    +

    Included on page: Copyable `idf.py` build/flash commands, C99 firmware source code, downloadable KiCad `.kicad_sch` schematic & `.zip` archive, 3 prototype photos, and 🎬 YouTube PoC Video slot.

    - Read Page & PoC Video - GitHub Repo + Open Page, Code & PoC + ⬇ Download ZIP + GitHub
    @@ -112,51 +121,23 @@
    -

    Includes on page: 3 high-res breadboard photos, 16-track playlist table, ESP32 pinout, RLE compression architecture, and 🎬 YouTube PoC Video Placeholder.

    +

    Included on page: Full `midi_to_c.py` Python script & C99 Dual-Core FreeRTOS audio engine code, copyable CLI commands, downloadable `.py` & `.zip` links, 3 breadboard photos, and 🎬 YouTube PoC Video slot.

    - Read Page & PoC Video - GitHub Repo + Open Page, Code & PoC + ⬇ Download ZIP + GitHub
    - -
    -
    -
    - In Progress - Project 03 • Robotics & Control -
    -

    RC and Autonomous 4WD Vehicle

    -

    - An ongoing 4WD robotic vehicle platform exploring manual 2.4 GHz RF remote control (paired with the Multi-Functional Controller) alongside autonomous obstacle avoidance, motor driver electronics, and real-time control logic. -

    - -
      -
    • 4WD Vehicle Platform
    • -
    • 2.4 GHz RF Receiver Link
    • -
    • Autonomous Control Logic
    • -
    • Power & Motor Electronics
    • -
    - -
    -

    Includes on page: System scope, manual-to-autonomous control transition notes, and 🎬 YouTube PoC Video Placeholder.

    -
    -
    - - -
    - - +
    - v1.0.0 Shipped - Project 04 • Rust & Linux Systems + v1.0.0 Shipped Binary + Project 03 • Rust & Linux Systems

    Point Blank on Linux — Standalone Community Launcher

    @@ -171,13 +152,43 @@

    -

    Includes on page: Architecture overview, Wine prefix automation breakdown, release links, and 🎬 YouTube PoC Video Placeholder.

    +

    Included on page: Direct pre-compiled `x86_64` release `.tar.gz` download, copyable distro dependency commands (Arch/Ubuntu/Fedora), Rust source build commands, and 🎬 YouTube PoC Video slot.

    +
    + + +
    +
    +
    + In Progress + Project 04 • Robotics & Control +
    +

    RC and Autonomous 4WD Vehicle

    +

    + An ongoing 4WD robotic vehicle platform exploring manual 2.4 GHz RF remote control (paired with the Multi-Functional Controller) alongside autonomous obstacle avoidance, motor driver electronics, and real-time control logic. +

    + +
      +
    • 4WD Vehicle Platform
    • +
    • 2.4 GHz RF Receiver Link
    • +
    • Autonomous Control Logic
    • +
    • Power & Motor Electronics
    • +
    + +
    +

    Included on page: C99 2.4 GHz telemetry receiver packet & differential motor drive code structure, companion controller link, and 🎬 YouTube PoC Video slot.

    +
    +
    + +
    @@ -189,7 +200,7 @@ - + diff --git a/projects/midi-breadboard-instrument.html b/projects/midi-breadboard-instrument.html index f732f0b..a2384cb 100644 --- a/projects/midi-breadboard-instrument.html +++ b/projects/midi-breadboard-instrument.html @@ -1,12 +1,12 @@ - + MIDI Breadboard Instrument (Desk Rave & 16-Track Symphony) — Projects — Ertunç Özbay - + - + @@ -21,21 +21,29 @@ - +
    +
    + + + +
    - + + + +
    @@ -59,9 +67,10 @@ What started as making a passive piezo buzzer squeak evolved into a full 16-track embedded music box with live kick/hi-hat drum transients, hardware PCNT quadrature rotary controls for real-time tempo and volume scaling, and dual-core FreeRTOS task isolation.

    - 💻 View GitHub Repository + 💻 View GitHub Repo + ⬇ Download Project (.zip) + 🐍 Download midi_to_c.py 🎬 Watch PoC Video Slot - All Projects
    @@ -70,7 +79,6 @@

    YouTube Proof-of-Concept Demonstration

    -
    -
    - -

    From a Squeaking Buzzer to a Dual-Core Synthesizer

    -

    - Pushing a bare-metal breadboard setup to play recognizable, energetic multi-track music required solving several real embedded systems challenges: + +

    + +

    Build, Flash & MIDI Conversion Commands

    +

    + Clone the repository, convert any `.mid` file into an RLE-compressed C struct array using `scripts/midi_to_c.py`, and flash the 16-track firmware to an ESP32:

    -
      -
    • The Strobe-Light Bug & RLE Compression (midi_to_c.py): Raw MIDI files often slice sustained notes into microscopic fragments, causing the LEDs and OLED UI to strobe at 30+ Hz while wasting flash memory. We built a custom Python Run-Length Encoding (RLE) compressor using mido that merges contiguous identical pitch/drum states into solid SequenceStep blocks and routes bass/percussion channels to dedicated drum triggers.
    • -
    • Acoustic Hardware Limits (+2 Octave Transposition): Passive piezo buzzers physically struggle to resonate at low bass frequencies. Tracks with deep basslines like Seven Nation Army were transposed up two full octaves so the piezo disc resonates clearly while the active buzzers carry the rhythmic punch.
    • -
    • Dual-Core FreeRTOS Lockless IPC: Core 0 runs oled_visualizer_task (30 FPS SPI DMA framebuffer engine) and button_task (debounced input polling), while Core 1 exclusively runs buzzer_sequence_task for microsecond-accurate LEDC PWM pitch generation and hardware PCNT rotary encoder scaling.
    • -
    + +
    +
    + + + bash — Convert MIDI to C & Flash ESP32 Firmware (ESP-IDF v5.2.2) + + +
    +
    # 1. Clone the repository
    +git clone https://github.com/ertunc-ozbay/midi-breadboard-instrument.git
    +cd midi-breadboard-instrument
    +
    +# 2. (Optional) Convert a custom .mid file into an RLE-compressed C struct array
    +pip install mido
    +python3 scripts/midi_to_c.py scripts/midillis/Alla_Turca/Alla_Turca.mid > my_track.h
    +
    +# 3. Build and flash the 16-track firmware to ESP32
    +source ~/esp/esp-idf/export.sh
    +idf.py build
    +idf.py -p /dev/ttyUSB0 flash monitor
    +
    + +

    Python RLE MIDI-to-C Compiler (scripts/midi_to_c.py)

    +

    + To prevent fragmented MIDI delta-times from strobing the LEDs/OLED at 30+ Hz and exhausting flash memory, midi_to_c.py merges contiguous identical states via Run-Length Encoding and routes Channel 10 + bass notes (`< MIDI 50`) to hardware percussion buzzers: +

    + +
    +
    + + + python3 — scripts/midi_to_c.py (RLE Compression & Drum Routing Engine) + + +
    +
    #!/usr/bin/env python3
    +import sys, mido
    +
    +def convert_midi_to_c(midi_filename):
    +    mid = mido.MidiFile(midi_filename)
    +    safe_name = midi_filename.split('/')[-1].replace('.mid', '').replace('-', '_')
    +    print(f"const SequenceStep midi_{safe_name}[] = {{")
    +
    +    active_melody_notes = set()
    +    time_accum = 0.0
    +    trigger_kick = trigger_hat = False
    +    rle_freq, rle_dur, rle_kick, rle_hat = -1, 0, False, False
    +
    +    for msg in mid:
    +        time_accum += msg.time
    +        if msg.type in ['note_on', 'note_off'] and time_accum > 0.01:
    +            duration_ms = int(time_accum * 1000)
    +            freq = int(440.0 * (2.0 ** ((max(active_melody_notes) - 69) / 12.0))) if active_melody_notes else 0
    +
    +            # RLE Engine: coalesce contiguous identical frequency & drum states
    +            if freq == rle_freq and trigger_kick == rle_kick and trigger_hat == rle_hat:
    +                rle_dur += duration_ms
    +            else:
    +                if rle_dur > 0:
    +                    print(f"    {{{rle_freq}, {rle_dur}, {str(rle_kick).lower()}, {str(rle_hat).lower()}}},")
    +                rle_freq, rle_dur, rle_kick, rle_hat = freq, duration_ms, trigger_kick, trigger_hat
    +
    +            time_accum, trigger_kick, trigger_hat = 0.0, False, False
    +
    + +

    Dual-Core FreeRTOS Music & Visualizer Architecture (main/mmcontroller.c)

    +
    +
    + + + c99 — main/mmcontroller.c (SequenceStep Struct & Dual-Core Task Pinning) + + +
    +
    typedef struct {
    +    uint16_t frequency; // Melody pitch in Hz (driven by 13-bit LEDC PWM on GPIO 25)
    +    uint16_t duration;  // Step duration in ms (scaled live by PCNT rotary speed)
    +    bool kick_drum;     // Triggers Active Buzzer 1 (GPIO 26) + Kick LED (GPIO 21)
    +    bool hi_hat;        // Triggers Active Buzzer 2 (GPIO 27) + Hat LED (GPIO 22)
    +} SequenceStep;
    +
    +void app_main(void) {
    +    printf("Desk Rave: 16-Track Symphony Edition Initializing...\n");
    +    init_hardware();
    +
    +    // Core 0: 30 FPS SPI OLED Framebuffer Visualizer & 50ms Button Polling
    +    xTaskCreatePinnedToCore(oled_visualizer_task, "oled_task",  4096, NULL, 4, NULL, 0);
    +    xTaskCreatePinnedToCore(button_task,          "btn_task",   4096, NULL, 5, NULL, 0);
    +
    +    // Core 1: Dedicated Real-Time Audio Synthesizer & PCNT Rotary Scaling
    +    xTaskCreatePinnedToCore(buzzer_sequence_task, "music_task", 4096, NULL, 5, NULL, 1);
    +}
    +
    @@ -188,9 +286,6 @@

    The 16-Track Symphony

    -

    - All 16 tracks are stored in ESP32 flash memory as SequenceStep arrays featuring frequency, duration, kick_drum, and hi_hat triggers: -

    1. Careless Whisper (Extended Club Edit)
    2. Take On Me (EDM Build-up Edition)
    3. @@ -210,20 +305,6 @@
    4. Mega Man 2 (Dr. Wily Stage)
    - -
    - -

    Current State & Roadmap

    -
    - Current State & Next Steps -

    - The firmware is rock-solid on the breadboard: the rotary encoder dynamically scales volume and tempo via lockless IPC variables, all 16 tracks play from flash memory, and the 1.3" SPI OLED renders real-time frequency bars and drum hits at 30 FPS. -

    -

    - Next Step: Migrating the dual-breadboard circuit onto a soldered perfboard or custom KiCad PCB. -

    -
    -
    @@ -232,7 +313,7 @@ - + diff --git a/projects/multi-functional-controller.html b/projects/multi-functional-controller.html index 94482c5..d75f2a2 100644 --- a/projects/multi-functional-controller.html +++ b/projects/multi-functional-controller.html @@ -1,12 +1,12 @@ - + Multi-Functional RC Controller (MFC) — Projects — Ertunç Özbay - + - + @@ -21,21 +21,29 @@ - +
    +
    + + + +
    - + + + +
    @@ -59,9 +67,10 @@ Designed to serve as a universal handheld and desktop transmitter for external robotic platforms (such as my 4WD RC & Autonomous Vehicle) while integrating dual K-Silver Hall-effect joysticks, a 1.3" ST7789 IPS TFT display, MicroSD storage, and MAX4466 audio capture.

    - 💻 View GitHub Repository + 💻 View GitHub Repo + ⬇ Download Repo (.zip) + 📐 Download KiCad Schematic 🎬 Watch PoC Video Slot - All Projects
    @@ -70,7 +79,6 @@

    YouTube Proof-of-Concept Demonstration

    -
    @@ -145,7 +169,7 @@ - +