diff --git a/app/@breadcrumbs/about/page.tsx b/app/@breadcrumbs/about/page.tsx index ed78d5e..c04bb9f 100644 --- a/app/@breadcrumbs/about/page.tsx +++ b/app/@breadcrumbs/about/page.tsx @@ -1,4 +1,4 @@ -import { Breadcrumbs } from '@/components/layout/Breadcrumbs'; +import { Breadcrumbs } from '@/components/layout/breadcrumbs'; export default function AboutBreadcrumb() { return ( diff --git a/app/@breadcrumbs/blog/[...slug]/page.tsx b/app/@breadcrumbs/blog/[...slug]/page.tsx index a2dc242..21c9398 100644 --- a/app/@breadcrumbs/blog/[...slug]/page.tsx +++ b/app/@breadcrumbs/blog/[...slug]/page.tsx @@ -1,4 +1,4 @@ -import { Breadcrumbs } from '@/components/layout/Breadcrumbs'; +import { Breadcrumbs } from '@/components/layout/breadcrumbs'; import { getPostBySlug } from '@/lib/markdown'; interface BreadcrumbItem { diff --git a/app/@breadcrumbs/blog/page.tsx b/app/@breadcrumbs/blog/page.tsx index 6abd4ba..e3897f5 100644 --- a/app/@breadcrumbs/blog/page.tsx +++ b/app/@breadcrumbs/blog/page.tsx @@ -1,4 +1,4 @@ -import { Breadcrumbs } from '@/components/layout/Breadcrumbs'; +import { Breadcrumbs } from '@/components/layout/breadcrumbs'; export default function BlogBreadcrumb() { return ( diff --git a/app/@breadcrumbs/default.tsx b/app/@breadcrumbs/default.tsx index 8f1d385..f934837 100644 --- a/app/@breadcrumbs/default.tsx +++ b/app/@breadcrumbs/default.tsx @@ -1,6 +1,6 @@ 'use client'; -import { Breadcrumbs } from '@/components/layout/Breadcrumbs'; +import { Breadcrumbs } from '@/components/layout/breadcrumbs'; export default function DefaultBreadcrumb() { return ; diff --git a/app/@breadcrumbs/tags/[tag]/page.tsx b/app/@breadcrumbs/tags/[tag]/page.tsx index 9451e8d..7f3c00a 100644 --- a/app/@breadcrumbs/tags/[tag]/page.tsx +++ b/app/@breadcrumbs/tags/[tag]/page.tsx @@ -1,4 +1,4 @@ -import { Breadcrumbs } from '@/components/layout/Breadcrumbs'; +import { Breadcrumbs } from '@/components/layout/breadcrumbs'; export default async function TagBreadcrumb({ params, diff --git a/app/@breadcrumbs/tags/page.tsx b/app/@breadcrumbs/tags/page.tsx index 8d74cd3..01aa702 100644 --- a/app/@breadcrumbs/tags/page.tsx +++ b/app/@breadcrumbs/tags/page.tsx @@ -1,4 +1,4 @@ -import { Breadcrumbs } from '@/components/layout/Breadcrumbs'; +import { Breadcrumbs } from '@/components/layout/breadcrumbs'; export default function TagsBreadcrumb() { return ( diff --git a/app/globals.css b/app/globals.css index 4e99d8c..073c34a 100644 --- a/app/globals.css +++ b/app/globals.css @@ -1,5 +1,37 @@ @import "tailwindcss"; +@theme { + --color-*: initial; +} + +@variant dark (&:where(.dark, .dark *)); + +@layer base { + :root { + /* Light mode colors */ + --bg-primary: 241 245 249; + --bg-secondary: 226 232 240; + --bg-tertiary: 203 213 225; + --text-primary: 15 23 42; + --text-secondary: 51 65 85; + --text-muted: 100 116 139; + --border-primary: 203 213 225; + --border-subtle: 226 232 240; + } + + .dark { + /* Dark mode colors - INDUSTRIAL */ + --bg-primary: 24 24 27; + --bg-secondary: 15 23 42; + --bg-tertiary: 30 41 59; + --text-primary: 241 245 249; + --text-secondary: 203 213 225; + --text-muted: 100 116 139; + --border-primary: 71 85 105; + --border-subtle: 30 41 59; + } +} + @layer utilities { .scrollbar-hide { -ms-overflow-style: none; @@ -11,21 +43,99 @@ /* Industrial/Terminal aesthetic utilities */ .grid-bg { - background-image: url('/grid.svg'); + background-image: + linear-gradient(rgba(100, 116, 139, 0.1) 1px, transparent 1px), + linear-gradient(90deg, rgba(100, 116, 139, 0.1) 1px, transparent 1px); + background-size: 20px 20px; } + /* Noise texture */ .noise-bg { background-image: url('/noise.svg'); + opacity: 0.03; + pointer-events: none; } + /* Scanline effect */ .scanline { - background: repeating-linear-gradient( + background: linear-gradient( 0deg, - transparent, - transparent 2px, - rgba(0, 0, 0, 0.3) 2px, - rgba(0, 0, 0, 0.3) 4px + transparent 0%, + rgba(6, 182, 212, 0.1) 50%, + transparent 100% ); + background-size: 100% 3px; + pointer-events: none; + } + + .scanline::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: linear-gradient( + to bottom, + transparent 0%, + rgba(6, 182, 212, 0.05) 50%, + transparent 100% + ); + animation: scanline 8s linear infinite; + pointer-events: none; + } + + /* CRT screen curvature effect */ + .crt-effect { + animation: flicker 0.15s infinite; + } + + /* Glitch text effect */ + .glitch-text { + position: relative; + } + + .glitch-text::before, + .glitch-text::after { + content: attr(data-text); + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + opacity: 0; + } + + .glitch-text.active::before { + color: #06b6d4; + animation: glitch-1 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94); + clip-path: polygon(0 0, 100% 0, 100% 45%, 0 45%); + transform: translate(-2px, -2px); + opacity: 0.8; + } + + .glitch-text.active::after { + color: #10b981; + animation: glitch-2 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94); + clip-path: polygon(0 55%, 100% 55%, 100% 100%, 0 100%); + transform: translate(2px, 2px); + opacity: 0.8; + } + + @keyframes glitch-1 { + 0%, 100% { clip-path: polygon(0 0, 100% 0, 100% 45%, 0 45%); transform: translate(0); } + 20% { clip-path: polygon(0 15%, 100% 15%, 100% 65%, 0 65%); } + 40% { clip-path: polygon(0 30%, 100% 30%, 100% 70%, 0 70%); } + 60% { clip-path: polygon(0 5%, 100% 5%, 100% 60%, 0 60%); } + 80% { clip-path: polygon(0 25%, 100% 25%, 100% 40%, 0 40%); } + } + + @keyframes glitch-2 { + 0%, 100% { clip-path: polygon(0 55%, 100% 55%, 100% 100%, 0 100%); transform: translate(0); } + 20% { clip-path: polygon(0 70%, 100% 70%, 100% 95%, 0 95%); } + 40% { clip-path: polygon(0 40%, 100% 40%, 100% 85%, 0 85%); } + 60% { clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%); } + 80% { clip-path: polygon(0 50%, 100% 50%, 100% 90%, 0 90%); } } /* Grayscale filter with instant toggle */ @@ -36,4 +146,105 @@ .grayscale-0 { filter: grayscale(0%); } + + /* Cyberpunk Glitch Effect for Button */ + .glitch-btn { + position: relative; + animation: glitch 300ms cubic-bezier(.25, .46, .45, .94); + } + + .glitch-layer { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + display: flex; + align-items: center; + justify-content: center; + opacity: 0.8; + clip-path: polygon(0 0, 100% 0, 100% 45%, 0 45%); + } + + .glitch-layer:first-of-type { + animation: glitch-1 300ms cubic-bezier(.25, .46, .45, .94); + color: rgb(6 182 212); /* cyan-500 */ + transform: translate(-2px, 0); + clip-path: polygon(0 0, 100% 0, 100% 35%, 0 35%); + } + + .glitch-layer:last-of-type { + animation: glitch-2 300ms cubic-bezier(.25, .46, .45, .94); + color: rgb(16 185 129); /* emerald-500 */ + transform: translate(2px, 0); + clip-path: polygon(0 65%, 100% 65%, 100% 100%, 0 100%); + } + + @keyframes glitch-1 { + 0%, 100% { + transform: translate(0, 0); + clip-path: polygon(0 0, 100% 0, 100% 35%, 0 35%); + } + 25% { + transform: translate(-3px, 2px); + clip-path: polygon(0 10%, 100% 10%, 100% 45%, 0 45%); + } + 50% { + transform: translate(3px, -2px); + clip-path: polygon(0 20%, 100% 20%, 100% 55%, 0 55%); + } + 75% { + transform: translate(-2px, -1px); + clip-path: polygon(0 5%, 100% 5%, 100% 40%, 0 40%); + } + } + + @keyframes glitch-2 { + 0%, 100% { + transform: translate(0, 0); + clip-path: polygon(0 65%, 100% 65%, 100% 100%, 0 100%); + } + 25% { + transform: translate(3px, -2px); + clip-path: polygon(0 55%, 100% 55%, 100% 90%, 0 90%); + } + 50% { + transform: translate(-3px, 2px); + clip-path: polygon(0 45%, 100% 45%, 100% 80%, 0 80%); + } + 75% { + transform: translate(2px, 1px); + clip-path: polygon(0 60%, 100% 60%, 100% 95%, 0 95%); + } + } + + /* Border Pulse Animation */ + .border-pulse { + animation: pulse-border 2s ease-in-out infinite; + } + + /* Screen Flicker Effect */ + body.screen-flicker { + animation: flicker 150ms ease-in-out; + } + + body.screen-flicker::before { + content: ''; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(6, 182, 212, 0.1); + pointer-events: none; + z-index: 9999; + animation: flicker 150ms ease-in-out; + } + + /* CRT Noise Texture */ + @supports (filter: url('#noise')) { + .noise-bg { + filter: url('#noise'); + } + } } diff --git a/app/layout.tsx b/app/layout.tsx index 0dfc5e4..153a0bd 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,6 +1,7 @@ import type { Metadata } from 'next' import { JetBrains_Mono } from 'next/font/google' import './globals.css' +import { ThemeProvider } from '@/providers/providers' const jetbrainsMono = JetBrains_Mono({ subsets: ['latin'], variable: '--font-mono' }) @@ -33,20 +34,28 @@ export default function RootLayout({ children: React.ReactNode }) { return ( - - - {children} + + + + {children} - {/* Footer - from worktree-agent-1 */} -
-
-
-

- © 2025 // BLOG & PORTOFOLIU // ALL RIGHTS RESERVED -

+ {/* Footer - from worktree-agent-1 */} +
+
+
+

+ © 2025 // BLOG & PORTOFOLIU // ALL RIGHTS RESERVED +

+
-
-
+ +
) diff --git a/app/page.tsx b/app/page.tsx index cc338e4..c28083c 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -2,48 +2,50 @@ import Link from 'next/link' import Image from 'next/image' import { getAllPosts } from '@/lib/markdown' import { formatDate } from '@/lib/utils' +import { ThemeToggle } from '@/components/theme-toggle' export default async function HomePage() { const allPosts = await getAllPosts() const featuredPosts = allPosts.slice(0, 6) return ( -
+
{/* Hero Section - from worktree-agent-2 */} -
+
-
+
{/* Logo */} -
+
Logo TERMINAL:// V2.0
-
- [BLOG] - [ABOUT] +
+ [BLOG] + [ABOUT] +
-
-

DOCUMENT LEVEL-1 // CLASSIFIED

-

+
+

DOCUMENT LEVEL-1 // CLASSIFIED

+

BUILD. WRITE.
SHARE.

-

+

> Explorează idei despre dezvoltare, design și tehnologie_

- + [EXPLOREAZĂ BLOG] - + [DESPRE MINE]
@@ -52,13 +54,13 @@ export default async function HomePage() {

{/* Featured Posts Grid - from worktree-agent-1 */} -
+
-
-

+

+

ARCHIVE ACCESS // RECENT ENTRIES

-

+

> POSTĂRI RECENTE_

@@ -67,37 +69,37 @@ export default async function HomePage() { {featuredPosts.map((post, index) => (
-
+
{post.frontmatter.image ? ( {post.frontmatter.title} ) : ( -
- #{String(index + 1).padStart(2, '0')} +
+ #{String(index + 1).padStart(2, '0')}
)} -
-
- +
+
+ FILE#{String(index + 1).padStart(3, '0')} // {post.frontmatter.category}
-
-
-

+
+
+

{post.frontmatter.title}

-

+

{post.frontmatter.description}

-
+
{formatDate(post.frontmatter.date)} // {post.readingTime} MIN @@ -105,7 +107,7 @@ export default async function HomePage() {
[ACCESEAZĂ] >> @@ -118,7 +120,7 @@ export default async function HomePage() {
[VEZI TOATE ARTICOLELE] >> @@ -128,41 +130,41 @@ export default async function HomePage() {

{/* Stats Section - from worktree-agent-1 */} -
+
-
-

+

+

SYSTEM STATISTICS // DATABASE METRICS

-

+

> METRICI_

-
-
+
+
{allPosts.length}+
-

+

ARTICOLE PUBLICATE

-
-
+
+
50K+
-

+

CITITORI LUNARI

-
-
+
+
99%
-

+

SATISFACȚIE

@@ -171,32 +173,32 @@ export default async function HomePage() {
{/* Newsletter CTA - from worktree-agent-1 */} -
+
-
-

+

+

NEWSLETTER SUBSCRIPTION

-

+

> RĂMÂI LA CURENT_

-

+

Primește cele mai noi articole direct în inbox

-
+
-

+

// Fără spam. Dezabonare oricând.

diff --git a/components/blog/MarkdownRenderer.tsx b/components/blog/markdown-renderer.tsx similarity index 100% rename from components/blog/MarkdownRenderer.tsx rename to components/blog/markdown-renderer.tsx diff --git a/components/layout/Breadcrumbs.tsx b/components/layout/Breadcrumbs.tsx index 1dfd000..bd99998 100644 --- a/components/layout/Breadcrumbs.tsx +++ b/components/layout/Breadcrumbs.tsx @@ -3,7 +3,7 @@ import Link from 'next/link'; import { usePathname } from 'next/navigation'; import { Fragment } from 'react'; -import { BreadcrumbsSchema } from './BreadcrumbsSchema'; +import { BreadcrumbsSchema } from './breadcrumbs-schema'; interface BreadcrumbItem { label: string; diff --git a/components/layout/BreadcrumbsSchema.tsx b/components/layout/breadcrumbs-schema.tsx similarity index 100% rename from components/layout/BreadcrumbsSchema.tsx rename to components/layout/breadcrumbs-schema.tsx diff --git a/components/theme-toggle.tsx b/components/theme-toggle.tsx new file mode 100644 index 0000000..105930c --- /dev/null +++ b/components/theme-toggle.tsx @@ -0,0 +1,70 @@ +'use client' + +import { useEffect, useState } from 'react' +import { useTheme } from 'next-themes' + +export function ThemeToggle() { + const [mounted, setMounted] = useState(false) + const { theme, setTheme } = useTheme() + const [isGlitching, setIsGlitching] = useState(false) + + useEffect(() => { + setMounted(true) + }, []) + + const toggleTheme = () => { + // Trigger glitch animation + setIsGlitching(true) + + // Trigger screen flicker + document.body.classList.add('screen-flicker') + + // Toggle theme + setTheme(theme === 'dark' ? 'light' : 'dark') + + // Remove effects after animation + setTimeout(() => { + setIsGlitching(false) + document.body.classList.remove('screen-flicker') + }, 300) + } + + if (!mounted) { + return ( + + ) + } + + return ( + + ) +} diff --git a/package-lock.json b/package-lock.json index 2979a71..60720fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "autoprefixer": "^10.4.21", "gray-matter": "^4.0.3", "next": "^16.0.1", + "next-themes": "^0.4.6", "postcss": "^8.5.6", "react": "^19.2.0", "react-dom": "^19.2.0", @@ -2984,6 +2985,16 @@ } } }, + "node_modules/next-themes": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz", + "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", diff --git a/package.json b/package.json index 5127e98..d02bb97 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "autoprefixer": "^10.4.21", "gray-matter": "^4.0.3", "next": "^16.0.1", + "next-themes": "^0.4.6", "postcss": "^8.5.6", "react": "^19.2.0", "react-dom": "^19.2.0", diff --git a/providers/providers.tsx b/providers/providers.tsx new file mode 100644 index 0000000..1ddf4dd --- /dev/null +++ b/providers/providers.tsx @@ -0,0 +1,8 @@ +'use client' + +import { ThemeProvider as NextThemesProvider } from 'next-themes' +import type { ThemeProviderProps } from 'next-themes' + +export function ThemeProvider({ children, ...props }: ThemeProviderProps) { + return {children} +} diff --git a/tailwind.config.js b/tailwind.config.js index c7c0b9f..e97e515 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,5 +1,6 @@ /** @type {import('tailwindcss').Config} */ module.exports = { + darkMode: 'class', content: [ "./pages/**/*.{js,ts,jsx,tsx,mdx}", "./components/**/*.{js,ts,jsx,tsx,mdx}", @@ -20,6 +21,65 @@ module.exports = { 800: '#075985', 900: '#0c4a6e', }, + 'dark-primary': '#18181b', + 'dark-secondary': '#0f172a', + 'dark-tertiary': '#1e293b', + 'accent': { + DEFAULT: '#164e63', + hover: '#155e75', + light: '#0e7490', + }, + 'accent-emerald': { + DEFAULT: '#064e3b', + hover: '#065f46', + }, + 'accent-teal': { + DEFAULT: '#134e4a', + hover: '#115e59', + }, + }, + animation: { + 'glitch': 'glitch 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94) both', + 'flicker': 'flicker 0.15s infinite', + 'scanline': 'scanline 8s linear infinite', + 'noise': 'noise 0.2s infinite', + }, + keyframes: { + glitch: { + '0%': { transform: 'translate(0)' }, + '20%': { transform: 'translate(-2px, 2px)' }, + '40%': { transform: 'translate(-2px, -2px)' }, + '60%': { transform: 'translate(2px, 2px)' }, + '80%': { transform: 'translate(2px, -2px)' }, + '100%': { transform: 'translate(0)' }, + }, + flicker: { + '0%, 100%': { opacity: '1' }, + '41.99%': { opacity: '1' }, + '42%': { opacity: '0' }, + '43%': { opacity: '0' }, + '43.01%': { opacity: '1' }, + '47.99%': { opacity: '1' }, + '48%': { opacity: '0' }, + '49%': { opacity: '0' }, + '49.01%': { opacity: '1' }, + }, + scanline: { + '0%': { transform: 'translateY(-100%)' }, + '100%': { transform: 'translateY(100%)' }, + }, + noise: { + '0%, 100%': { backgroundPosition: '0 0' }, + '10%': { backgroundPosition: '-5% -10%' }, + '20%': { backgroundPosition: '-15% 5%' }, + '30%': { backgroundPosition: '7% -25%' }, + '40%': { backgroundPosition: '-5% 25%' }, + '50%': { backgroundPosition: '-15% 10%' }, + '60%': { backgroundPosition: '15% 0%' }, + '70%': { backgroundPosition: '0% 15%' }, + '80%': { backgroundPosition: '3% 35%' }, + '90%': { backgroundPosition: '-10% 10%' }, + }, }, }, },