diff --git a/.gitignore b/.gitignore index 16d54bb..2bfc1c0 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,7 @@ pnpm-debug.log* # jetbrains setting folder .idea/ +.gga +diseño/ +.vscode/ + diff --git a/README.md b/README.md index ba563c6..5c0f264 100644 --- a/README.md +++ b/README.md @@ -1,85 +1,52 @@ -# Personal Portfolio +# Personal Portfolio - Itziar ZG -A framework-free, static portfolio website built with vanilla HTML, CSS, and JavaScript. +A modern, static portfolio website for AI & Automation Developer. Built with HTML, Tailwind CSS, and minimal JavaScript. ## Features -- **Zero Runtime Dependencies**: No JavaScript framework required -- **Multi-language Support**: English and Spanish with instant switching -- **Dark/Light Mode**: Theme persistence with localStorage -- **Glassmorphism Design**: Modern UI with blur effects and transparency -- **Fully Responsive**: Works on all devices +- **Modern Design**: Glassmorphism, gradients, fluid animations +- **Responsive**: Mobile-first design with Tailwind CSS +- **Fast Loading**: No build step, CDN-powered Tailwind - **SEO Optimized**: Semantic HTML5 markup -- **Fast Loading**: Minimal bundle size +- **Smooth Navigation**: Scroll-to-section anchors +- **Professional Layout**: Hero, About, Projects, Tech Stack, Contact sections ## Tech Stack - **HTML5**: Semantic markup -- **CSS3**: Custom properties, flexbox, grid, animations -- **Vanilla JavaScript**: ES6+ modules, classes, localStorage -- **Google Fonts**: Space Grotesk typography +- **Tailwind CSS**: Utility-first styling via CDN +- **Vanilla JavaScript**: Smooth scrolling, minimal interactions +- **Google Fonts**: Space Grotesk & Instrument Serif - **Material Symbols**: Icon system -## Development -### Prerequisites +## Getting Started -- Node.js (for dev server only) -- Any modern web browser - -### Setup +Simply open `index.html` in your browser. No build step required. ```bash -# Install dev dependencies (optional) -npm install - -# Start development server -npm run dev - -# Or simply open index.html in your browser +# Or use a local server +python -m http.server 8000 +# Then visit http://localhost:8000 ``` -### Project Structure +## Project Structure ``` -├── index.html # Main HTML file -├── styles/ -│ └── main.css # Complete stylesheet -├── js/ -│ └── main.js # JavaScript functionality -├── public/ # Static assets -└── package.json # Dev dependencies only +├── index.html # Main portfolio page (loads CSS and JS) +├── css/ # Site-wide styles (e.g., styles.css) +├── js/ # Site scripts (e.g., main.js) +├── diseño/ # Original design files from Stitch +└── README.md # This file ``` -## Features Implementation +## Sections -### Language Switching - -- Translations stored in JavaScript objects -- No page reload required -- Preference saved in localStorage -- Dynamic content rendering - -### Theme Toggle - -- CSS custom properties for theming -- System preference detection -- Smooth transitions -- Icon updates based on current theme - -### Performance - -- No build step required -- Minimal HTTP requests -- Optimized CSS with custom properties -- Efficient DOM manipulation - -## Browser Support - -- Chrome 60+ -- Firefox 55+ -- Safari 12+ -- Edge 79+ +- **Hero**: Attention-grabbing intro with CTA buttons +- **About**: Professional background and capabilities +- **Selected Works**: 3 featured projects with tech tags +- **Tech Stack**: Technologies and tools used +- **Contact**: Call-to-action footer with email and social links ## License diff --git a/css/styles.css b/css/styles.css new file mode 100644 index 0000000..ac44f2d --- /dev/null +++ b/css/styles.css @@ -0,0 +1,37 @@ +/* Glass Morphism Effect */ +.glass { + background: rgba(255, 255, 255, 0.4); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + border: 1px solid rgba(255, 255, 255, 0.3); +} + +.dark .glass { + background: rgba(30, 20, 40, 0.4); + border: 1px solid rgba(255, 255, 255, 0.1); +} + +/* Iridescent Background Gradient */ +.iridescent-bg { + background: + radial-gradient( + circle at 0% 0%, + rgba(140, 43, 238, 0.15) 0%, + transparent 50% + ), + radial-gradient( + circle at 100% 100%, + rgba(255, 182, 255, 0.2) 0%, + transparent 50% + ), + radial-gradient( + circle at 50% 50%, + rgba(140, 43, 238, 0.05) 0%, + transparent 100% + ); +} + +/* Fluid Blob Shapes */ +.fluid-shape { + border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; +} diff --git a/index.html b/index.html index 151a230..d886fe8 100644 --- a/index.html +++ b/index.html @@ -1,212 +1,954 @@ - + - - - - Itziar ZG - Vanguard CV + + + Itziar ZG | AI & Automation Developer + + - - - - + - - - - - - - - - - - - - - - - - - - - + + auto_awesome + + +

+ Itziar ZG +

+ + +
+ + +
+ - - +
+
+ + + + + Disponible para nuevos proyectos +
+

+ Arquitecta de + IA + & Automatización +

+

+ Construyo automatizaciones y agentes de IA que conectan + herramientas, procesan información y transforman flujos de trabajo + en sistemas inteligentes. +

+
+ + +
+ +
+
+
+
+
+ + +
+
+
+

+ Sobre mí +

+

+ Ingeniera de telecomunicaciones y desarrolladora especializada + en automatización de procesos, integración de APIs y creación de + agentes basados en inteligencia artificial. Construyo sistemas + que conectan herramientas, procesan información y crean flujos + automatizados que reducen trabajo manual. +

+
+
+ router +

Automatización

+

+ Optimización de procesos complejos con workflows + inteligentes. +

+
+
+ psychology +

Agentes IA

+

+ LLMs y flujos generativos autónomos. +

+
+
+ hub +

+ Integración APIs +

+

+ Conexión fluida entre servicios SaaS. +

+
+
+ terminal +

Web Moderna

+

+ Desarrollo Frontend con Next.js y React. +

+
+
+
+
+
+ + +
+
+
+
+

+ Selected Works +

+

+ Proyectos destacados en automatización inteligente. +

+
+ +
+
+ +
+
+ Visualization of an AI neural network and data pipeline +
+
+
+

+ AI Knowledge Pipeline +

+

+ Sistema automatizado capaz de recibir audio, PDFs, vídeos o + texto. Transcribe el contenido, lo resume mediante IA y lo + almacena estructuradamente para su reutilización. +

+
+ n8n + Supabase + APIs IA +
+ +
+
+ + +
+
+ High-end modern kitchen with minimalist design +
+
+
+

+ ChefGPT +

+

+ Agente conversacional que sugiere recetas en función de los + ingredientes disponibles. Integra Telegram, Google Sheets y + n8n para automatizar consultas de inventario. +

+
+ Telegram + Google Sheets + n8n +
+ +
+
+ + + +
+
+
+ + +
+
+
+

+ Tech Curated Stack +

+
+
+
+ hub +
+ n8n +
+
+
+ terminal +
+ Next.js +
+
+
+ code +
+ JavaScript +
+
+
+ model_training +
+ LLMs +
+
+
+ database +
+ Supabase +
+
+
+ api +
+ APIs +
+
+
+ palette +
+ Tailwind CSS +
+
+
+ chat +
+ TypeScript +
+
+
+
+ + + - --> + + + + + + + + + + + + diff --git a/js/language-toggle.js b/js/language-toggle.js deleted file mode 100644 index 8ef8ab0..0000000 --- a/js/language-toggle.js +++ /dev/null @@ -1,20 +0,0 @@ -(function () { - const savedLang = localStorage.getItem("language") || "en"; - const htmlLang = document.documentElement.lang || "en"; - const currentLang = savedLang || htmlLang; - - window.setLanguage = function (lang) { - localStorage.setItem("language", lang); - location.reload(); - }; - - window.getCurrentLanguage = function () { - return localStorage.getItem("language") || "en"; - }; - - window.toggleLanguage = function () { - const currentLang = getCurrentLanguage(); - const newLang = currentLang === "en" ? "es" : "en"; - setLanguage(newLang); - }; -})(); diff --git a/js/main.js b/js/main.js index 69fa380..8dba210 100644 --- a/js/main.js +++ b/js/main.js @@ -1,280 +1,130 @@ -// Translation data -const translations = { - en: { - hero: { - title: "Vanguard Designer", - subtitle: "Crafting Digital Excellence" - }, - about: { - title: "About Me", - description: "A sophisticated designer specializing in high-end digital experiences with a focus on dark aesthetics, glassmorphism, and modern typography. Transforming complex problems into elegant, intuitive interfaces.", - downloadCV: "Download CV", - contact: "Contact" - }, - skills: { - title: "Core Expertise" - }, - projects: { - title: "Latest Work", - viewAll: "View All" - }, - experience: { - title: "Experience" - } - }, - es: { - hero: { - title: "Diseñadora Vanguardista", - subtitle: "Creando Excelencia Digital" - }, - about: { - title: "Sobre Mí", - description: "Una diseñadora sofisticada especializada en experiencias digitales de alta gama con un enfoque en estéticas oscuras, glassmorfismo y tipografía moderna. Transformando problemas complejos en interfaces elegantes e intuitivas.", - downloadCV: "Descargar CV", - contact: "Contacto" - }, - skills: { - title: "Competencias Clave" - }, - projects: { - title: "Trabajos Recientes", - viewAll: "Ver Todos" - }, - experience: { - title: "Experiencia" - } - } -}; +// ============================================ +// Theme Toggle - Dark/Light Mode +// ============================================ -// Projects data -const projects = [ - { - id: 1, - title: { - en: 'Luminary App', - es: 'App Luminary' - }, - description: { - en: 'A fintech dashboard redesign for high-net-worth individuals.', - es: 'Un rediseño de dashboard fintech para individuos de alto patrimonio.' - }, - url: 'luminary-project.co', - image: 'https://lh3.googleusercontent.com/aida-public/AB6AXuDuiRGNBP07ZrmaH7F-Q5XCG8XcmSnVisQQn-Tq4zMmt4oxFQYhnVmEZ16pqAEXpXmPJ29Xc42MlLHJHMla4Q1dMWqm2apfbWMmKQW4gH3fD35Piy_YM1xG2DEHO_es1DqVWQ1GzgmjaRrLehiCzLynVjvtlIg7p5NL8kDBwKBkPqk_nYfYK7jv1lDBrVN4AZ1Hz_j_sRfkerkDWmP2oaTSQh0gN2DLNyN-r34Nda4Dp3GWFWRjZSlivobGKj0mj0eg7QK_Fqcp5GU' - }, - { - id: 2, - title: { - en: 'Ether OS', - es: 'Sistema Ether' - }, - description: { - en: 'A minimalist operating system concept based on spatial UI.', - es: 'Un concepto de sistema operativo minimalista basado en UI espacial.' - }, - url: 'ether-spatial.io', - image: 'https://lh3.googleusercontent.com/aida-public/AB6AXuDvWd-Z_6rj37HlgWlrmx1VJHroq2bg6Pv0atKO0GnAF5_74-yfWaASnLWaWh5J6NiThTvt1W3avgzNI3bOpEG0GoVeYjwZxqMwZZRIiaaODFunpArG-H2otP37dkbfuWzOP_QoEWn6INmZ8YFm50k3YDvoCyZNrnv1dETjWlyg2cok9MP4IIqJLDVxp5Yi32R9BUDgxGlVWLUceUR71hTQRKQqKI9jsQPH7E0Y1OLKeCOZ1Wo-RKabzipc2Vtvmo6RtGvT2X0VoSE' - } -]; - -// Experience data -const experience = [ - { - period: '2022 - Present', - title: { - en: 'Senior UX Designer', - es: 'Diseñadora UX Senior' - }, - company: 'Studio Vanta • Remote', - description: { - en: 'Leading the design language for next-gen SaaS products and immersive web experiences.', - es: 'Liderando el lenguaje de diseño para productos SaaS de próxima generación y experiencias web inmersivas.' - }, - isActive: true, - }, - { - period: '2020 - 2022', - title: { - en: 'Product Designer', - es: 'Diseñadora de Producto' - }, - company: 'Flow Digital • Madrid', - description: { - en: 'Conceptualized and launched 4 mobile applications with over 1M combined downloads.', - es: 'Conceptualicé y lancé 4 aplicaciones móviles con más de 1M de descargas combinadas.' - }, - isActive: false, - } -]; - -// Theme Management -class ThemeManager { - constructor() { - this.theme = localStorage.getItem('theme') || this.getSystemPreference(); - this.init(); - } - - getSystemPreference() { - return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; - } - - init() { - this.applyTheme(); - this.setupEventListeners(); - } - - applyTheme() { - document.documentElement.classList.toggle('dark', this.theme === 'dark'); - this.updateThemeIcon(); - } - - updateThemeIcon() { - const icon = document.querySelector('#theme-toggle .material-symbols-outlined'); - if (icon) { - icon.textContent = this.theme === 'dark' ? 'light_mode' : 'dark_mode'; - } - } - - toggle() { - this.theme = this.theme === 'dark' ? 'light' : 'dark'; - localStorage.setItem('theme', this.theme); - this.applyTheme(); - } - - setupEventListeners() { - const themeToggle = document.getElementById('theme-toggle'); - if (themeToggle) { - themeToggle.addEventListener('click', () => this.toggle()); - } - } +/** + * Initialize theme on page load + * Checks localStorage for saved preference, falls back to light mode + */ +function initTheme() { + const savedTheme = localStorage.getItem("theme") || "light"; + if (savedTheme === "dark") { + document.documentElement.classList.add("dark"); + } else { + document.documentElement.classList.remove("dark"); + } } -// Language Management -class LanguageManager { - constructor() { - this.currentLang = localStorage.getItem('language') || 'en'; - this.init(); - } - - init() { - this.applyLanguage(); - this.setupEventListeners(); - this.renderDynamicContent(); - } - - applyLanguage() { - document.documentElement.lang = this.currentLang; - - // Update all elements with data-i18n attribute - document.querySelectorAll('[data-i18n]').forEach(element => { - const key = element.getAttribute('data-i18n'); - const translation = this.getTranslation(key); - if (translation) { - element.textContent = translation; - } - }); - } - - getTranslation(key) { - const keys = key.split('.'); - let value = translations[this.currentLang]; - - for (const k of keys) { - value = value?.[k]; - } - - return value || key; - } - - toggle() { - this.currentLang = this.currentLang === 'en' ? 'es' : 'en'; - localStorage.setItem('language', this.currentLang); - this.applyLanguage(); - this.renderDynamicContent(); - } - - renderDynamicContent() { - this.renderProjects(); - this.renderExperience(); - } - - renderProjects() { - const container = document.getElementById('projects-container'); - if (!container) return; - - container.innerHTML = projects.map(project => ` -
-
-
-

${project.title[this.currentLang]}

-

${project.description[this.currentLang]}

-
- link - ${project.url} -
-
-
- `).join(''); - } - - renderExperience() { - const container = document.getElementById('experience-container'); - if (!container) return; - - container.innerHTML = ` -
- ${experience.map(job => ` -
-
-
-
- ${job.period} -

${job.title[this.currentLang]}

-

${job.company}

-

${job.description[this.currentLang]}

-
- `).join('')} -
- `; - } - - setupEventListeners() { - const languageToggle = document.getElementById('language-toggle'); - if (languageToggle) { - languageToggle.addEventListener('click', () => this.toggle()); - } - } +/** + * Toggle between dark and light theme + * Saves preference to localStorage + */ +function toggleTheme() { + const html = document.documentElement; + if (html.classList.contains("dark")) { + html.classList.remove("dark"); + localStorage.setItem("theme", "light"); + } else { + html.classList.add("dark"); + localStorage.setItem("theme", "dark"); + } } -// Initialize everything when DOM is ready -document.addEventListener('DOMContentLoaded', () => { - new ThemeManager(); - new LanguageManager(); - - // Add smooth scrolling - document.querySelectorAll('a[href^="#"]').forEach(anchor => { - anchor.addEventListener('click', function (e) { - e.preventDefault(); - const target = document.querySelector(this.getAttribute('href')); - if (target) { - target.scrollIntoView({ behavior: 'smooth' }); - } - }); - }); - - // Add fade-in animation to sections - const observer = new IntersectionObserver((entries) => { - entries.forEach(entry => { - if (entry.isIntersecting) { - entry.target.classList.add('animate-fade-in'); - } - }); - }, { threshold: 0.1 }); - - document.querySelectorAll('section').forEach(section => { - observer.observe(section); +// ============================================ +// Smooth Scrolling +// ============================================ + +/** + * Scroll to projects section + */ +function scrollToProjects() { + const projectsSection = document.getElementById("projects"); + if (projectsSection) { + projectsSection.scrollIntoView({ behavior: "smooth" }); + } +} + +/** + * Scroll to contact section + */ +function scrollToContact() { + const contactSection = document.getElementById("contact"); + if (contactSection) { + contactSection.scrollIntoView({ behavior: "smooth" }); + } +} + +// ============================================ +// Modal Management +// ============================================ + +/** Element that had focus before a modal was opened */ +let _modalPreviousFocus = null; + +/** + * Open modal by project ID. + * Saves the currently focused element and moves focus into the modal. + * @param {string} projectId - The project identifier + */ +function openModal(projectId) { + const modal = document.getElementById(projectId + "-modal"); + if (modal) { + _modalPreviousFocus = document.activeElement; + modal.classList.remove("hidden"); + document.body.style.overflow = "hidden"; + + // Move focus to the first focusable element inside the modal + const focusable = modal.querySelectorAll( + 'button, [href], input, select, textarea, [contenteditable="true"], [tabindex]:not([tabindex="-1"])' + ); + if (focusable.length > 0) { + focusable[0].focus(); + } else { + modal.setAttribute("tabindex", "-1"); + modal.focus(); + } + } +} + +/** + * Close modal by project ID. + * Restores focus to the element that was focused before the modal opened. + * @param {string} projectId - The project identifier + */ +function closeModal(projectId) { + const modal = document.getElementById(projectId + "-modal"); + if (modal) { + modal.classList.add("hidden"); + document.body.style.overflow = "auto"; + + // Return focus to the element that triggered the modal + if (_modalPreviousFocus) { + _modalPreviousFocus.focus(); + _modalPreviousFocus = null; + } + } +} + +// ============================================ +// Event Listeners +// ============================================ + +/** + * Close modal when ESC key is pressed + */ +document.addEventListener("keydown", function (event) { + if (event.key === "Escape") { + const modals = document.querySelectorAll( + '[id$="-modal"]:not(.hidden)' + ); + modals.forEach((modal) => { + const projectId = modal.id.replace("-modal", ""); + closeModal(projectId); }); + } }); + +/** + * Initialize theme as early as possible + */ +initTheme(); diff --git a/js/theme-toggle.js b/js/theme-toggle.js deleted file mode 100644 index c9b653a..0000000 --- a/js/theme-toggle.js +++ /dev/null @@ -1,15 +0,0 @@ -(function() { - const theme = localStorage.getItem('theme'); - const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; - const initialTheme = theme || (systemPrefersDark ? 'dark' : 'light'); - - document.documentElement.classList.toggle('dark', initialTheme === 'dark'); - - window.toggleTheme = function() { - const currentTheme = document.documentElement.classList.contains('dark') ? 'dark' : 'light'; - const newTheme = currentTheme === 'dark' ? 'light' : 'dark'; - - document.documentElement.classList.toggle('dark'); - localStorage.setItem('theme', newTheme); - }; -})(); diff --git a/styles/main.css b/styles/main.css deleted file mode 100644 index d7d795b..0000000 --- a/styles/main.css +++ /dev/null @@ -1,552 +0,0 @@ -/* Reset and Base Styles */ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -/* CSS Custom Properties for Theming */ -:root { - --primary: #8c2bee; - --primary-light: #d4a5ff; - --background-light: #f7f6f8; - --background-dark: #0d0614; - --surface-light: #ffffff; - --surface-dark: #1a0f2e; - --text-primary-light: #0f172a; - --text-primary-dark: #f8fafc; - --text-secondary-light: #64748b; - --text-secondary-dark: #94a3b8; - --border-light: #e2e8f0; - --border-dark: #334155; - --glass-bg-light: rgba(140, 43, 238, 0.05); - --glass-bg-dark: rgba(20, 10, 30, 0.6); - --glass-border-light: rgba(140, 43, 238, 0.1); - --glass-border-dark: rgba(140, 43, 238, 0.2); -} - -/* Typography */ -body { - font-family: 'Space Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; - line-height: 1.6; - min-height: max(884px, 100dvh); -} - -.font-display { - font-family: 'Space Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; -} - -/* Material Symbols */ -.material-symbols-outlined { - font-variation-settings: - 'FILL' 0, - 'wght' 400, - 'GRAD' 0, - 'opsz' 24; -} - -.material-symbols-outlined.fill-1 { - font-variation-settings: - 'FILL' 1, - 'wght' 400, - 'GRAD' 0, - 'opsz' 24; -} - -/* Layout */ -.sticky { - position: sticky; -} - -.top-0 { - top: 0; -} - -.z-50 { - z-index: 50; -} - -.flex { - display: flex; -} - -.items-center { - align-items: center; -} - -.justify-between { - justify-content: space-between; -} - -.justify-center { - justify-content: center; -} - -.justify-end { - justify-content: flex-end; -} - -.gap-1 { gap: 0.25rem; } -.gap-2 { gap: 0.5rem; } -.gap-4 { gap: 1rem; } -.gap-6 { gap: 1.5rem; } - -/* Spacing */ -.p-1 { padding: 0.25rem; } -.p-2 { padding: 0.5rem; } -.p-3 { padding: 0.75rem; } -.p-4 { padding: 1rem; } -.p-5 { padding: 1.25rem; } -.p-6 { padding: 1.5rem; } - -.px-1 { padding-left: 0.25rem; padding-right: 0.25rem; } -.px-2 { padding-left: 0.5rem; padding-right: 0.5rem; } -.px-3 { padding-left: 0.75rem; padding-right: 0.75rem; } -.px-6 { padding-left: 1.5rem; padding-right: 1.5rem; } - -.py-1 { padding-top: 0.25rem; padding-bottom: 0.25rem; } -.py-3 { padding-top: 0.75rem; padding-bottom: 0.75rem; } - -.pt-10 { padding-top: 2.5rem; } -.pt-16 { padding-top: 4rem; } -.pb-16 { padding-bottom: 4rem; } -.pb-24 { padding-bottom: 6rem; } - -.mb-1 { margin-bottom: 0.25rem; } -.mb-2 { margin-bottom: 0.5rem; } -.mb-4 { margin-bottom: 1rem; } -.mb-6 { margin-bottom: 1.5rem; } -.mb-8 { margin-bottom: 2rem; } -.mb-12 { margin-bottom: 3rem; } - -.mt-2 { margin-top: 0.5rem; } -.mt-4 { margin-top: 1rem; } - -.ml-8 { margin-left: 2rem; } - -/* Flexbox */ -.flex-col { - flex-direction: column; -} - -.flex-1 { - flex: 1; -} - -/* Grid */ -.grid { - display: grid; -} - -.grid-cols-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); -} - -/* Positioning */ -.relative { - position: relative; -} - -.absolute { - position: absolute; -} - -.fixed { - position: fixed; -} - -.top-0 { top: 0; } -.right-0 { right: 0; } -.bottom-0 { bottom: 0; } -.left-0 { left: 0; } -.left-1\/2 { left: 50%; } - -.-z-10 { - z-index: -10; -} - -.z-50 { - z-index: 50; -} - -.-translate-x-1\/2 { - transform: translateX(-50%); -} - -/* Sizing */ -.w-32 { width: 8rem; } -.w-48 { width: 12rem; } -.w-64 { width: 16rem; } -.w-full { width: 100%; } -.w-[90%] { width: 90%; } -.w-[95%] { width: 95%; } -.w-[88%] { width: 88%; } -.w-[82%] { width: 82%; } - -.h-32 { height: 8rem; } -.h-48 { height: 12rem; } -.h-64 { height: 16rem; } -.h-1 { height: 0.25rem; } -.h-1\.5 { height: 0.375rem; } -.h-2 { height: 0.5rem; } -.h-2\.5 { height: 0.625rem; } -.h-24 { height: 6rem; } -.h-full { height: 100%; } - -.min-h-screen { - min-height: 100vh; -} - -.max-w-md { - max-width: 28rem; -} - -/* Border Radius */ -.rounded { - border-radius: 0.25rem; -} - -.rounded-full { - border-radius: 9999px; -} - -.rounded-lg { - border-radius: 0.5rem; -} - -.rounded-xl { - border-radius: 0.75rem; -} - -/* Backgrounds */ -.bg-background-light { - background-color: var(--background-light); -} - -.bg-background-dark { - background-color: var(--background-dark); -} - -.bg-primary { - background-color: var(--primary); -} - -.bg-slate-800 { - background-color: #1e293b; -} - -.bg-primary\/10 { - background-color: rgba(140, 43, 238, 0.1); -} - -.bg-primary\/20 { - background-color: rgba(140, 43, 238, 0.2); -} - -.bg-purple-600\/10 { - background-color: rgba(147, 51, 234, 0.1); -} - -.bg-cover { - background-size: cover; -} - -.bg-center { - background-position: center; -} - -.bg-gradient-to-tr { - background: linear-gradient(to top right, var(--primary), var(--primary-light)); -} - -/* Glass Effects */ -.glass { - background: var(--glass-bg-light); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - border: 1px solid var(--glass-border-light); -} - -.dark .glass { - background: var(--glass-bg-light); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - border: 1px solid var(--glass-border-light); -} - -.glass-dark { - background: var(--glass-bg-dark); - backdrop-filter: blur(16px); - -webkit-backdrop-filter: blur(16px); - border: 1px solid var(--glass-border-dark); -} - -/* Borders */ -.border { - border: 1px solid; -} - -.border-2 { - border: 2px solid; -} - -.border-4 { - border: 4px solid; -} - -.border-l-4 { - border-left: 4px solid; -} - -.border-primary { - border-color: var(--primary); -} - -.border-primary\/10 { - border-color: rgba(140, 43, 238, 0.1); -} - -.border-primary\/20 { - border-color: rgba(140, 43, 238, 0.2); -} - -.border-primary\/30 { - border-color: rgba(140, 43, 238, 0.3); -} - -.border-background-dark { - border-color: var(--background-dark); -} - -/* Text Colors */ -.text-slate-900 { - color: var(--text-primary-light); -} - -.dark .text-slate-900 { - color: var(--text-primary-dark); -} - -.text-slate-100 { - color: var(--text-primary-dark); -} - -.text-slate-400 { - color: var(--text-secondary-light); -} - -.dark .text-slate-400 { - color: var(--text-secondary-dark); -} - -.text-slate-500 { - color: #64748b; -} - -.text-primary { - color: var(--primary); -} - -.text-white { - color: white; -} - -/* Typography */ -.text-xs { font-size: 0.75rem; } -.text-sm { font-size: 0.875rem; } -.text-lg { font-size: 1.125rem; } -.text-xl { font-size: 1.25rem; } -.text-2xl { font-size: 1.5rem; } -.text-3xl { font-size: 1.875rem; } -.text-4xl { font-size: 2.25rem; } - -.font-thin { font-weight: 100; } -.font-light { font-weight: 300; } -.font-normal { font-weight: 400; } -.font-medium { font-weight: 500; } -.font-semibold { font-weight: 600; } -.font-bold { font-weight: 700; } - -.tracking-tight { letter-spacing: -0.025em; } -.tracking-tighter { letter-spacing: -0.05em; } -.tracking-widest { letter-spacing: 0.1em; } -.tracking-wider { letter-spacing: 0.05em; } - -.uppercase { text-transform: uppercase; } -.lowercase { text-transform: lowercase; } - -.leading-relaxed { line-height: 1.625; } - -.text-center { text-align: center; } - -/* Effects */ -.transition-colors { - transition-property: color, background-color, border-color; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -.shadow-lg { - box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); -} - -.shadow-primary\/20 { - box-shadow: 0 10px 15px -3px rgba(140, 43, 238, 0.2), 0 4px 6px -2px rgba(140, 43, 238, 0.1); -} - -.shadow-2xl { - box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); -} - -.shadow-primary\/20 { - box-shadow: 0 25px 50px -12px rgba(140, 43, 238, 0.25); -} - -.blur-\[100px\] { - filter: blur(100px); -} - -.blur-\[80px\] { - filter: blur(80px); -} - -.overflow-hidden { - overflow: hidden; -} - -.space-y-2 > * + * { - margin-top: 0.5rem; -} - -.space-y-4 > * + * { - margin-top: 1rem; -} - -.space-y-8 > * + * { - margin-top: 2rem; -} - -.space-x-2 > * + * { - margin-left: 0.5rem; -} - -/* Hover States */ -.hover\:bg-primary\/10:hover { - background-color: rgba(140, 43, 238, 0.1); -} - -/* Group States */ -.group:hover .group-hover\:scale-105 { - transform: scale(1.05); -} - -/* Dark Mode */ -.dark { - color-scheme: dark; -} - -.dark .bg-background-light { - background-color: var(--background-dark); -} - -.dark .text-slate-900 { - color: var(--text-primary-dark); -} - -.dark .text-slate-400 { - color: var(--text-secondary-dark); -} - -/* Responsive */ -@media (min-width: 640px) { - .sm\:grid-cols-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } -} - -@media (min-width: 768px) { - .md\:grid-cols-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } -} - -@media (min-width: 1024px) { - .lg\:grid-cols-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } -} - -/* Utility Classes */ -.block { - display: block; -} - -.inline { - display: inline; -} - -.inline-block { - display: inline-block; -} - -.hidden { - display: none; -} - -.opacity-0 { opacity: 0; } -.opacity-30 { opacity: 0.3; } -.opacity-100 { opacity: 1; } - -.cursor-pointer { - cursor: pointer; -} - -.select-none { - user-select: none; -} - -.pointer-events-none { - pointer-events: none; -} - -/* Focus States */ -.focus\:outline-none:focus { - outline: 2px solid transparent; - outline-offset: 2px; -} - -.focus\:ring-2:focus { - box-shadow: 0 0 0 2px var(--primary); -} - -/* Animation */ -@keyframes fadeIn { - from { opacity: 0; transform: translateY(10px); } - to { opacity: 1; transform: translateY(0); } -} - -.animate-fade-in { - animation: fadeIn 0.5s ease-out; -} - -/* Custom scrollbar */ -::-webkit-scrollbar { - width: 8px; -} - -::-webkit-scrollbar-track { - background: var(--background-light); -} - -.dark ::-webkit-scrollbar-track { - background: var(--background-dark); -} - -::-webkit-scrollbar-thumb { - background: var(--primary); - border-radius: 4px; -} - -::-webkit-scrollbar-thumb:hover { - background: var(--primary-light); -}