diff --git a/.gitignore b/.gitignore index 216796c..6329410 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,6 @@ coverage.out *.coverprofile .claude playwright.config.js + +# Test artifacts +tests/screenshots/ diff --git a/static/css/01-foundation/_reset.css b/static/css/01-foundation/_reset.css new file mode 100644 index 0000000..5e8f351 --- /dev/null +++ b/static/css/01-foundation/_reset.css @@ -0,0 +1,36 @@ +/* ============================================================================ + CSS RESET - Normalize & Base Styles + ============================================================================ */ + +/* Box sizing reset */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +/* Body base */ +body { + background-color: var(--page-bg); + background-image: + linear-gradient(90deg, rgba(0, 0, 0, 0.05) 1px, transparent 1px), + linear-gradient(180deg, rgba(0, 0, 0, 0.05) 1px, transparent 1px), + linear-gradient(90deg, rgba(0, 0, 0, 0.02) 1px, transparent 1px), + linear-gradient(180deg, rgba(0, 0, 0, 0.02) 1px, transparent 1px); + background-size: 50px 50px, 50px 50px, 10px 10px, 10px 10px; + background-attachment: fixed; + overflow-x: auto; +} + +/* Smooth scrolling */ +html { + scroll-behavior: smooth; + scroll-padding-top: 70px; /* Account for fixed header */ +} + +/* Ensure Iconify icons display properly */ +.iconify, +iconify-icon { + display: inline-block; + vertical-align: middle; +} diff --git a/static/css/01-foundation/_themes.css b/static/css/01-foundation/_themes.css new file mode 100644 index 0000000..431b44b --- /dev/null +++ b/static/css/01-foundation/_themes.css @@ -0,0 +1,285 @@ +/* ============================================================================== + COLOR THEME SYSTEM + ============================================================================== */ +/* + IMPORTANT: This is the COLOR theme system (light/dark/auto) + This is SEPARATE from the LAYOUT theme (.theme-clean) + + - COLOR theme: Controls backgrounds, text colors, shadows + - LAYOUT theme (.theme-clean): Controls sidebars, layout structure + + Both systems work independently and can be combined. +*/ + +/* ============================================================================== + LIGHT THEME (DEFAULT) + ============================================================================== */ +:root { + /* Page Background - Softer version of dark theme */ + --page-bg: #b8bbbe; + + /* Paper/Card Backgrounds */ + --paper-bg: #ffffff; + --paper-secondary-bg: #f5f5f5; + + /* Text Colors */ + --text-primary: #1a1a1a; + --text-secondary: #333333; + --text-muted: #666666; + --text-light: #999999; + + /* Action Bar & Navigation */ + --action-bar-bg: #2b2b2b; + --action-bar-text: #ffffff; + --action-bar-text-muted: rgba(255, 255, 255, 0.85); + + /* Borders & Dividers */ + --border-color: #333333; + --border-light: #e0e0e0; + + /* Shadows */ + --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1); + --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.15); + --shadow-lg: 2px 2px 9px rgba(0, 0, 0, 0.5); + + /* Interactive Elements */ + --button-bg: transparent; + --button-bg-hover: rgba(0, 0, 0, 0.05); + --button-bg-active: rgba(0, 0, 0, 0.1); + + /* Accent Colors (unchanged in dark mode) */ + --accent-blue: #0066cc; + --accent-green: #27ae60; + + /* Sidebar (for non-clean theme) */ + --sidebar-bg: #d1d4d2; + + /* Legacy CV content variables - theme-aware overrides */ + --text-dark: #1a1a1a; /* Dark text for light background */ + --text-gray: #333333; /* Secondary text for light background */ +} + +/* ============================================================================== + DARK THEME + ============================================================================== */ +[data-color-theme="dark"] { + /* Page Background - Original background */ + --page-bg: rgb(82, 86, 89); + + /* Paper/Card Backgrounds */ + --paper-bg: #1a1a1a; + --paper-secondary-bg: #2a2a2a; + + /* Text Colors */ + --text-primary: #e0e0e0; + --text-secondary: #d0d0d0; + --text-muted: #b0b0b0; + --text-light: #808080; + + /* Action Bar & Navigation */ + --action-bar-bg: #1a1a1a; + --action-bar-text: #e0e0e0; + --action-bar-text-muted: rgba(224, 224, 224, 0.85); + + /* Borders & Dividers */ + --border-color: #404040; + --border-light: #333333; + + /* Shadows */ + --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.3); + --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.4); + --shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.6); + + /* Interactive Elements */ + --button-bg: transparent; + --button-bg-hover: rgba(255, 255, 255, 0.05); + --button-bg-active: rgba(255, 255, 255, 0.1); + + /* Accent Colors - slightly brighter in dark mode */ + --accent-blue: #3399ff; + --accent-green: #2ecc71; + + /* Sidebar (for non-clean theme) */ + --sidebar-bg: #2a2a2a; + + /* Legacy CV content variables - theme-aware overrides */ + --text-dark: #e0e0e0; /* Light text for dark background */ + --text-gray: #d0d0d0; /* Secondary text for dark background */ +} + +/* ============================================================================== + AUTO THEME - Follows System Preference + ============================================================================== */ +@media (prefers-color-scheme: dark) { + [data-color-theme="auto"] { + /* Page Background - Original background */ + --page-bg: rgb(82, 86, 89); + + /* Paper/Card Backgrounds */ + --paper-bg: #1a1a1a; + --paper-secondary-bg: #2a2a2a; + + /* Text Colors */ + --text-primary: #e0e0e0; + --text-secondary: #d0d0d0; + --text-muted: #b0b0b0; + --text-light: #808080; + + /* Action Bar & Navigation */ + --action-bar-bg: #1a1a1a; + --action-bar-text: #e0e0e0; + --action-bar-text-muted: rgba(224, 224, 224, 0.85); + + /* Borders & Dividers */ + --border-color: #404040; + --border-light: #333333; + + /* Shadows */ + --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.3); + --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.4); + --shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.6); + + /* Interactive Elements */ + --button-bg: transparent; + --button-bg-hover: rgba(255, 255, 255, 0.05); + --button-bg-active: rgba(255, 255, 255, 0.1); + + /* Accent Colors - slightly brighter in dark mode */ + --accent-blue: #3399ff; + --accent-green: #2ecc71; + + /* Sidebar (for non-clean theme) */ + --sidebar-bg: #2a2a2a; + + /* Legacy CV content variables - theme-aware overrides */ + --text-dark: #e0e0e0; /* Light text for dark background */ + --text-gray: #d0d0d0; /* Secondary text for dark background */ + } +} + +/* ============================================================================== + THEME SWITCHER BUTTON STYLES - Dynamic colors based on theme mode + ============================================================================== */ +.color-theme-switcher { + position: fixed; + bottom: 14rem; /* Middle position - between print (18rem) and shortcuts (10rem) */ + left: 2rem; + width: 50px; + height: 50px; + background: var(--black-bar); + color: white; + border: none; + border-radius: 50%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + transition: all 0.3s ease; + z-index: 999; + opacity: 0.6; +} + +/* Dynamic colors ONLY on hover based on active theme mode */ +.color-theme-switcher:hover[data-theme-mode="light"] { + background: #d4b200 !important; /* Bright sun yellow (gold) for light mode */ +} + +.color-theme-switcher:hover[data-theme-mode="dark"] { + background: #013c77 !important; /* Dark nighty blue for dark mode */ +} + +.color-theme-switcher:hover[data-theme-mode="auto"] { + background: #9b59b6 !important; /* Purple for auto mode (mix of both) */ +} + +.color-theme-switcher:hover { + opacity: 1 !important; + transform: translateY(-3px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); +} + +/* At-bottom state - dynamic colors based on theme mode (matches hover) */ +.color-theme-switcher.at-bottom[data-theme-mode="light"] { + opacity: 1; + background: #d4b200 !important; /* Bright sun yellow (gold) for light mode */ +} + +.color-theme-switcher.at-bottom[data-theme-mode="dark"] { + opacity: 1; + background: #013c77 !important; /* Dark nighty blue for dark mode */ +} + +.color-theme-switcher.at-bottom[data-theme-mode="auto"] { + opacity: 1; + background: #9b59b6 !important; /* Purple for auto mode */ +} + +.color-theme-switcher iconify-icon { + color: white !important; + transition: color 0.3s ease; +} + +.color-theme-switcher:hover iconify-icon { + color: white !important; +} + +/* Hide the internal theme buttons - we'll cycle through on click */ +.theme-option-btn { + display: none; +} + +/* ============================================================================== + ICON COLOR PRESERVATION + ============================================================================== */ +/* Ensure all iconify icons keep their intended colors across themes */ + +/* Section icons - keep their brand colors */ +.section-icon iconify-icon, +.project-icon iconify-icon, +.course-icon iconify-icon, +.default-project-icon iconify-icon { + color: inherit !important; +} + +/* Toggle switch icons - keep their state-specific colors */ +/* Note: Already defined in main.css with !important - just ensure they're not overridden */ + +/* Hamburger menu and site icons */ +.site-icon iconify-icon, +.site-icon-mobile iconify-icon { + color: white !important; +} + +/* CV content icons */ +.cv-paper iconify-icon { + color: inherit !important; +} + +/* Error toast icon */ +.error-icon iconify-icon { + color: #dc3545 !important; +} + +/* Mobile adjustments */ +@media (max-width: 900px) { + .color-theme-switcher { + position: fixed !important; + bottom: 1.5rem !important; + left: auto !important; + right: auto !important; + width: 50px !important; + height: 50px !important; + opacity: 0.7 !important; + transform: none !important; + /* Position before info button: 5 buttons total */ + /* Download, Print, Shortcuts, Theme, Info */ + /* Total width: 5 * 50px + 4 * 10px = 290px */ + left: calc(50% + 35px) !important; /* Fourth button */ + } + + .color-theme-switcher:hover { + opacity: 1 !important; + transform: translateY(-3px) !important; + } +} diff --git a/static/css/01-foundation/_typography.css b/static/css/01-foundation/_typography.css new file mode 100644 index 0000000..71bd9aa --- /dev/null +++ b/static/css/01-foundation/_typography.css @@ -0,0 +1,28 @@ +/* ============================================================================ + TYPOGRAPHY - Fonts & Text Styles + ============================================================================ */ + +/* Font Imports */ +@import url('https://fonts.googleapis.com/css2?family=Quicksand:wght@400;500;600;700&family=Source+Sans+Pro:wght@400;600&family=Inter:wght@400;500;600;700&display=swap'); + +/* Base Typography */ +body { + font-family: 'Quicksand', 'Source Sans Pro', -apple-system, system-ui, sans-serif; + color: var(--text-secondary); + line-height: 1.5; + font-size: 16px; + font-weight: 400; + font-smoothing: antialiased; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* Links */ +a { + color: var(--accent-blue); + text-decoration: none; + + &:hover { + text-decoration: underline; + } +} diff --git a/static/css/01-foundation/_variables.css b/static/css/01-foundation/_variables.css new file mode 100644 index 0000000..0846930 --- /dev/null +++ b/static/css/01-foundation/_variables.css @@ -0,0 +1,55 @@ +/* ============================================================================ + CSS CUSTOM PROPERTIES - Design Tokens + ============================================================================ */ + +:root { + /* Brand Colors */ + --bg-gray: rgb(82, 86, 89); + --sidebar-gray: #d1d4d2; + --black-bar: #2b2b2b; + --paper-white: #ffffff; + --text-dark: rgb(0, 0, 0); + --text-gray: rgb(51, 51, 51); + --accent-blue: #0066cc; + --border-gray: #dddddd; + + /* Theme System - These get overridden by color-theme.css */ + /* Page Background */ + --page-bg: #b8bbbe; + + /* Paper/Card Backgrounds */ + --paper-bg: #ffffff; + --paper-secondary-bg: #f5f5f5; + + /* Text Colors */ + --text-primary: #1a1a1a; + --text-secondary: #333333; + --text-muted: #666666; + --text-light: #999999; + + /* Action Bar & Navigation */ + --action-bar-bg: #2b2b2b; + --action-bar-text: #ffffff; + --action-bar-text-muted: rgba(255, 255, 255, 0.85); + + /* Borders & Dividers */ + --border-color: #333333; + --border-light: #e0e0e0; + + /* Shadows */ + --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1); + --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.15); + --shadow-lg: 2px 2px 9px rgba(0, 0, 0, 0.5); + + /* Interactive Elements */ + --button-bg: transparent; + --button-bg-hover: rgba(0, 0, 0, 0.05); + --button-bg-active: rgba(0, 0, 0, 0.1); + + /* Accent Colors */ + --accent-blue: #0066cc; + --accent-green: #27ae60; + + /* Sidebar */ + --sidebar-bg: #d1d4d2; +} diff --git a/static/css/02-layout/_container.css b/static/css/02-layout/_container.css new file mode 100644 index 0000000..ca8015d --- /dev/null +++ b/static/css/02-layout/_container.css @@ -0,0 +1,58 @@ +/* ============================================================================ + CV CONTAINER & ZOOM WRAPPER + ============================================================================ */ + +/* Zoom Wrapper - wraps cv-container for zoom functionality */ +.zoom-wrapper { + /* CSS zoom property changes actual layout space (not just visual) */ + /* This allows footer to naturally position right after zoomed content */ +} + +/* Main CV Container */ +.cv-container { + width: 100%; + max-width: 100%; /* Full width to accommodate pages */ + margin: 0 auto; + padding: 20px 0 0 0; /* Top padding to prevent sticky action bar overlap */ + display: block; + + /* Clean theme - no sidebars, centered content */ + &.theme-clean { + padding: 20px 0 0 0; + transition: all 0.3s ease-in-out; + + .cv-page { + box-shadow: var(--shadow-lg); + border: 1px solid var(--border-color); + margin: 0 auto; + max-width: 900px; + transition: all 0.3s ease-in-out; + } + + .cv-sidebar, + .cv-title-badges-header, + .cv-footer { + display: none !important; + animation: fadeOutShrink 0.3s ease-in-out; + } + + .page-content { + grid-template-columns: 1fr !important; + transition: grid-template-columns 0.3s ease-in-out; + } + + .cv-main { + grid-column: 1 !important; + padding: 2rem 3rem!important; + transition: all 0.3s ease-in-out; + } + } +} + +/* Animate sidebar, header, footer when hiding/showing */ +.cv-sidebar, +.cv-title-badges-header, +.cv-footer { + overflow: hidden; + transition: all 0.3s ease-in-out; +} diff --git a/static/css/02-layout/_grid.css b/static/css/02-layout/_grid.css new file mode 100644 index 0000000..3ab636e --- /dev/null +++ b/static/css/02-layout/_grid.css @@ -0,0 +1,38 @@ +/* ============================================================================ + GRID LAYOUT - Page Content Grid + ============================================================================ */ + +/* Professional Title Badges - Spans Both Columns */ +.cv-title-badges-header { + grid-column: 1 / -1; /* Span all columns */ + background: #303030 !important; /* Elegant dark gray */ + padding: 10px 20px; + display: flex; + flex-wrap: wrap; + justify-content: center; + align-items: center; + gap: 0; + border-bottom: 2px solid #34495e; +} + +.title-badge { + font-size: 0.9em; + font-weight: normal; + color: #ccc; + text-transform: uppercase; + white-space: nowrap; +} + +.badge-separator { + color: #ccc; + font-weight: normal; + padding: 0 15px; + position: relative; + top: -1px; +} + +/* Main Content Area */ +.cv-main { + background: var(--paper-white); + padding: 3rem 2.5rem 8rem 2.5rem; /* Bottom padding for footer and zoom control clearance */ +} diff --git a/static/css/02-layout/_page.css b/static/css/02-layout/_page.css new file mode 100644 index 0000000..eff01b0 --- /dev/null +++ b/static/css/02-layout/_page.css @@ -0,0 +1,112 @@ +.cv-page { + background: var(--paper-bg); + max-width: 1200px; + margin: 2rem auto; + box-shadow: var(--shadow-lg); + border: 1px solid var(--border-color); + transform: scale(0.95); + transform-origin: top center; + transition: transform 0.3s ease; +} + +/* Page Content Grid */ +.page-content { + display: grid; +} + +/* Page 1: Left sidebar + Main content */ +.page-1 .page-content { + grid-template-columns: 300px 1fr; +} + +/* Page 2: Main content + Right sidebar */ +.page-2 .page-content { + grid-template-columns: 1fr 300px; +} + +/* Sidebar positioning */ +.cv-sidebar-left { + grid-column: 1; + grid-row: 1; +} + +.cv-sidebar-right { + grid-column: 2; + grid-row: 1; + text-align: right; +} + +/* Main content positioning */ +.page-1 .cv-main { + grid-column: 2; + grid-row: 1; +} + +.page-2 .cv-main { + grid-column: 1; + grid-row: 1; +} + +/* =============================================== + FOOTER STYLES + =============================================== */ + +.cv-footer { + background: #303030; + color: #ccc; + padding: 20px 0; + margin: 0; + grid-column: 1 / -1; /* Span all columns */ +} + +.footer-content { + list-style: none; + text-align: center; + margin: 0; + padding: 0; +} + +.footer-content li { + display: inline-block; + margin: 0; +} + +.footer-content li > div { + display: inline-block; + margin: 0 20px; + text-align: left; +} + +.footer-label { + width: 200px; + font-size: 1.7em; +} + +.footer-value { + width: 450px; + font-size: 1em; +} + +.footer-value b { + font-weight: normal; + font-size: 1.7em; +} + +.footer-separator { + position: relative; + left: -4%; + font-size: 0.6em; +} + +.footer-separator i { + opacity: 0.3; +} + +.cv-footer a { + color: inherit; +} + +.cv-footer a:hover { + color: #0275d8; + text-decoration: none; +} diff --git a/static/css/02-layout/_paper.css b/static/css/02-layout/_paper.css new file mode 100644 index 0000000..4020315 --- /dev/null +++ b/static/css/02-layout/_paper.css @@ -0,0 +1,29 @@ +/* ============================================================================ + CV PAPER - Container for two-page layout + ============================================================================ */ + +.cv-paper { + width: 100%; + background: transparent; /* Remove white background - each page has its own */ + box-shadow: none; /* Remove shadow - each page has its own */ + margin: 0; + position: relative; + display: block; /* Changed from grid to block for stacking pages */ + min-height: auto; + + /* Zoom transform properties */ + transform-origin: top center; /* Scale from top center - page stays anchored at top */ + transition: transform 0.08s linear; /* Smooth, immediate zoom response */ + will-change: transform; /* Hint browser to optimize for transforms */ +} + +/* Page break helpers */ +.page-break { + page-break-after: always; + break-after: page; +} + +.avoid-break { + page-break-inside: avoid; + break-inside: avoid; +} diff --git a/static/css/03-components/_action-bar.css b/static/css/03-components/_action-bar.css new file mode 100644 index 0000000..05a228e --- /dev/null +++ b/static/css/03-components/_action-bar.css @@ -0,0 +1,602 @@ +/* Single Black Top Bar */ +.action-bar { + background: var(--action-bar-bg); + color: var(--action-bar-text); + position: sticky; + top: 0; + z-index: 100; + box-shadow: var(--shadow-md); + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; +} + +.action-bar-content { + max-width: 100%; + margin: 0 auto; + padding: 0; + display: grid; + grid-template-columns: 1fr auto 1fr; + align-items: stretch; + gap: 2rem; + height: 50px; +} + +/* Left: Site Title */ +.site-title { + display: flex; + align-items: center; + gap: 0.75rem; + justify-self: start; + white-space: nowrap; + padding: 0; + height: 100%; +} + +.site-title-left { + display: flex; + align-items: center; + gap: 0.75rem; +} + +.site-icon { + color: #fff; + flex-shrink: 0; + display: inline-flex; + align-items: center; + justify-content: center; + height: 36px; + padding: 0 .5rem 0 1.5rem; +} + +/* Mobile icon hidden by default, shown only on mobile */ +.site-icon-mobile { + display: none; + color: #fff; + flex-shrink: 0; + margin-right: 0.5rem; +} + +/* Site logo and title links */ +.site-logo-link, +.site-title-link { + text-decoration: none; + color: inherit; + display: flex; + align-items: center; + height: 36px; + transition: opacity 0.2s ease; +} + +.site-logo-link:hover, +.site-title-link:hover { + opacity: 0.8; + text-decoration: none; +} + +.site-logo-link { + padding: 0; +} + +/* Ensure Iconify icons display properly */ +.iconify, +iconify-icon { + display: inline-block; + vertical-align: middle; +} + +.site-title-text { + font-size: 1.05rem; + font-weight: 500; + color: #fff; + letter-spacing: -0.01em; + line-height: 1; + display: flex; + align-items: center; + height: 36px; + padding: 0 1rem 0 0rem; +} + +/* Center: View controls with labels */ +.view-controls-center { + display: flex; + flex-direction: row; + align-items: center; + gap: 2.5rem; + justify-self: center; + flex-shrink: 0; + white-space: nowrap; + height: 100%; +} + +.selector-group { + display: flex; + align-items: center; + gap: 0.75rem; +} + +.selector-label { + font-size: 0.875rem; + color: rgba(255,255,255,0.85); + font-weight: 500; + white-space: nowrap; + letter-spacing: -0.01em; + line-height: 1; + display: flex; + align-items: center; + height: 36px; +} + +.selector-label span { + color: #27ae60; + font-weight: 600; +} + +.language-toggle, +.cv-length-toggle, +.logo-toggle { + flex-shrink: 0; +} + +/* Right: Action buttons */ +.action-buttons { + justify-self: end; + flex-shrink: 0; +} + +.htmx-indicator { + flex-shrink: 0; +} + +.lang-btn { + padding: 0.4rem 1rem; + border: 1px solid rgba(255,255,255,0.3); + background: transparent; + color: white; + border-radius: 3px; + cursor: pointer; + font-size: 1rem; + font-weight: 400; + text-transform: capitalize; + transition: all 0.2s ease; +} + +.lang-btn:hover { + background: rgba(255,255,255,0.1); + border-color: rgba(255,255,255,0.5); +} + +.lang-btn.active { + background: #27ae60 !important; + border-color: #27ae60 !important; + font-weight: 500; +} + +/* Icon Toggle Switches */ +.icon-toggle { + position: relative; + display: flex; + cursor: pointer; +} + +.icon-toggle input[type="checkbox"] { + position: absolute; + opacity: 0; + width: 0; + height: 0; +} + +.icon-toggle-slider { + position: relative; + display: inline-flex; + align-items: center; + justify-content: space-between; + width: 75px; + height: 30px; + background: #e0e0e0; + border: 2px solid #d0d0d0; + border-radius: 15px; + padding: 0 6px; + transition: all 0.3s ease; +} + +.icon-toggle-slider::before { + content: ''; + position: absolute; + width: 24px; + height: 24px; + left: 2px; + background: white; + border-radius: 50%; + transition: transform 0.3s ease; + box-shadow: 0 2px 4px rgba(0,0,0,0.3); + z-index: 2; + pointer-events: none; +} + +.icon-toggle input:checked + .icon-toggle-slider::before { + transform: translateX(43px); +} + +.icon-toggle input:checked + .icon-toggle-slider { + background: #27ae60; + border-color: #229954; +} + +.icon-toggle-slider .icon-left, +.icon-toggle-slider .icon-right { + position: absolute; + z-index: 3; + transition: all 0.3s ease; + flex-shrink: 0; + pointer-events: none; +} + +.icon-toggle-slider .icon-left { + left: 6px; +} + +.icon-toggle-slider .icon-right { + right: 6px; +} + +.icon-toggle input:not(:checked) + .icon-toggle-slider .icon-left { + color: #333 !important; + font-weight: bold; +} + +.icon-toggle input:not(:checked) + .icon-toggle-slider .icon-right { + color: #999 !important; + opacity: 0.5; +} + +.icon-toggle input:checked + .icon-toggle-slider .icon-left { + color: rgba(255,255,255,0.4) !important; + opacity: 0.5; +} + +.icon-toggle input:checked + .icon-toggle-slider .icon-right { + color: white !important; + font-weight: bold; +} + +.icon-toggle input:focus + .icon-toggle-slider { + box-shadow: 0 0 0 3px rgba(39, 174, 96, 0.2); +} + +/* Language selector wrapper - contains indicators outside swap target */ +.language-selector-wrapper { + position: relative; + display: inline-flex; + height: 100%; + /* Ensure wrapper doesn't create extra spacing */ + width: fit-content; +} + +/* Language selector - matching action button style */ +.language-selector { + display: inline-flex; + gap: 0; + padding: 0; + padding-left: 1rem; /* Space after the title */ + margin-right: 0; + background: transparent; + border-radius: 0; + height: 100%; + align-items: stretch; +} + +/* Position language indicators next to their respective buttons */ +#lang-indicator-en, +#lang-indicator-es { + position: absolute; + top: 50%; + transform: translateY(-50%); + pointer-events: none; + z-index: 10; +} + +/* Position indicators inside the button visual area */ +#lang-indicator-en { + left: calc(1rem + 50px); /* Inside first button */ +} + +#lang-indicator-es { + left: calc(1rem + 135px); /* Inside second button */ +} + +.selector-btn { + padding: 0 1.5rem; + background: transparent; + color: white; + border: none; + border-radius: 0; + cursor: pointer; + font-size: 1rem; + font-weight: 500; + display: inline-flex; + align-items: center; + justify-content: center; + /* gap: 0.5rem; */ + gap: 0rem; + text-decoration: none; + white-space: nowrap; + letter-spacing: -0.01em; + height: 100%; + line-height: 1; + transition: all 0.2s ease; + outline: none !important; + box-shadow: none !important; + min-width: 50px!important; +} + +.selector-btn:focus, +.selector-btn:focus-visible, +.selector-btn:active { + outline: none !important; + box-shadow: none !important; +} + +.selector-btn:hover { + background: #666; +} + +.selector-btn:hover iconify-icon { + color: #27ae60; +} + +.selector-btn.active { + background: #27ae60; + color: white; +} + +.selector-btn:not(.active) { + background: transparent; + color: white; +} + +/* Language selector buttons - no global animations (applied in responsive range only) */ + +/* Action buttons - transparent with white text */ +.action-btn { + padding: 0 1.5rem; + background: transparent; + color: white; + border: none; + border-radius: 0; + cursor: pointer; + font-size: 1rem; + font-weight: 500; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + text-decoration: none; + white-space: nowrap; + letter-spacing: -0.01em; + height: 100%; + line-height: 1; + transition: background-color 0.3s ease, color 0.3s ease; /* Smooth color transitions */ +} + +.action-btn iconify-icon { + color: white; + transition: color 0.3s ease; /* Smooth icon color transition */ +} + +.action-btn:hover { + background: #ddd; + color: #333; + text-decoration: none; +} + +.action-btn:hover iconify-icon { + color: #27ae60; +} + +/* PDF Download button - gray by default, red on hover */ +.pdf-btn { + background: transparent !important; /* Transparent like other buttons */ + color: white !important; +} + +.pdf-btn:hover, +.pdf-btn.pdf-hover-sync { + background: #cd6060 !important; /* PDF red on hover */ + color: white !important; +} + +.pdf-btn iconify-icon { + color: white !important; + filter: brightness(0) invert(1); /* Always white */ + transition: filter 0.3s ease; +} + +.pdf-btn:hover iconify-icon { + color: white !important; + filter: brightness(0) invert(1); /* Keep white on hover */ +} + +/* Print Friendly button - white bg with green icon on hover */ +.print-btn { + background: transparent !important; + color: white !important; +} + +.print-btn:hover, +.print-btn.print-hover-sync { + background: white !important; /* White background on hover */ + color: #27ae60 !important; /* Green icon on hover */ +} + +.print-btn iconify-icon { + color: white; /* White icon by default */ +} + +.print-btn:hover iconify-icon, +.print-btn.print-hover-sync iconify-icon { + color: #27ae60; /* Green icon on hover */ +} + +/* CV Length Toggle - Center of action bar */ +.cv-length-toggle { + display: flex; + gap: 0.5rem; + justify-self: center; +} + +.length-btn { + padding: 0.4rem 1rem; + border: 1px solid rgba(255,255,255,0.4); + background: rgba(255,255,255,0.1); + color: white; + border-radius: 4px; + cursor: pointer; + font-size: 0.9rem; + font-weight: 500; + transition: all 0.2s ease; +} + +.length-btn:hover { + background: rgba(255,255,255,0.2); + border-color: rgba(255,255,255,0.6); +} + +.length-btn.active { + background: white; + color: #1a1a1a; + border-color: white; + font-weight: 600; +} + +/* Action buttons styling (already positioned by grid) */ +.action-buttons, +.action-buttons-right { + display: flex; + gap: 0; + align-items: stretch; + height: 100%; +} + +.action-buttons-right { + justify-self: end; + margin-left: auto; +} + +/* ============================================================================ + HTMX Loading Indicators + ========================================================================= */ + +/* Base indicator styles - hidden by default with opacity for smooth transitions */ +.htmx-indicator { + opacity: 0; /* Hidden by default */ + transition: opacity 200ms ease-in-out; + pointer-events: none; + display: inline-flex; + align-items: center; + justify-content: center; + position: absolute; /* Remove from layout flow to prevent spacing issues */ +} + +/* Override for when request is active - must come AFTER base rule */ +.htmx-indicator.htmx-request, +#lang-indicator-en.htmx-request, +#lang-indicator-es.htmx-request { + opacity: 1 !important; /* Force visible state */ +} + +/* Ensure iconify-icon indicators override global iconify-icon display style */ +iconify-icon.htmx-indicator { + display: inline-flex; + align-items: center; + justify-content: center; +} + +/* Show indicators during HTMX requests */ +/* Using span wrapper, so target span.htmx-request specifically */ +span.htmx-request.htmx-indicator, +.htmx-request .htmx-indicator, +.htmx-request.htmx-indicator { + opacity: 1 !important; +} + +/* Spinning animation for loading icons */ +.htmx-indicator.spinning { + animation: htmx-spin 1s linear infinite; +} + +@keyframes htmx-spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} + +/* Indicator size variants */ +.htmx-indicator.small { + width: 14px; + height: 14px; + font-size: 14px; +} + +.htmx-indicator.medium { + width: 18px; + height: 18px; + font-size: 18px; +} + +.htmx-indicator.large { + width: 24px; + height: 24px; + font-size: 24px; +} + +/* Positioning variants */ +.htmx-indicator.inline { + display: inline-flex; + margin-left: 8px; + vertical-align: middle; +} + +.htmx-indicator.inline-start { + display: inline-flex; + margin-right: 8px; + vertical-align: middle; +} + +/* Color variants for different contexts */ +.htmx-indicator.light { + color: rgba(255, 255, 255, 0.9); +} + +.htmx-indicator.dark { + color: rgba(0, 0, 0, 0.7); +} + +.htmx-indicator.accent { + color: #27ae60; +} + +/* Respect reduced motion preference */ +@media (prefers-reduced-motion: reduce) { + .htmx-indicator.spinning { + animation: none; + } + .htmx-indicator { + transition: none; + } +} + +/* Legacy loader class for backward compatibility */ +.loader { + border: 2px solid #f3f3f3; + border-top: 2px solid white; + border-radius: 50%; + width: 20px; + height: 20px; + animation: htmx-spin 1s linear infinite; +} + +/* ============================================================================ + Inline Loading States for HTMX Transitions + ========================================================================= */ + +/* Inline loading states - no blocking overlay, smooth transitions only */ +/* Language selector buttons already have htmx-indicator spinners */ +/* CV content areas show subtle fade during swap */ diff --git a/static/css/03-components/_courses.css b/static/css/03-components/_courses.css new file mode 100644 index 0000000..95d6efb --- /dev/null +++ b/static/css/03-components/_courses.css @@ -0,0 +1,90 @@ +/* Courses */ +.course-item { + display: flex; + gap: 1.2rem; + align-items: flex-start; + margin-bottom: 2.5rem; + padding-bottom: 2rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} + +/* Keep border on all course items including last one */ + +.course-icon { + flex-shrink: 0; + width: 80px; + height: 80px; + display: flex; + align-items: center; + justify-content: center; +} + +.course-icon img { + width: 80px; + height: 80px; + object-fit: contain; + border-radius: 4px; + border: 1px solid #ddd; + background: transparent; + padding: 4px; +} + +.default-course-icon { + width: 80px; + height: 80px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + border: 1px solid #ddd; + background: transparent; + color: var(--text-light); + padding: 10px; +} + +.course-content { + flex: 1; +} + +.course-header { + margin-bottom: 0.5rem; +} + +.course-title { + font-size: 1em; + font-weight: 600; + margin: 0 0 0.3rem 0; + line-height: 1.4; + color: var(--text-dark); +} + +.course-title-text { + display: inline; +} + +.course-institution { + display: inline; + margin-left: 0.5em; + font-weight: normal; +} + +.course-period, +.course-separator, +.course-location, +.course-duration { + color: var(--text-muted); + font-size: 0.9em; +} + +.course-separator { + color: var(--text-light); +} + +.course-desc { + font-size: 0.85em; + color: var(--text-gray); + margin-top: 0.4rem; + line-height: 1.4; + text-align: justify; +} + diff --git a/static/css/03-components/_cv-header.css b/static/css/03-components/_cv-header.css new file mode 100644 index 0000000..633b0d3 --- /dev/null +++ b/static/css/03-components/_cv-header.css @@ -0,0 +1,80 @@ +/* Header with photo and name */ +.cv-header { + margin-bottom: 2rem; +} + +.cv-header-content { + display: flex; + justify-content: space-between; + align-items: flex-start; + gap: 2rem; +} + +.cv-header-left { + flex: 1; + position: relative; + /* Desktop: Add right padding to make room for the photo */ + padding-right: 185px; /* Photo width (150px) + gap (35px) */ +} + +.cv-photo { + width: 150px; + height: 200px; + flex-shrink: 0; + overflow: hidden; + border: 3px solid white; + box-shadow: 0 2px 8px rgba(0,0,0,0.15); + + /* Desktop: Position photo in the right padding area */ + position: absolute; + top: 15px; + right: 15px; /* Margin from the right edge */ +} + +.cv-photo img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.cv-name { + font-family: 'Quicksand', sans-serif; + font-size: 2.2em; + font-weight: 400; + {{/* font-style: italic; */}} + line-height: 1.1; + margin-bottom: 8px; + color: var(--text-primary); + text-align: right; +} + +.cv-experience-years { + font-family: 'Quicksand', sans-serif; + font-size: 0.9em; + font-weight: 500; + line-height: 1.5; + color: var(--text-primary); + margin: 0; +} + +.years-experience { + font-family: 'Quicksand', sans-serif; + font-size: 1.25em; + font-weight: 400; + color: var(--text-muted); + margin: 4px 0 0 0; + line-height: 1.4; + text-align: right; +} + +/* Intro/Excerpt Text - Positioned inside header, matching old React CV */ +.intro-text { + font-family: 'Quicksand', sans-serif; + font-size: 1.0em; + line-height: 1.6; + color: var(--text-secondary); + margin-top: 20px; + text-align: justify; + font-style: italic; +} + diff --git a/static/css/03-components/_cv-section.css b/static/css/03-components/_cv-section.css new file mode 100644 index 0000000..0d39e7e --- /dev/null +++ b/static/css/03-components/_cv-section.css @@ -0,0 +1,309 @@ +/* Sections */ +.cv-section { + margin-bottom: 3rem; + page-break-inside: avoid; +} + +/* Remove margin when section is collapsed */ +.cv-section:has(details:not([open])) { + margin-bottom: 0; +} + +.section-title { + font-family: 'Quicksand', sans-serif; + font-size: 1.4em; + font-weight: 500; + line-height: 1.2em; + margin: 20px 0 25px 0; + padding: 0; + color: var(--text-primary); +} + +/* Collapsible Section Styles */ +.cv-section details { + margin: 0; +} + +.cv-section details summary ~ * { + overflow: hidden; + max-height: 0; + opacity: 0; + transform: translateY(-8px); + transition: max-height 0.5s ease-in-out, + opacity 0.3s ease-in-out, + transform 0.3s ease-in-out; +} + +.cv-section details[open] summary ~ * { + max-height: 3000px; + opacity: 1; + transform: translateY(0); +} + +.cv-section summary { + cursor: pointer; + list-style: none; + user-select: none; + position: relative; +} + +/* Remove default triangle marker in all browsers */ +.cv-section summary::-webkit-details-marker, +.cv-section summary::marker { + display: none; +} + +/* Add custom collapse indicator after the title */ +.cv-section summary .section-title { + display: inline-flex; + align-items: center; + gap: 0.5rem; +} + +.cv-section summary .section-title::after { + content: '▼'; + font-size: 0.8em; + color: var(--text-muted); + transition: transform 0.2s ease, opacity 0.2s ease; + opacity: 0; + margin-left: 0.5rem; +} + +/* Show indicator on hover or when closed */ +.cv-section summary:hover .section-title::after, +.cv-section details:not([open]) summary .section-title::after { + opacity: 1; +} + +/* Rotate indicator when closed */ +.cv-section details:not([open]) summary .section-title::after { + transform: rotate(-90deg); +} + +/* Hover effect on summary */ +.cv-section summary:hover .section-title { + color: var(--accent-blue); +} + +.summary-text { + font-family: 'Quicksand', sans-serif; + line-height: 1.5; + text-align: justify; + font-size: 0.9em; + font-weight: 400; + color: var(--text-primary); +} + +/* Experience */ +/* Experience item layout moved to logo-toggle.css */ + +.experience-header { + margin-bottom: 0.6rem; +} + +.experience-title-line { + margin-bottom: 0.3em; +} + +.position { + font-size: 1rem; + font-weight: 500; + margin: 0; + color: var(--text-dark); + margin-bottom: 4px; +} + +.position .position-title { + display: inline-block; + margin-right: 0.3em; +} + +.position .company-name { + display: inline-block; +} + +.current-badge { + display: inline-block; + background: #27ae60; + color: white; + font-weight: 700; + font-size: 0.7em; + padding: 0.2em 0.5em; + border-radius: 3px; + margin-left: 0.5em; + vertical-align: middle; + letter-spacing: 0.5px; +} + +.live-badge { + display: inline-flex; + align-items: center; + gap: 0.3em; + background: #27ae60; + color: white; + font-weight: 700; + font-size: 0.7em; + padding: 0.2em 0.5em; + border-radius: 3px; + margin-left: 0.5em; + vertical-align: middle; + letter-spacing: 0.5px; +} + +.live-badge iconify-icon { + font-size: 1.2em; +} + +.expired-badge { + display: inline-block; + background: #e74c3c; + color: white; + font-weight: 700; + font-size: 0.7em; + padding: 0.2em 0.5em; + border-radius: 3px; + margin-left: 0.5em; + vertical-align: middle; + letter-spacing: 0.5px; +} + +.maintained-badge { + display: inline-block; + background: #3498db; + color: white; + font-weight: 700; + font-size: 0.7em; + padding: 0.2em 0.5em; + border-radius: 3px; + margin-left: 0.5em; + vertical-align: middle; + letter-spacing: 0.5px; +} + +.experience-period, +.experience-separator, +.experience-location, +.experience-duration { + color: var(--text-muted); + font-weight: 600; + display: inline-block; + font-size: 1.05rem; +} + +.experience-duration { + font-style: italic; +} + +.short-desc { + color: var(--text-dark); + font-size: 0.95rem; + line-height: 1.6; + margin-top: 0.5rem; +} + +.duration-text { + color: var(--text-light); + font-weight: 500; +} + +.responsibilities { + list-style: none; + margin-top: 1rem; + padding-left: 0; +} + +.responsibilities li { + padding-left: 1.2rem; + margin-bottom: 0.4rem; + position: relative; + font-size: 0.95rem; + color: var(--text-dark); + line-height: 1.5; +} + +.responsibilities li:before { + content: "•"; + position: absolute; + left: 0; + color: var(--text-gray); +} + +/* Responsibilities with company icons (similar to main experience layout) */ +.responsibilities li:has(img), +.responsibilities li:has(iconify-icon) { + display: grid; + grid-template-columns: 60px 1fr; + gap: 1rem; + padding-left: 0; + margin-bottom: 1rem; + align-items: start; +} + +.responsibilities li:has(img):before, +.responsibilities li:has(iconify-icon):before { + display: none; +} + +.responsibilities li img { + width: 60px; + height: 60px; + object-fit: contain; + border-radius: 4px; + border: 1px solid #ddd; + background: transparent; + padding: 4px; +} + +.responsibilities li iconify-icon.default-company-icon { + width: 60px; + height: 60px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + border: 1px solid #ddd; + background: transparent; + color: var(--text-light); + padding: 8px; +} + +/* Education */ +.education-item { + margin-bottom: 1rem; + font-size: 0.95rem; + line-height: 1.6; + color: var(--text-dark); +} + + +/* Languages */ +.languages-list { + display: flex; + flex-wrap: wrap; + gap: 1.5rem; +} + +.language-item { + font-size: 0.95rem!important; + color: var(--text-dark); + margin-bottom: 0.3rem!important; + line-height: 1.4!important; + margin-left: 2rem!important; +} + +.language-item small { + display: block; + font-size: 0.8em; + margin-top: 0.2rem; + font-style: italic; +} + +/* Experience Items */ +.experience-item { + margin-bottom: 2.5rem; + padding-bottom: 2rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} + +/* Keep border on all experience items including last one */ + diff --git a/static/css/03-components/_education.css b/static/css/03-components/_education.css new file mode 100644 index 0000000..8e60959 --- /dev/null +++ b/static/css/03-components/_education.css @@ -0,0 +1,40 @@ +/* Education */ +.education-item { + margin-bottom: 1rem; + font-size: 0.95rem; + line-height: 1.6; + color: var(--text-dark); +} + + +/* Languages */ +.languages-list { + display: flex; + flex-wrap: wrap; + gap: 1.5rem; +} + +.language-item { + font-size: 0.95rem!important; + color: var(--text-dark); + margin-bottom: 0.3rem!important; + line-height: 1.4!important; + margin-left: 2rem!important; +} + +.language-item small { + display: block; + font-size: 0.8em; + margin-top: 0.2rem; + font-style: italic; +} + +/* Experience Items */ +.experience-item { + margin-bottom: 2.5rem; + padding-bottom: 2rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} + +/* Keep border on all experience items including last one */ + diff --git a/static/css/03-components/_experience.css b/static/css/03-components/_experience.css new file mode 100644 index 0000000..e5b0b5c --- /dev/null +++ b/static/css/03-components/_experience.css @@ -0,0 +1,533 @@ +/* Experience */ +/* Experience item layout moved to logo-toggle.css */ + +.experience-header { + margin-bottom: 0.6rem; +} + +.experience-title-line { + margin-bottom: 0.3em; +} + +.position { + font-size: 1rem; + font-weight: 500; + margin: 0; + color: var(--text-dark); + margin-bottom: 4px; +} + +.position .position-title { + display: inline-block; + margin-right: 0.3em; +} + +.position .company-name { + display: inline-block; +} + +.current-badge { + display: inline-block; + background: #27ae60; + color: white; + font-weight: 700; + font-size: 0.7em; + padding: 0.2em 0.5em; + border-radius: 3px; + margin-left: 0.5em; + vertical-align: middle; + letter-spacing: 0.5px; +} + +.live-badge { + display: inline-flex; + align-items: center; + gap: 0.3em; + background: #27ae60; + color: white; + font-weight: 700; + font-size: 0.7em; + padding: 0.2em 0.5em; + border-radius: 3px; + margin-left: 0.5em; + vertical-align: middle; + letter-spacing: 0.5px; +} + +.live-badge iconify-icon { + font-size: 1.2em; +} + +.expired-badge { + display: inline-block; + background: #e74c3c; + color: white; + font-weight: 700; + font-size: 0.7em; + padding: 0.2em 0.5em; + border-radius: 3px; + margin-left: 0.5em; + vertical-align: middle; + letter-spacing: 0.5px; +} + +.maintained-badge { + display: inline-block; + background: #3498db; + color: white; + font-weight: 700; + font-size: 0.7em; + padding: 0.2em 0.5em; + border-radius: 3px; + margin-left: 0.5em; + vertical-align: middle; + letter-spacing: 0.5px; +} + +.experience-period, +.experience-separator, +.experience-location, +.experience-duration { + color: var(--text-muted); + font-weight: 600; + display: inline-block; + font-size: 1.05rem; +} + +.experience-duration { + font-style: italic; +} + +.short-desc { + color: var(--text-dark); + font-size: 0.95rem; + line-height: 1.6; + margin-top: 0.5rem; +} + +.duration-text { + color: var(--text-light); + font-weight: 500; +} + +.responsibilities { + list-style: none; + margin-top: 1rem; + padding-left: 0; +} + +.responsibilities li { + padding-left: 1.2rem; + margin-bottom: 0.4rem; + position: relative; + font-size: 0.95rem; + color: var(--text-dark); + line-height: 1.5; +} + +.responsibilities li:before { + content: "•"; + position: absolute; + left: 0; + color: var(--text-gray); +} + +/* Responsibilities with company icons (similar to main experience layout) */ +.responsibilities li:has(img), +.responsibilities li:has(iconify-icon) { + display: grid; + grid-template-columns: 60px 1fr; + gap: 1rem; + padding-left: 0; + margin-bottom: 1rem; + align-items: start; +} + +.responsibilities li:has(img):before, +.responsibilities li:has(iconify-icon):before { + display: none; +} + +.responsibilities li img { + width: 60px; + height: 60px; + object-fit: contain; + border-radius: 4px; + border: 1px solid #ddd; + background: transparent; + padding: 4px; +} + +.responsibilities li iconify-icon.default-company-icon { + width: 60px; + height: 60px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + border: 1px solid #ddd; + background: transparent; + color: var(--text-light); + padding: 8px; +} + +/* Education */ +.education-item { + margin-bottom: 1rem; + font-size: 0.95rem; + line-height: 1.6; + color: var(--text-dark); +} + + +/* Languages */ +.languages-list { + display: flex; + flex-wrap: wrap; + gap: 1.5rem; +} + +.language-item { + font-size: 0.95rem!important; + color: var(--text-dark); + margin-bottom: 0.3rem!important; + line-height: 1.4!important; + margin-left: 2rem!important; +} + +.language-item small { + display: block; + font-size: 0.8em; + margin-top: 0.2rem; + font-style: italic; +} + +/* Experience Items */ +.experience-item { + margin-bottom: 2.5rem; + padding-bottom: 2rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} + +/* Keep border on all experience items including last one */ + +/* Courses */ +.course-item { + display: flex; + gap: 1.2rem; + align-items: flex-start; + margin-bottom: 2.5rem; + padding-bottom: 2rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} + +/* Keep border on all course items including last one */ + +.course-icon { + flex-shrink: 0; + width: 80px; + height: 80px; + display: flex; + align-items: center; + justify-content: center; +} + +.course-icon img { + width: 80px; + height: 80px; + object-fit: contain; + border-radius: 4px; + border: 1px solid #ddd; + background: transparent; + padding: 4px; +} + +.default-course-icon { + width: 80px; + height: 80px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + border: 1px solid #ddd; + background: transparent; + color: var(--text-light); + padding: 10px; +} + +.course-content { + flex: 1; +} + +.course-header { + margin-bottom: 0.5rem; +} + +.course-title { + font-size: 1em; + font-weight: 600; + margin: 0 0 0.3rem 0; + line-height: 1.4; + color: var(--text-dark); +} + +.course-title-text { + display: inline; +} + +.course-institution { + display: inline; + margin-left: 0.5em; + font-weight: normal; +} + +.course-period, +.course-separator, +.course-location, +.course-duration { + color: var(--text-muted); + font-size: 0.9em; +} + +.course-separator { + color: var(--text-light); +} + +.course-desc { + font-size: 0.85em; + color: var(--text-gray); + margin-top: 0.4rem; + line-height: 1.4; + text-align: justify; +} + +/* Projects */ +.project-item { + display: flex; + gap: 1.2rem; + align-items: flex-start; + margin-bottom: 2.5rem; + padding-bottom: 2rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} + +.project-icon { + flex-shrink: 0; + width: 80px; + height: 80px; + display: flex; + align-items: center; + justify-content: center; +} + +.project-icon img { + width: 80px; + height: 80px; + object-fit: contain; + border-radius: 4px; + border: 1px solid #ddd; + background: transparent; + padding: 4px; +} + +.default-project-icon { + width: 80px; + height: 80px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + border: 1px solid #ddd; + background: transparent; + color: var(--text-light); + padding: 10px; +} + +.project-content { + flex: 1; +} + +.project-header { + margin-bottom: 0.5rem; +} + +.project-title { + font-size: 1em; + font-weight: 600; + margin: 0 0 0.3rem 0; + line-height: 1.4; + color: var(--text-dark); +} + +.project-title-text { + display: inline; +} + +.project-title-text a { + color: var(--accent-blue); + text-decoration: none; +} + +.project-title-text a:hover { + text-decoration: underline; +} + +.project-period, +.project-separator, +.project-location { + color: var(--text-muted); + font-size: 0.9em; + font-weight: 600; +} + +.project-separator { + color: var(--text-light); +} + +.project-desc { + font-size: 0.95rem; + color: var(--text-dark); + margin-top: 0.5rem; + line-height: 1.6; + text-align: justify; +} + +.project-technologies { + font-size: 0.85em; + color: var(--text-gray); + margin-top: 0.5rem; + line-height: 1.4; +} + +.projects-footer { + margin-top: -1.5rem; + padding-top: 0rem; + text-align: center; + font-size: 0.95rem; + color: var(--text-gray); +} + +.projects-footer p { + margin: 0; +} + +.projects-footer a { + color: var(--accent-blue); + text-decoration: none; +} + +.projects-footer a:hover { + text-decoration: underline; +} + +/* References */ +.reference-item { + margin-bottom: 0!important; + line-height: 1.4!important; + margin-left: 2rem!important; + font-size: 0.95rem!important; +} + +.reference-item a { + + color: var(--accent-blue); + text-decoration: none; + word-break: break-word; +} + +.reference-item a:hover { + text-decoration: underline; +} + +.ref-type { + display: block; + font-size: 0.8em; + color: var(--text-gray); + font-style: italic; + margin-top: 0.2rem; +} + +/* Footer */ +footer { + text-align: center; + padding: 2rem; + color: rgba(255,255,255,0.7); + font-size: 0.85rem; +} + +/* GitHub repository link styling */ +.github-repo-link { + color: whitesmoke !important; + transition: color 0.2s ease-in-out; +} + +.github-repo-link:hover { + color: #66B3FF !important; +} + + +/* CV Version Toggle Animations */ +@keyframes fadeInGrow { + from { + opacity: 0; + max-height: 0; + transform: scaleY(0.8); + transform-origin: top; + } + to { + opacity: 1; + max-height: 5000px; + transform: scaleY(1); + } +} + +@keyframes fadeOutShrink { + from { + opacity: 1; + max-height: 5000px; + transform: scaleY(1); + } + to { + opacity: 0; + max-height: 0; + transform: scaleY(0.8); + transform-origin: top; + } +} + +/* Elements that appear/disappear */ +.long-only, +.short-desc { + overflow: hidden; + transition: all 0.3s ease-in-out; +} + +/* Short CV - Hide detailed content with animation */ +.cv-short .long-only { + display: none; + animation: fadeOutShrink 0.3s ease-in-out; +} + +.cv-short .short-desc { + display: block; + animation: fadeInGrow 0.3s ease-in-out; +} + +/* Long CV - Hide short descriptions with animation */ +.cv-long .short-desc, +.short-desc { + display: none; + animation: fadeOutShrink 0.3s ease-in-out; +} + +.cv-long .long-only { + display: block; + animation: fadeInGrow 0.3s ease-in-out; +} + +.cv-long .responsibilities { + display: block; + animation: fadeInGrow 0.3s ease-in-out; +} + + diff --git a/static/css/03-components/_languages.css b/static/css/03-components/_languages.css new file mode 100644 index 0000000..c2336cd --- /dev/null +++ b/static/css/03-components/_languages.css @@ -0,0 +1,31 @@ +/* Languages */ +.languages-list { + display: flex; + flex-wrap: wrap; + gap: 1.5rem; +} + +.language-item { + font-size: 0.95rem!important; + color: var(--text-dark); + margin-bottom: 0.3rem!important; + line-height: 1.4!important; + margin-left: 2rem!important; +} + +.language-item small { + display: block; + font-size: 0.8em; + margin-top: 0.2rem; + font-style: italic; +} + +/* Experience Items */ +.experience-item { + margin-bottom: 2.5rem; + padding-bottom: 2rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} + +/* Keep border on all experience items including last one */ + diff --git a/static/css/03-components/_projects.css b/static/css/03-components/_projects.css new file mode 100644 index 0000000..2bf6538 --- /dev/null +++ b/static/css/03-components/_projects.css @@ -0,0 +1,230 @@ +/* Projects */ +.project-item { + display: flex; + gap: 1.2rem; + align-items: flex-start; + margin-bottom: 2.5rem; + padding-bottom: 2rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} + +.project-icon { + flex-shrink: 0; + width: 80px; + height: 80px; + display: flex; + align-items: center; + justify-content: center; +} + +.project-icon img { + width: 80px; + height: 80px; + object-fit: contain; + border-radius: 4px; + border: 1px solid #ddd; + background: transparent; + padding: 4px; +} + +.default-project-icon { + width: 80px; + height: 80px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + border: 1px solid #ddd; + background: transparent; + color: var(--text-light); + padding: 10px; +} + +.project-content { + flex: 1; +} + +.project-header { + margin-bottom: 0.5rem; +} + +.project-title { + font-size: 1em; + font-weight: 600; + margin: 0 0 0.3rem 0; + line-height: 1.4; + color: var(--text-dark); +} + +.project-title-text { + display: inline; +} + +.project-title-text a { + color: var(--accent-blue); + text-decoration: none; +} + +.project-title-text a:hover { + text-decoration: underline; +} + +.project-period, +.project-separator, +.project-location { + color: var(--text-muted); + font-size: 0.9em; + font-weight: 600; +} + +.project-separator { + color: var(--text-light); +} + +.project-desc { + font-size: 0.95rem; + color: var(--text-dark); + margin-top: 0.5rem; + line-height: 1.6; + text-align: justify; +} + +.project-technologies { + font-size: 0.85em; + color: var(--text-gray); + margin-top: 0.5rem; + line-height: 1.4; +} + +.projects-footer { + margin-top: -1.5rem; + padding-top: 0rem; + text-align: center; + font-size: 0.95rem; + color: var(--text-gray); +} + +.projects-footer p { + margin: 0; +} + +.projects-footer a { + color: var(--accent-blue); + text-decoration: none; +} + +.projects-footer a:hover { + text-decoration: underline; +} + +/* References */ +.reference-item { + margin-bottom: 0!important; + line-height: 1.4!important; + margin-left: 2rem!important; + font-size: 0.95rem!important; +} + +.reference-item a { + + color: var(--accent-blue); + text-decoration: none; + word-break: break-word; +} + +.reference-item a:hover { + text-decoration: underline; +} + +.ref-type { + display: block; + font-size: 0.8em; + color: var(--text-gray); + font-style: italic; + margin-top: 0.2rem; +} + +/* Footer */ +footer { + text-align: center; + padding: 2rem; + color: rgba(255,255,255,0.7); + font-size: 0.85rem; +} + +/* GitHub repository link styling */ +.github-repo-link { + color: whitesmoke !important; + transition: color 0.2s ease-in-out; +} + +.github-repo-link:hover { + color: #66B3FF !important; +} + + +/* CV Version Toggle Animations */ +@keyframes fadeInGrow { + from { + opacity: 0; + max-height: 0; + transform: scaleY(0.8); + transform-origin: top; + } + to { + opacity: 1; + max-height: 5000px; + transform: scaleY(1); + } +} + +@keyframes fadeOutShrink { + from { + opacity: 1; + max-height: 5000px; + transform: scaleY(1); + } + to { + opacity: 0; + max-height: 0; + transform: scaleY(0.8); + transform-origin: top; + } +} + +/* Elements that appear/disappear */ +.long-only, +.short-desc { + overflow: hidden; + transition: all 0.3s ease-in-out; +} + +/* Short CV - Hide detailed content with animation */ +.cv-short .long-only { + display: none; + animation: fadeOutShrink 0.3s ease-in-out; +} + +.cv-short .short-desc { + display: block; + animation: fadeInGrow 0.3s ease-in-out; +} + +/* Long CV - Hide short descriptions with animation */ +.cv-long .short-desc, +.short-desc { + display: none; + animation: fadeOutShrink 0.3s ease-in-out; +} + +.cv-long .long-only { + display: block; + animation: fadeInGrow 0.3s ease-in-out; +} + +.cv-long .responsibilities { + display: block; + animation: fadeInGrow 0.3s ease-in-out; +} + + diff --git a/static/css/03-components/_sidebar.css b/static/css/03-components/_sidebar.css new file mode 100644 index 0000000..185faf5 --- /dev/null +++ b/static/css/03-components/_sidebar.css @@ -0,0 +1,157 @@ +/* ============================================================================ + SIDEBAR COMPONENT + ============================================================================ */ + +/* Sidebar - Left/Right columns */ +.cv-sidebar { + background: var(--sidebar-bg); + padding: 4rem 1.5rem; + font-size: 0.9rem; +} + +/* Sidebar Accordion - Hidden on desktop, visible on mobile */ +.sidebar-accordion-header { + display: none; +} + +.sidebar-section { + margin-bottom: 2rem; + + /* Add margin when section is collapsed */ + &:has(details:not([open])) { + margin-bottom: 3rem; + margin-top: 0rem; + } + + /* Collapsible Details */ + details { + margin: 0; + + summary ~ * { + overflow: hidden; + max-height: 0; + opacity: 0; + transform: translateY(-8px); + transition: max-height 0.5s ease-in-out, + opacity 0.3s ease-in-out, + transform 0.3s ease-in-out; + } + + &[open] summary ~ * { + max-height: 1500px; + opacity: 1; + transform: translateY(0); + } + + &[open] .sidebar-content { + margin-top: 0.5rem; + } + } + + summary { + cursor: pointer; + list-style: none; + user-select: none; + position: relative; + display: flex; + align-items: center; + justify-content: space-between; + + /* Remove default triangle marker */ + &::-webkit-details-marker, + &::marker { + display: none; + } + + .sidebar-title { + margin-bottom: 0; + } + + &:hover .sidebar-title { + color: var(--accent-blue); + } + + &:hover::after, + details:not([open]) &::after { + opacity: 1; + } + } +} + +.sidebar-title { + font-family: 'Quicksand', sans-serif; + font-size: 1.4em; + font-weight: 700; + line-height: 1.3em; + margin-bottom: 10px; + padding: 0; + color: rgb(51, 51, 51); + text-align: left; +} + +.sidebar-content { + font-family: 'Quicksand', sans-serif; + font-size: 0.95rem; + font-weight: 400; + line-height: 1.5; +} + +.skill-item { + margin-bottom: 0.15rem; + color: rgb(0, 0, 0); + font-weight: 400; +} + +/* Left Sidebar Specific */ +.cv-sidebar-left { + .sidebar-section summary::after { + content: '▶'; + font-size: 0.8em; + color: rgb(100, 100, 100); + transition: transform 0.2s ease, opacity 0.2s ease; + opacity: 0; + margin-left: 15px; + flex-shrink: 0; + } + + .sidebar-section details[open] summary::after { + transform: rotate(90deg); + } + + .sidebar-content, + .skill-item { + text-align: left; + } +} + +/* Right Sidebar Specific */ +.cv-sidebar-right { + .sidebar-section summary { + flex-direction: row-reverse; + justify-content: space-between; + + .sidebar-title { + text-align: right; + width: 100%; + } + + &::after { + content: '▶'; + font-size: 0.8em; + color: rgb(100, 100, 100); + transition: transform 0.2s ease, opacity 0.2s ease; + opacity: 0; + margin-right: 15px; + flex-shrink: 0; + } + } + + .sidebar-section details[open] summary::after { + transform: rotate(90deg); + } + + .sidebar-content, + .skill-item { + text-align: right; + } +} diff --git a/static/css/04-interactive/_hamburger.css b/static/css/04-interactive/_hamburger.css new file mode 100644 index 0000000..3a4daa3 --- /dev/null +++ b/static/css/04-interactive/_hamburger.css @@ -0,0 +1,391 @@ +/* Hamburger button */ +.hamburger-btn { + background: transparent; + border: none; + color: #fff; + cursor: pointer; + padding: 0.5rem; + display: flex; + align-items: center; + justify-content: center; + transition: background-color 0.2s ease; + border-radius: 4px; + margin: 0 0.5rem; + position: relative; /* For CSS-only hover trigger */ +} + + +.hamburger-btn:hover { + background-color: rgba(255, 255, 255, 0.1); +} + +.hamburger-btn:active { + background-color: rgba(255, 255, 255, 0.2); +} + +/* Navigation Menu */ +.navigation-menu { + position: fixed; + top: 50px; /* Height of action bar */ + left: 0; + width: 280px; + max-height: 0; + background: #ffffff; + box-shadow: 2px 0 10px rgba(0, 0, 0, 0.15); + transition: max-height 0.5s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease; + overflow-y: auto; + z-index: 1000; /* Above fixed buttons (z-index: 999) */ + pointer-events: none; /* Disable pointer events when hidden */ + opacity: 0; +} + +/* Pure CSS Menu Activation - Show menu when hovering hamburger OR menu */ +/* Show when hovering the hamburger button (adjacent in DOM after site-title-left) */ +.hamburger-btn:hover ~ .navigation-menu, +.hamburger-btn:focus ~ .navigation-menu, +/* Show when hovering the menu itself */ +.navigation-menu:hover, +/* Legacy class for backward compatibility */ +.navigation-menu.menu-hover, +.navigation-menu.menu-open { + max-height: calc(100vh - 60px); /* Viewport height minus header + some spacing */ + pointer-events: auto; /* Enable pointer events when visible */ + opacity: 1; +} + +.menu-content { + padding: 1rem 0; +} + +.menu-item { + display: flex; + align-items: center; + gap: 1rem; + padding: 0.875rem 1.5rem; + color: var(--text-dark); + text-decoration: none; + transition: background-color 0.2s ease, color 0.2s ease; + font-size: 0.95rem; + font-weight: 500; + border-left: 3px solid transparent; +} + +.menu-item:hover { + background-color: rgba(0, 102, 204, 0.08); + color: var(--accent-blue); + border-left-color: var(--accent-blue); + text-decoration: none; +} + +.menu-item iconify-icon { + color: var(--text-gray); + flex-shrink: 0; + transition: color 0.2s ease; +} + +.menu-item:hover iconify-icon { + color: var(--accent-blue); +} + +/* Menu item action controls (Expand All, Collapse All) */ +/* Removed centered text styling - action items now behave like regular menu items */ + +/* Remove extra padding - all menu items should align consistently */ + +/* Submenu styles - hover triggered, opens to the right */ +.menu-item-submenu { + position: relative; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + padding: 0 0 1rem 0; +} + +.menu-item.has-submenu { + justify-content: space-between; + position: relative; +} + +.submenu-arrow { + transition: transform 0.2s ease; + margin-left: auto; +} + +/* Rotate arrow slightly on hover */ +.menu-item-submenu:hover .submenu-arrow { + transform: translateX(3px); +} + +.submenu-content { + position: fixed; /* Changed from absolute to fixed to break out of parent overflow */ + left: 232px; /* Slight overlap with menu to eliminate any gap */ + background: #ffffff; + box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.15); + border-radius: 8px; + min-width: 250px; + max-width: 300px; + opacity: 0; + visibility: hidden; + transform: translateX(-3px); + transition: all 0.3s ease; + z-index: 1000; /* Higher z-index to appear above everything */ + padding: 0.5rem 0; + max-height: calc(100vh - 100px); /* Ensure it fits viewport */ + overflow-y: auto; /* Scroll if content is too long */ +} + +/* Show submenu when hovering the submenu container OR the submenu itself */ +.menu-item-submenu:hover .submenu-content, +.submenu-content:hover { + opacity: 1; + visibility: visible; + transform: translateX(0); +} + +/* Legacy class for JS compatibility */ +.menu-item-submenu.submenu-open .submenu-arrow { + transform: translateX(3px); +} + +.menu-item-submenu.submenu-open .submenu-content { + opacity: 1; + visibility: visible; + transform: translateX(0); +} + +.submenu-content .menu-item { + padding: 0.875rem 1.5rem; + font-size: 0.9rem; + border-left: 3px solid transparent; + border-radius: 0; +} + +.submenu-content .menu-item:first-child { + border-top-left-radius: 8px; + border-top-right-radius: 8px; +} + +.submenu-content .menu-item:last-child { + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; +} + +/* ========== Menu Sections with Separators ========== */ +/* Quick Actions section - always visible */ +.menu-section-wrapper { + padding: 0.5rem 1.5rem 1rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} + +/* Remove border from last visible section */ +.menu-content > *:last-child, +.menu-content > div:last-child { + border-bottom: none !important; +} + +/* ========== Menu Controls & Actions (Always Visible) ========== */ +/* Always visible in hamburger menu at all screen sizes */ +.menu-controls-section, +.menu-actions-section { + display: block; + padding: 0.5rem 1.5rem 1rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} + +.menu-item-header { + display: flex; + align-items: center; + gap: 1rem; + padding: 0.875rem 0 0.875rem 0; + color: var(--text-dark); + font-size: 0.85rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.5px; + cursor: default; +} + +/* Disable hover effect for headers */ +.menu-item-header:hover { + background-color: transparent !important; + color: var(--text-dark) !important; + border-left-color: transparent !important; +} + +.menu-item-header iconify-icon { + color: var(--text-gray); + flex-shrink: 0; +} + +.menu-item-header:hover iconify-icon { + color: var(--text-gray) !important; +} + +.menu-item-header span { + flex: 1; +} + +.menu-control-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.75rem 0; +} + +.menu-control-label { + display: flex; + align-items: center; + gap: 0.75rem; + color: var(--text-dark); + font-size: 0.9rem; + font-weight: 500; +} + +.menu-control-label iconify-icon { + color: var(--text-gray); +} + +.menu-action-btn { + display: flex; + align-items: center; + justify-content: center; + gap: 1rem; + padding: 0.875rem 1rem; + margin: 0.25rem 0; + background: rgba(0, 0, 0, 0.03); + border: none; + border-radius: 8px; + color: var(--text-dark); + text-decoration: none; + font-size: 0.9rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; + width: 100%; +} + +.menu-action-btn:hover { + background: rgba(0, 102, 204, 0.08); + color: var(--accent-blue); + text-decoration: none; +} + +.menu-action-btn iconify-icon { + color: var(--text-gray); + flex-shrink: 0; + transition: color 0.2s ease; +} + +.menu-action-btn:hover iconify-icon { + color: var(--accent-blue); +} + +/* PDF button in menu - White bg with red icon on hover */ +.menu-pdf-btn:hover, +.menu-pdf-btn.pdf-hover-sync { + background: white !important; + color: #e74c3c !important; +} + +.menu-pdf-btn:hover iconify-icon, +.menu-pdf-btn.pdf-hover-sync iconify-icon { + color: #e74c3c !important; +} + +/* Print button in menu - White bg with green icon on hover */ +.menu-print-btn:hover, +.menu-print-btn.print-hover-sync { + background: white !important; + color: #27ae60 !important; +} + +.menu-print-btn:hover iconify-icon, +.menu-print-btn.print-hover-sync iconify-icon { + color: #27ae60 !important; +} + +/* Section icons in titles */ +.section-icon { + vertical-align: middle; + margin-right: 0.5rem; + color: #7d7d7d; +} + +/* Add invisible separator (blank space) below section titles */ +#experience .section-title, +#awards .section-title, +#courses .section-title, +#projects .section-title { + margin-bottom: 40px !important; +} + +/* Smooth scrolling */ +html { + scroll-behavior: smooth; +} + +/* Add scroll padding to account for fixed header */ +html { + scroll-padding-top: 70px; /* Action bar height + some spacing */ +} + +/* Mobile responsive */ +@media (max-width: 768px) { + .navigation-menu { + width: 240px; + } + + .menu-item { + padding: 0.75rem 1rem; + font-size: 0.9rem; + } + + .site-title { + justify-content: space-between; + width: 100%; + } +} + +/* Hide menu overlay on print */ +@media print { + .navigation-menu { + display: none !important; + } + + .hamburger-btn { + display: none !important; + } +} + +/* ======================================== + Scroll Direction - Hide/Show Header + ======================================== */ + +/* Add smooth transition to header elements */ +.action-bar, +.navigation-menu { + transition: transform 0.3s ease-in-out; +} + +/* Hide header when scrolling down */ +.action-bar.header-hidden { + transform: translateY(-100%); +} + +.navigation-menu.header-hidden { + transform: translateY(-100%); +} + +/* ======================================== + Back to Top Button + ======================================== */ + +.back-to-top { + position: fixed; + bottom: 2rem; + right: 2rem; + width: 50px; + height: 50px; + background: var(--black-bar); + color: white; + border: none; + border-radius: 50%; + cursor: pointer; diff --git a/static/css/04-interactive/_remaining.css b/static/css/04-interactive/_remaining.css new file mode 100644 index 0000000..664c3f1 --- /dev/null +++ b/static/css/04-interactive/_remaining.css @@ -0,0 +1,2287 @@ +/* Hamburger button */ +.hamburger-btn { + background: transparent; + border: none; + color: #fff; + cursor: pointer; + padding: 0.5rem; + display: flex; + align-items: center; + justify-content: center; + transition: background-color 0.2s ease; + border-radius: 4px; + margin: 0 0.5rem; + position: relative; /* For CSS-only hover trigger */ +} + + +.hamburger-btn:hover { + background-color: rgba(255, 255, 255, 0.1); +} + +.hamburger-btn:active { + background-color: rgba(255, 255, 255, 0.2); +} + +/* Navigation Menu */ +.navigation-menu { + position: fixed; + top: 50px; /* Height of action bar */ + left: 0; + width: 280px; + max-height: 0; + background: #ffffff; + box-shadow: 2px 0 10px rgba(0, 0, 0, 0.15); + transition: max-height 0.5s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease; + overflow-y: auto; + z-index: 1000; /* Above fixed buttons (z-index: 999) */ + pointer-events: none; /* Disable pointer events when hidden */ + opacity: 0; +} + +/* Pure CSS Menu Activation - Show menu when hovering hamburger OR menu */ +/* Show when hovering the hamburger button (adjacent in DOM after site-title-left) */ +.hamburger-btn:hover ~ .navigation-menu, +.hamburger-btn:focus ~ .navigation-menu, +/* Show when hovering the menu itself */ +.navigation-menu:hover, +/* Legacy class for backward compatibility */ +.navigation-menu.menu-hover, +.navigation-menu.menu-open { + max-height: calc(100vh - 60px); /* Viewport height minus header + some spacing */ + pointer-events: auto; /* Enable pointer events when visible */ + opacity: 1; +} + +.menu-content { + padding: 1rem 0; +} + +.menu-item { + display: flex; + align-items: center; + gap: 1rem; + padding: 0.875rem 1.5rem; + color: var(--text-dark); + text-decoration: none; + transition: background-color 0.2s ease, color 0.2s ease; + font-size: 0.95rem; + font-weight: 500; + border-left: 3px solid transparent; +} + +.menu-item:hover { + background-color: rgba(0, 102, 204, 0.08); + color: var(--accent-blue); + border-left-color: var(--accent-blue); + text-decoration: none; +} + +.menu-item iconify-icon { + color: var(--text-gray); + flex-shrink: 0; + transition: color 0.2s ease; +} + +.menu-item:hover iconify-icon { + color: var(--accent-blue); +} + +/* Menu item action controls (Expand All, Collapse All) */ +/* Removed centered text styling - action items now behave like regular menu items */ + +/* Remove extra padding - all menu items should align consistently */ + +/* Submenu styles - hover triggered, opens to the right */ +.menu-item-submenu { + position: relative; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + padding: 0 0 1rem 0; +} + +.menu-item.has-submenu { + justify-content: space-between; + position: relative; +} + +.submenu-arrow { + transition: transform 0.2s ease; + margin-left: auto; +} + +/* Rotate arrow slightly on hover */ +.menu-item-submenu:hover .submenu-arrow { + transform: translateX(3px); +} + +.submenu-content { + position: fixed; /* Changed from absolute to fixed to break out of parent overflow */ + left: 232px; /* Slight overlap with menu to eliminate any gap */ + background: #ffffff; + box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.15); + border-radius: 8px; + min-width: 250px; + max-width: 300px; + opacity: 0; + visibility: hidden; + transform: translateX(-3px); + transition: all 0.3s ease; + z-index: 1000; /* Higher z-index to appear above everything */ + padding: 0.5rem 0; + max-height: calc(100vh - 100px); /* Ensure it fits viewport */ + overflow-y: auto; /* Scroll if content is too long */ +} + +/* Show submenu when hovering the submenu container OR the submenu itself */ +.menu-item-submenu:hover .submenu-content, +.submenu-content:hover { + opacity: 1; + visibility: visible; + transform: translateX(0); +} + +/* Legacy class for JS compatibility */ +.menu-item-submenu.submenu-open .submenu-arrow { + transform: translateX(3px); +} + +.menu-item-submenu.submenu-open .submenu-content { + opacity: 1; + visibility: visible; + transform: translateX(0); +} + +.submenu-content .menu-item { + padding: 0.875rem 1.5rem; + font-size: 0.9rem; + border-left: 3px solid transparent; + border-radius: 0; +} + +.submenu-content .menu-item:first-child { + border-top-left-radius: 8px; + border-top-right-radius: 8px; +} + +.submenu-content .menu-item:last-child { + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; +} + +/* ========== Menu Sections with Separators ========== */ +/* Quick Actions section - always visible */ +.menu-section-wrapper { + padding: 0.5rem 1.5rem 1rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} + +/* Remove border from last visible section */ +.menu-content > *:last-child, +.menu-content > div:last-child { + border-bottom: none !important; +} + +/* ========== Menu Controls & Actions (Always Visible) ========== */ +/* Always visible in hamburger menu at all screen sizes */ +.menu-controls-section, +.menu-actions-section { + display: block; + padding: 0.5rem 1.5rem 1rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} + +.menu-item-header { + display: flex; + align-items: center; + gap: 1rem; + padding: 0.875rem 0 0.875rem 0; + color: var(--text-dark); + font-size: 0.85rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.5px; + cursor: default; +} + +/* Disable hover effect for headers */ +.menu-item-header:hover { + background-color: transparent !important; + color: var(--text-dark) !important; + border-left-color: transparent !important; +} + +.menu-item-header iconify-icon { + color: var(--text-gray); + flex-shrink: 0; +} + +.menu-item-header:hover iconify-icon { + color: var(--text-gray) !important; +} + +.menu-item-header span { + flex: 1; +} + +.menu-control-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.75rem 0; +} + +.menu-control-label { + display: flex; + align-items: center; + gap: 0.75rem; + color: var(--text-dark); + font-size: 0.9rem; + font-weight: 500; +} + +.menu-control-label iconify-icon { + color: var(--text-gray); +} + +.menu-action-btn { + display: flex; + align-items: center; + justify-content: center; + gap: 1rem; + padding: 0.875rem 1rem; + margin: 0.25rem 0; + background: rgba(0, 0, 0, 0.03); + border: none; + border-radius: 8px; + color: var(--text-dark); + text-decoration: none; + font-size: 0.9rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; + width: 100%; +} + +.menu-action-btn:hover { + background: rgba(0, 102, 204, 0.08); + color: var(--accent-blue); + text-decoration: none; +} + +.menu-action-btn iconify-icon { + color: var(--text-gray); + flex-shrink: 0; + transition: color 0.2s ease; +} + +.menu-action-btn:hover iconify-icon { + color: var(--accent-blue); +} + +/* PDF button in menu - White bg with red icon on hover */ +.menu-pdf-btn:hover, +.menu-pdf-btn.pdf-hover-sync { + background: white !important; + color: #e74c3c !important; +} + +.menu-pdf-btn:hover iconify-icon, +.menu-pdf-btn.pdf-hover-sync iconify-icon { + color: #e74c3c !important; +} + +/* Print button in menu - White bg with green icon on hover */ +.menu-print-btn:hover, +.menu-print-btn.print-hover-sync { + background: white !important; + color: #27ae60 !important; +} + +.menu-print-btn:hover iconify-icon, +.menu-print-btn.print-hover-sync iconify-icon { + color: #27ae60 !important; +} + +/* Section icons in titles */ +.section-icon { + vertical-align: middle; + margin-right: 0.5rem; + color: #7d7d7d; +} + +/* Add invisible separator (blank space) below section titles */ +#experience .section-title, +#awards .section-title, +#courses .section-title, +#projects .section-title { + margin-bottom: 40px !important; +} + +/* Smooth scrolling */ +html { + scroll-behavior: smooth; +} + +/* Add scroll padding to account for fixed header */ +html { + scroll-padding-top: 70px; /* Action bar height + some spacing */ +} + +/* Mobile responsive */ +@media (max-width: 768px) { + .navigation-menu { + width: 240px; + } + + .menu-item { + padding: 0.75rem 1rem; + font-size: 0.9rem; + } + + .site-title { + justify-content: space-between; + width: 100%; + } +} + +/* Hide menu overlay on print */ +@media print { + .navigation-menu { + display: none !important; + } + + .hamburger-btn { + display: none !important; + } +} + +/* ======================================== + Scroll Direction - Hide/Show Header + ======================================== */ + +/* Add smooth transition to header elements */ +.action-bar, +.navigation-menu { + transition: transform 0.3s ease-in-out; +} + +/* Hide header when scrolling down */ +.action-bar.header-hidden { + transform: translateY(-100%); +} + +.navigation-menu.header-hidden { + transform: translateY(-100%); +} + +/* ======================================== + Back to Top Button + ======================================== */ + +.back-to-top { + position: fixed; + bottom: 2rem; + right: 2rem; + width: 50px; + height: 50px; + background: var(--black-bar); + color: white; + border: none; + border-radius: 50%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + z-index: 99; + transition: all 0.3s ease; + opacity: 0.2; +} + +.back-to-top:hover { + opacity: 1; + transform: translateY(-3px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); + background: #27ae60; +} + +.back-to-top.at-bottom { + opacity: 1; + background: #27ae60; +} + +.back-to-top:active { + transform: translateY(-1px); + box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3); +} + +/* Mobile adjustments */ +@media (max-width: 768px) { + .back-to-top { + bottom: 1.5rem; + right: 1.5rem; + width: 45px; + height: 45px; + } +} + +/* ======================================== + Info Button (Bottom Left) + ======================================== */ + +.info-button { + position: fixed; + bottom: 2rem; + left: 2rem; + width: 50px; + height: 50px; + background: var(--black-bar); + color: white; + border: none; + border-radius: 50%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + z-index: 99; + transition: all 0.3s ease; + opacity: 0.6; /* Increased from 0.2 for better discoverability */ +} + +.info-button:hover { + opacity: 1; + transform: translateY(-3px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); + background: #27ae60; +} + +.info-button.at-bottom { + opacity: 1; + background: #27ae60; +} + +.info-button:active { + transform: translateY(-1px); + box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3); +} + +/* Mobile adjustments - Flexbox button layout at bottom center */ +@media (max-width: 900px) { + /* Hide only zoom control on mobile */ + .zoom-toggle-btn, + .zoom-control { + display: none !important; + } + + /* Reset fixed positioning for FLEXBOX buttons on mobile (exclude back-to-top) */ + .download-btn, + .print-friendly-btn, + .shortcuts-btn, + .info-button { + position: fixed !important; + bottom: 1.5rem !important; + left: auto !important; + right: auto !important; + width: 50px !important; + height: 50px !important; + opacity: 0.7 !important; + transform: none !important; + } + + /* Keep back-to-top button at bottom-right (same as desktop) */ + .back-to-top { + position: fixed !important; + bottom: 1.5rem !important; + right: 1.5rem !important; + width: 50px !important; + height: 50px !important; + } + + /* Flexbox container behavior - buttons arrange themselves */ + /* Buttons will be positioned using JavaScript or individual positioning */ + /* For now, use fixed spacing from center */ + + /* 5 buttons: Download, Print, Shortcuts, Theme, Info */ + /* Spacing: 10px gap between buttons, centered horizontally */ + /* Total width: 5 * 50px + 4 * 10px = 290px */ + /* Start position: 50% - 145px */ + + .download-btn { + left: calc(50% - 145px) !important; /* First button */ + } + + .print-friendly-btn { + left: calc(50% - 85px) !important; /* Second button */ + } + + .shortcuts-btn { + left: calc(50% - 25px) !important; /* Third button */ + } + + /* Theme switcher button - fourth position (defined in color-theme.css) */ + /* left: calc(50% + 35px) !important; */ + + .info-button { + left: calc(50% + 95px) !important; /* Fifth button (last) */ + } + + /* Hover effects - only Y transform + enhanced shadow */ + .download-btn:hover, + .download-btn.pdf-hover-sync, + .print-friendly-btn:hover, + .print-friendly-btn.print-hover-sync, + .shortcuts-btn:hover, + .info-button:hover, + .back-to-top:hover { + transform: translateY(-3px) !important; + opacity: 1 !important; + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4) !important; + } + + /* Keep at-bottom state without transform */ + .info-button.at-bottom, + .shortcuts-btn.at-bottom { + opacity: 1 !important; + transform: none !important; + } +} + +/* Very narrow mobile - Move back-to-top UP on RIGHT side to avoid overlap */ +@media (max-width: 483px) { + .back-to-top { + /* Stay on RIGHT side, just move UP higher */ + right: 1.5rem !important; + bottom: 5.5rem !important; /* Higher position to clear bottom button row */ + } +} + +/* ======================================== + Info Modal - Modern Glassmorphism Design + ======================================== */ + +/* Native element - force centering */ +.info-modal { + border: none; + border-radius: 24px; + padding: 0; + max-width: 420px; + width: calc(100% - 2rem); + background: transparent; + /* Force centering - override any browser defaults */ + position: fixed; + inset: 0; + margin: auto; + /* Constrain height so margin:auto can center vertically */ + max-height: fit-content; +} + +/* Native ::backdrop pseudo-element replaces manual backdrop div */ +.info-modal::backdrop { + background: rgba(0, 0, 0, 0.7); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); +} + +/* Dialog opening animation - native dialog uses [open] attribute */ +.info-modal[open] { + animation: modalFadeIn 0.3s ease; +} + +@keyframes modalFadeIn { + from { + opacity: 0; + transform: scale(0.9) translateY(20px); + } + to { + opacity: 1; + transform: scale(1) translateY(0); + } +} + +.info-modal-content { + background: linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.9) 100%); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + border-radius: 24px; + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3), 0 0 100px rgba(39, 174, 96, 0.1); + width: 100%; + padding: 2.5rem; + position: relative; + border: 1px solid rgba(255, 255, 255, 0.8); +} + +.info-modal-close { + position: absolute; + top: 1rem; + right: 1rem; + background: rgba(0, 0, 0, 0.05); + border: none; + width: 40px; + height: 40px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + color: var(--text-primary); + transition: all 0.2s ease; + z-index: 10; +} + +.info-modal-close:hover { + background: rgba(0, 0, 0, 0.1); + transform: rotate(90deg); +} + +.info-modal-header { + text-align: center; + margin-bottom: 2rem; +} + +.info-modal-header h2 { + font-size: 1.5rem; + font-weight: 600; + color: var(--text-primary); + margin: 0 0 1.5rem 0; +} + +.info-modal-cv-title { + font-size: 1.5rem; + font-weight: 700; + color: #f39c12; /* Orange subtitle */ + margin-bottom: 0; + letter-spacing: 0.05em; + display: flex; + align-items: center; + gap: 0.5rem; + justify-content: center; +} + +#info-modal .info-modal-cv-title { + color: #27ae60; +} + +.info-modal-photo { + width: 40px; + height: 53px; + object-fit: cover; + border-radius: 4px; + border: none; + box-shadow: none; +} + +.photo-bracket-wrapper { + position: relative; + display: inline-flex; + align-items: center; + padding: 0 22px; +} + +.photo-bracket-wrapper::before { + content: '{'; + position: absolute; + left: 2px; + font-size: 2rem; + font-weight: 700; + color: #27ae60; + line-height: 1; + top: 8px; +} + +.photo-bracket-wrapper::after { + content: '}'; + position: absolute; + right: 2px; + font-size: 2rem; + font-weight: 700; + color: #27ae60; + line-height: 1; + top: 8px; +} + +.info-modal-body { + color: #333; +} + +.info-modal-description { + font-size: 1rem; + line-height: 1.6; + margin-bottom: 2rem; + color: #444; +} + +.info-modal-description strong { + color: #27ae60; + font-weight: 600; +} + +.info-modal-tech { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 1rem; + margin-bottom: 2rem; +} + +.info-tech-item { + display: flex; + align-items: center; + justify-content: center; + gap: 0.75rem; + padding: 0.75rem; + background: rgba(39, 174, 96, 0.05); + border-radius: 12px; + border: 1px solid rgba(39, 174, 96, 0.1); + transition: all 0.3s ease; +} + +.info-tech-item:hover { + background: rgba(39, 174, 96, 0.1); + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(39, 174, 96, 0.2); +} + +.info-tech-item iconify-icon { + color: #27ae60; + flex-shrink: 0; +} + +.info-tech-item span { + font-size: 0.9rem; + font-weight: 500; + color: #333; +} + +.info-modal-github { + display: flex; + align-items: center; + justify-content: center; + gap: 0.75rem; + padding: 1rem 1.5rem; + background: linear-gradient(135deg, #27ae60 0%, #229954 100%); + color: white; + text-decoration: none; + border-radius: 12px; + font-weight: 600; + font-size: 1rem; + transition: all 0.3s ease; + box-shadow: 0 4px 15px rgba(39, 174, 96, 0.3); +} + +.info-modal-github:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(39, 174, 96, 0.4); + background: linear-gradient(135deg, #229954 0%, #27ae60 100%); +} + +.info-modal-github:active { + transform: translateY(0); + box-shadow: 0 4px 15px rgba(39, 174, 96, 0.3); +} + +.info-modal-github-subtext { + text-align: center; + font-size: 0.9rem; + color: #666; + margin-top: 1.5rem; + margin-bottom: 1rem; + font-style: italic; +} + +/* Mobile responsive */ +@media (max-width: 768px) { + .info-modal-content { + padding: 2rem 1.5rem; + max-width: calc(100% - 2rem); + } + + .info-modal-header h2 { + font-size: 1.5rem; + } + + .info-modal-tech { + grid-template-columns: 1fr; + } + + .info-modal-description { + font-size: 0.95rem; + } +} + +/* ======================================== + Desktop: Ensure Sidebar Content Visible (>1280px) + ======================================== */ + +/* ======================================== + Responsive: Medium Screens (901px - 1023px) + ======================================== */ + +@media (min-width: 901px) and (max-width: 1023px) { + + /* ========== Global Font Size Reduction ========== */ + html { + font-size: 14px; /* Reduced from default 16px */ + } + + .cv-name { + font-size: 1.8em; /* Reduced from 2.2em */ + } + + .sidebar-title { + font-size: 0.95rem; + } + + .sidebar-content { + font-size: 0.9rem; + } + + /* ========== Selector Labels - Hide, Show on Hover ========== */ + .selector-label { + max-width: 0; + overflow: hidden; + opacity: 0; + transition: all 0.3s ease; + white-space: nowrap; + } + + .selector-group:hover .selector-label { + max-width: 200px; + opacity: 1; + margin-right: 0.75rem; + } + + /* ========== Language Selector - Collapse to EN/ES ========== */ + .language-selector .selector-btn { + position: relative; + padding: 0.4rem 1rem; /* Keep padding consistent */ + min-width: 50px; + font-size: 0; /* Hide actual text */ + overflow: visible; + transition: font-size 0.3s ease; /* Slower animation */ + display: inline-flex; + justify-content: center; + align-items: center; + } + + /* Show only short version (EN/ES) */ + .language-selector .selector-btn::before { + content: attr(data-short); + font-size: 1rem; /* Restore font size for pseudo-element */ + opacity: 1; + transition: opacity 0.3s ease; /* Slower animation */ + display: block; + width: 100%; + text-align: center; + } + + /* On hover of INDIVIDUAL button only, show full text */ + .language-selector .selector-btn:hover { + font-size: 1rem; /* Restore font size to show full text */ + min-width: auto; + } + + .language-selector .selector-btn:hover::before { + content: ''; /* Hide short version */ + opacity: 0; + } + + /* ========== Action Buttons - Icon Only, Expand on Hover ========== */ + .action-btn { + position: relative; + width: 45px; + overflow: hidden; + transition: width 0.3s ease, padding 0.3s ease; + white-space: nowrap; + text-indent: 0; + } + + /* Hide button text, keep icon */ + .action-btn iconify-icon { + flex-shrink: 0; + } + + .action-btn { + font-size: 0; + padding: 0 0.65rem; + justify-content: center; + } + + /* On hover, show text */ + .action-btn:hover { + width: auto; + font-size: 0.95rem; + padding: 0.65rem 1.5rem; + gap: 0.5rem; + } + + /* ========== Sidebar Content - Hide Text, Show on Hover ========== */ + .sidebar-content { + max-height: 0 !important; + overflow: hidden !important; + opacity: 0 !important; + } + + /* Show sidebar content on hover */ + .skill-category:hover .sidebar-content, + .cv-sidebar-section:hover .sidebar-content { + max-height: 1000px !important; + opacity: 1 !important; + margin-top: 10px !important; + } +} + +/* ======================================== + Responsive: Medium Screens (1024px - 1280px) + ======================================== */ + +@media (min-width: 1024px) and (max-width: 1280px) { + + /* ========== Global Font Size Reduction ========== */ + html { + font-size: 14px; /* Reduced from default 16px */ + } + + .cv-name { + font-size: 1.8em; /* Reduced from 2.2em */ + } + + .sidebar-title { + font-size: 0.95rem; + } + + .sidebar-content { + font-size: 0.9rem; + } + + /* ========== Selector Labels - Hide, Show on Hover ========== */ + .selector-label { + max-width: 0; + overflow: hidden; + opacity: 0; + transition: all 0.3s ease; + white-space: nowrap; + } + + .selector-group:hover .selector-label { + max-width: 200px; + opacity: 1; + margin-right: 0.75rem; + } + + /* ========== Language Selector - Collapse to EN/ES ========== */ + .language-selector .selector-btn { + position: relative; + padding: 0.4rem 1rem; /* Keep padding consistent */ + min-width: 50px; + font-size: 0; /* Hide actual text */ + overflow: visible; + transition: font-size 0.3s ease; /* Slower animation */ + display: inline-flex; + justify-content: center; + align-items: center; + } + + /* Show only short version (EN/ES) */ + .language-selector .selector-btn::before { + content: attr(data-short); + font-size: 1rem; /* Restore font size for pseudo-element */ + opacity: 1; + transition: opacity 0.3s ease; /* Slower animation */ + display: block; + width: 100%; + text-align: center; + } + + /* On hover of INDIVIDUAL button only, show full text */ + .language-selector .selector-btn:hover { + font-size: 1rem; /* Restore font size to show full text */ + min-width: auto; + } + + .language-selector .selector-btn:hover::before { + content: ''; /* Hide short version */ + opacity: 0; + } + + /* ========== Action Buttons - Icon Only, Expand on Hover ========== */ + .action-btn { + position: relative; + width: 45px; + overflow: hidden; + transition: width 0.3s ease, padding 0.3s ease; + white-space: nowrap; + text-indent: 0; + } + + /* Hide button text, keep icon */ + .action-btn iconify-icon { + flex-shrink: 0; + } + + .action-btn { + font-size: 0; + padding: 0 0.65rem; + justify-content: center; + } + + /* On hover, show text */ + .action-btn:hover { + width: auto; + font-size: 0.95rem; + padding: 0.65rem 1.5rem; + gap: 0.5rem; + } + + /* ========== Sidebar Content - Hide Text, Show on Hover ========== */ + .sidebar-content { + max-height: 0 !important; + overflow: hidden !important; + opacity: 0 !important; + } + + /* Show sidebar content on hover */ + .skill-category:hover .sidebar-content, + .cv-sidebar-section:hover .sidebar-content { + max-height: 1000px !important; + opacity: 1 !important; + margin-top: 10px !important; + } +} + +/* ======================================== + Responsive: Small Screens (up to 540px) + ======================================== */ + +/* ======================================== + Responsive: Tablet Screens - Center Photo (up to 768px) + ======================================== */ + +@media (max-width: 768px) { + /* ======================================== + TYPOGRAPHY - Subtle font size reductions + ======================================== */ + .cv-name { + text-align: center; + font-size: 1.6rem; + } + + .years-experience { + text-align: center; + font-size: 1.1em; + } + + .section-title { + font-size: 1.2em; + } + + .sidebar-title { + font-size: 1.2em; + } + + .experience-period, + .experience-separator, + .experience-location, + .experience-duration { + font-size: 0.95rem; + } + + .position { + font-size: 0.95rem; + } + + .short-desc, + .responsibilities li { + font-size: 0.85rem; + } + + /* ======================================== + TEXT ALIGNMENT FIXES - Selective alignment + ======================================== */ + /* Keep justified for intro and skills */ + .intro-text, + .summary-text { + text-align: justify; + font-size: 0.85rem; + line-height: 1.5; + } + + .intro-text { + margin-top: 0; + width: 100%; + } + + /* Left-align for course/project descriptions */ + .course-desc, + .project-desc { + text-align: left !important; + font-size: 0.85rem !important; + line-height: 1.5; + } + + /* ======================================== + HEADER LAYOUT - Centered photo + ======================================== */ + .cv-header-content { + flex-direction: column; + align-items: center; + gap: 1rem; + } + + .cv-header-left { + width: 100%; + position: static; + padding-right: 0; + } + + .cv-photo { + position: static; + width: auto; + height: auto; + max-width: 250px; + margin: 1.5rem auto; + text-align: center; + right: auto; + top: auto; + } + + .cv-photo img { + width: 100%; + height: auto; + max-height: none; + } + + /* ======================================== + UNIFIED LOGO/ICON SIZING - Consistent 60px + ======================================== */ + .company-logo, + .course-icon, + .project-icon, + .award-logo { + width: 60px !important; + height: 60px !important; + flex-shrink: 0; + } + + .company-logo img, + .course-icon img, + .project-icon img, + .award-logo img { + width: 60px !important; + height: 60px !important; + object-fit: contain; + } + + /* Default icons inherit base 80px size from _toggles.css */ + /* Removed !important to allow base styles to apply */ + + /* ======================================== + CONSISTENT ITEM LAYOUT - Uniform spacing + ======================================== */ + .experience-item, + .course-item, + .project-item, + .award-item { + display: flex; + flex-direction: row; + gap: 1rem !important; + align-items: flex-start; + margin-bottom: 2rem !important; + padding-bottom: 1.5rem !important; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + } + + .experience-item { + margin-bottom: 1.8rem !important; + } + + .experience-content, + .course-content, + .project-content, + .award-content { + flex: 1; + min-width: 0; + } + + /* ======================================== + FONT SIZE CONSISTENCY - Titles and descriptions + ======================================== */ + .course-title, + .project-title, + .award-item strong { + font-size: 0.95rem !important; + line-height: 1.4; + } + + .course-item small, + .project-item small, + .award-item small { + font-size: 0.8rem !important; + } + + .course-desc, + .project-desc, + .award-desc { + font-size: 0.85rem !important; + line-height: 1.5; + } + + /* ======================================== + RESPONSIBILITIES MOBILE OPTIMIZATION + ======================================== */ + .responsibilities li:has(img), + .responsibilities li:has(iconify-icon) { + grid-template-columns: 60px 1fr !important; + gap: 0.75rem !important; + margin-bottom: 0.75rem !important; + } + + .responsibilities li img, + .responsibilities li iconify-icon.default-company-icon { + width: 60px !important; + height: 60px !important; + } + + /* ======================================== + SIDEBAR ITEMS MOBILE OPTIMIZATION + ======================================== */ + .language-item, + .reference-item, + .other-content { + margin-bottom: 0 !important; + line-height: 1.4 !important; + margin-left: 1rem !important; + font-size: 0.85rem !important; + } +} + +/* ======================================== + Responsive: All Mobile Screens (up to 540px) + ======================================== */ + +@media (max-width: 540px) { + /* Simplify action bar grid for mobile: single column */ + .action-bar-content { + grid-template-columns: 1fr; + gap: 0; + padding: 0; + } + + /* Hide center controls on mobile (moved to hamburger menu) */ + .view-controls-center { + display: none; + } + + /* Hide action buttons on small screens (available in hamburger menu) */ + .action-buttons-right { + display: none; + } + + /* Site title uses flexbox with percentage widths */ + .site-title { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + padding: 0 0.5rem; + gap: 0.5rem; + } + + /* Left group (hamburger + title) takes ~50-60% */ + .site-title-left { + display: flex; + align-items: center; + gap: 0.5rem; + flex: 1 1 1; + min-width: 0; + } + + /* Title link is flexible within left group */ + .site-title-link { + flex: 1 1 auto; + min-width: 0; + overflow: hidden; + } + + .site-title-text { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + /* Language selector takes ~30-35% */ + .language-selector { + display: flex; + flex: 0 0 35%; + margin-left: auto; + padding-left: 0; + margin-right: 0; + justify-content: flex-end; + gap: 0.25rem; + } + + /* Hide year from title in mobile view */ + .site-title-year { + display: none; + } + + /* Hide desktop logo, show mobile icon in title */ + .site-logo-link { + display: none; + } + + .site-icon-mobile { + display: inline-flex; + } + + /* ========== Language Selector - Show Short Names Only ========== */ + .language-selector .selector-btn { + position: relative; + padding: 0.4rem 0.75rem; + min-width: 40px; + font-size: 0; /* Hide actual text */ + overflow: visible; + transition: font-size 0.3s ease; + display: inline-flex; + justify-content: center; + align-items: center; + } + + /* Show only short version (EN/ES) */ + .language-selector .selector-btn::before { + content: attr(data-short); + font-size: 0.95rem; + opacity: 1; + transition: opacity 0.3s ease; + display: block; + width: 100%; + text-align: center; + } + + /* Keep short names on hover (no expansion) */ + .language-selector .selector-btn:hover { + font-size: 0; + min-width: 40px; + } + + .language-selector .selector-btn:hover::before { + content: attr(data-short); + opacity: 1; + } +} + +/* ========================================================================== + ZOOM CONTROL - Fixed Bottom Center + ========================================================================== */ + +.zoom-control { + position: fixed; + bottom: 100px; /* Default position, can be dragged */ + left: 50%; + transform: translateX(-50%); + z-index: 900; + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.65rem 1.25rem; + background: rgba(128, 128, 128, 0.7); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + border-radius: 50px; + box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2); + transition: all 0.3s ease; + opacity: 0.7; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; + cursor: move; /* Indicate draggability */ + user-select: none; /* Prevent text selection while dragging */ +} + +/* Zoom control highlight when hovering zoom toggle button */ +.zoom-control.zoom-highlight { + opacity: 1; + box-shadow: 0px 0px 10px 4px rgb(1 113 188 / 80%); + background: rgb(91 91 91); +} + +/* Hidden state for zoom control and show button */ +.zoom-hidden { + display: none !important; +} + +/* Close button for zoom control */ +.zoom-close-btn { + position: absolute; + top: -8px; + right: -8px; + width: 24px; + height: 24px; + background: rgba(128, 128, 128, 0.6); /* Subtle grey */ + border: 2px solid rgba(255, 255, 255, 0.3); + border-radius: 50%; + color: rgba(255, 255, 255, 0.8); /* Light grey icon */ + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + padding: 0; + transition: all 0.2s ease; + z-index: 1; + opacity: 0.7; /* Subtle by default */ +} + +.zoom-close-btn:hover { + background: rgba(220, 53, 69, 0.9); /* Red on hover */ + color: white; /* White icon on hover */ + opacity: 1; /* Fully visible on hover */ + transform: scale(1.1); + box-shadow: 0 2px 8px rgba(220, 53, 69, 0.4); +} + +.zoom-control:hover { + opacity: 1; + background: rgb(91 91 91); + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); +} + +/* Zoom Values (Labels) */ +.zoom-value { + color: rgba(255, 255, 255, 1); /* 100% white */ + font-size: 0.95rem; /* Bigger */ + font-weight: 500; /* Medium weight */ + min-width: 30px; + text-align: center; +} + +.zoom-value-current { + color: rgba(255, 255, 255, 1); /* 100% white */ + font-weight: 600; + font-size: 1.05rem; /* Bigger */ + min-width: 35px; +} + +/* Range Slider Styling */ +.zoom-slider { + -webkit-appearance: none; + appearance: none; + width: 180px; + height: 5px; + border-radius: 3px; + background: rgba(200, 200, 200, 0.5); + outline: none; + cursor: pointer; + transition: all 0.3s ease; +} + +/* Solid blue color on hover - no gradient */ +.zoom-control:hover .zoom-slider, +.zoom-slider:hover { + background: rgba(145, 190, 236, 1); /* solid blue */ +} + +.zoom-slider:focus { + outline: 2px solid rgba(255, 255, 255, 0.6); + outline-offset: 2px; +} + +/* Webkit Slider Thumb */ +.zoom-slider::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 18px; + height: 18px; + border-radius: 50%; + background: white; + border: 2px solid rgba(180, 180, 180, 0.8); + cursor: pointer; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); + transition: all 0.2s ease; +} + +.zoom-slider::-webkit-slider-thumb:hover { + transform: scale(1.1); + border-color: rgba(200, 200, 200, 1); + box-shadow: 0 3px 8px rgba(0, 0, 0, 0.4); +} + +.zoom-slider::-webkit-slider-thumb:active { + transform: scale(1.05); +} + +/* Firefox Slider Thumb */ +.zoom-slider::-moz-range-thumb { + width: 18px; + height: 18px; + border-radius: 50%; + background: white; + border: 2px solid rgba(180, 180, 180, 0.8); + cursor: pointer; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); + transition: all 0.2s ease; +} + +.zoom-slider::-moz-range-thumb:hover { + transform: scale(1.1); + border-color: rgba(200, 200, 200, 1); + box-shadow: 0 3px 8px rgba(0, 0, 0, 0.4); +} + +.zoom-slider::-moz-range-thumb:active { + transform: scale(1.05); +} + +/* Firefox Range Track */ +.zoom-slider::-moz-range-track { + height: 5px; + border-radius: 3px; + background: rgba(200, 200, 200, 0.5); + transition: all 0.3s ease; +} + +/* Firefox Range Track - Solid blue on hover */ +.zoom-control:hover .zoom-slider::-moz-range-track, +.zoom-slider:hover::-moz-range-track { + background: #3b82f6; /* solid blue */ +} + +/* Reset Button - Circular with dynamic value inside */ +.zoom-reset-btn { + display: flex; + align-items: center; + justify-content: center; + min-width: 44px; + min-height: 44px; + padding: 0.5rem; + background: rgba(200, 200, 200, 0.2); + border: 2px solid rgba(220, 220, 220, 0.3); + border-radius: 50%; + color: rgba(255, 255, 255, 0.8); + font-size: 0.85rem; + font-weight: 700; + cursor: pointer; + transition: all 0.3s ease; + flex-shrink: 0; + margin: 0 -5px 0 10px; +} + +.zoom-reset-btn #zoom-value-current { + color: inherit; + font-size: inherit; + font-weight: inherit; + min-width: auto; +} + +.zoom-reset-btn:hover { + background: rgba(220, 220, 220, 0.4); + border-color: rgba(240, 240, 240, 0.6); + color: white; +} + +/* Green hover only when zoom is not at default (100) */ +.zoom-reset-btn.zoom-not-default:hover { + background: #74aacd; + border-color: #74aacd; + color: white; +} + +.zoom-reset-btn:active { + transform: scale(0.95); +} + +.zoom-reset-btn:focus { + outline: 2px solid rgba(255, 255, 255, 0.6); + outline-offset: 2px; +} + +/* Mobile Responsive - Horizontal button layout defined below (around line 2867) */ +/* Old mobile styles removed - now using horizontal layout with all three buttons */ + +/* Very Small Screens - Ultra Compact */ +@media (max-width: 480px) { + .zoom-control { + bottom: 40px; + padding: 0.35rem 0.7rem; + gap: 0.35rem; + } + + .zoom-slider { + width: 100px; + } + + /* Hide min/max labels on very small screens */ + .zoom-value-min, + .zoom-value-max { + display: none; + } +} + +/* ============================================================================= + HTMX CSS TRANSITIONS + ============================================================================= */ + +/* Inline loading transition styles moved to main section above (~line 1677) */ +/* Prevent layout shift during content fade */ +.cv-page-content-wrapper { + position: relative; +} + +/* ============================================================================= + KEYBOARD SHORTCUTS BUTTON & MODAL + ============================================================================= */ + +/* Shortcuts Button (Fixed Left) - Mirrors info-button on opposite side */ +/* Zoom Toggle Button (above shortcuts button) */ +.zoom-toggle-btn { + position: fixed; + bottom: 10rem; /* Above shortcuts button */ + left: 2rem; + width: 50px; + height: 50px; + background: var(--black-bar); + color: white; /* Match other buttons when inactive */ + border: none; + border-radius: 50%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + transition: all 0.3s ease; + z-index: 999; + opacity: 0.6; /* Match shortcuts button opacity */ +} + +.zoom-toggle-btn:hover { + opacity: 1; + transform: translateY(-3px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); + background: #3498db; /* Blue hover */ +} + +.zoom-toggle-btn.at-bottom { + opacity: 1; + background: #3498db; /* Blue - matches hover */ +} + +/* No special styling for active state - button looks same whether zoom is on or off */ + +.shortcuts-btn { + position: fixed; + bottom: 6rem; /* Above back-to-top button (2rem + 50px + gap) */ + left: 2rem; /* LEFT SIDE instead of right */ + width: 50px; + height: 50px; + background: var(--black-bar); + color: white; + border: none; + border-radius: 50%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + z-index: 99; + transition: all 0.3s ease; + opacity: 0.6; /* Increased from 0.2 for better discoverability */ +} + +.shortcuts-btn:hover { + opacity: 1; + transform: translateY(-3px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); + background: #f39c12; /* Orange hover */ +} + +.shortcuts-btn.at-bottom { + opacity: 1; + background: #f39c12; /* Orange when at bottom */ +} + +.shortcuts-btn:active { + transform: translateY(-1px); +} + +/* Print-Friendly Button (second from top) */ +.print-friendly-btn { + position: fixed; + bottom: 18rem; /* Below download button (22rem) */ + left: 2rem; + width: 50px; + height: 50px; + background: var(--black-bar); /* Dark background by default */ + color: white; /* White icon by default */ + border: none; + border-radius: 50%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + transition: all 0.3s ease; + z-index: 999; + opacity: 0.6; +} + +.print-friendly-btn iconify-icon { + color: white; /* White icon by default */ +} + +.print-friendly-btn:hover, +.print-friendly-btn.print-hover-sync { + opacity: 1; + transform: translateY(-3px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); + background: white !important; /* White background on hover */ + color: #27ae60; /* Green icon on hover */ +} + +.print-friendly-btn:hover iconify-icon, +.print-friendly-btn.print-hover-sync iconify-icon { + color: #27ae60; /* Green icon on hover */ +} + +.print-friendly-btn.at-bottom { + opacity: 1; + background: white !important; /* White background - matches hover */ + color: #27ae60; /* Green - matches hover */ +} + +.print-friendly-btn.at-bottom iconify-icon { + color: #27ae60; /* Green icon when at bottom */ +} + +/* Download Button (TOP POSITION) */ +.download-btn { + position: fixed; + bottom: 22rem; /* Top button position */ + left: 2rem; + width: 50px; + height: 50px; + background: var(--black-bar); + color: white; + border: none; + border-radius: 50%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + transition: all 0.3s ease; + z-index: 999; + opacity: 0.6; +} + +.download-btn { + background: var(--black-bar); /* Gray by default like other buttons */ + opacity: 0.6; /* Match other buttons */ +} + +.download-btn:hover, +.download-btn.pdf-hover-sync { + opacity: 1; + transform: translateY(-3px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); + background: #cd6060 !important; /* PDF red on hover */ +} + +.download-btn iconify-icon { + filter: brightness(0) invert(1); /* Always white */ + transition: filter 0.3s ease; +} + +.download-btn:hover iconify-icon { + filter: brightness(0) invert(1); /* Keep white on hover */ +} + +.download-btn.at-bottom { + opacity: 1; + background: #cd6060 !important; /* PDF red - matches hover */ +} + +/* Mobile adjustments */ +@media (max-width: 768px) { + .shortcuts-btn { + bottom: 5.5rem; /* Above back-to-top button (1.5rem + 45px + gap) */ + left: 1.5rem; /* LEFT SIDE on mobile too */ + width: 45px; + height: 45px; + } +} + +/* Shortcuts Modal - Very wide for 3-column grid, less tall */ +#shortcuts-modal { + max-width: 900px; /* Much wider - was 750px */ + max-height: 80vh; /* Limit height */ +} + +/* Keyboard icon with green curly brackets (matching info modal style) */ +.keyboard-icon-wrapper { + position: relative; + display: inline-flex; + align-items: center; + padding: 0 22px; +} + +.keyboard-icon-wrapper::before { + content: '{'; + position: absolute; + left: 2px; + font-size: 2rem; + font-weight: 700; + color: #575757ff; /* Dark brackets - matching info modal */ + line-height: 1; + top: -3px; +} + +.keyboard-icon-wrapper::after { + content: '}'; + position: absolute; + right: 2px; + font-size: 2rem; + font-weight: 700; + color: #575757ff; /* Dark brackets - matching info modal */ + line-height: 1; + top: -3px; +} + +.keyboard-icon-wrapper iconify-icon { + color: #f39c12; + position: relative; + top: 1px; +} + +/* Add margin-bottom to subtitle */ +#shortcuts-modal .info-modal-cv-title { + margin-bottom: 0.5rem; +} + +#shortcuts-modal .info-modal-body { + display: grid; + grid-template-columns: 1fr 1fr; /* 2 columns for 5 sections (3+2) */ + gap: 1.2rem 1.5rem; /* row gap, column gap */ + margin-top: 1.5rem; /* Increased spacing since no description */ +} + +/* Shortcuts Modal Content - Extends info-modal styles */ +.shortcuts-section { + margin-top: 0; /* Grid handles spacing */ + background: #f8f9fa; + border: 1px solid #e1e4e8; + border-radius: 8px; + padding: 1rem; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); +} + +.shortcuts-section:first-of-type { + margin-top: 0; +} + +.shortcuts-section-title { + font-size: 1.05rem; + font-weight: 600; + color: #827a6e; /* Brownish-gray for section header text */ + margin-bottom: 0.75rem; + display: flex; + align-items: center; + gap: 0.5rem; + padding-bottom: 0.5rem; + border-bottom: 2px solid rgba(130, 122, 110, 0.2); /* Matching border */ +} + +.shortcuts-section-title iconify-icon { + color: #f39c12; /* ORANGE icons for section headers */ +} + +.shortcuts-list { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.shortcut-item { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + padding: 0.5rem 0; +} + +.shortcut-keys { + display: flex; + align-items: center; + gap: 0.4rem; + flex-wrap: wrap; +} + +.shortcut-keys kbd { + font-family: 'Monaco', 'Courier New', monospace; + font-size: 0.75rem; + font-weight: 600; + background: rgba(52, 152, 219, 0.08); /* Light blue background */ + border: 1px solid rgba(52, 152, 219, 0.35); /* Blue border */ + border-radius: 6px; + padding: 0.3rem 0.6rem; + box-shadow: 0 2px 4px rgba(52, 152, 219, 0.12), inset 0 -1px 0 rgba(52, 152, 219, 0.25); + white-space: nowrap; + text-align: center; + color: #3498db; /* Blue text */ + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.2rem; + transition: all 0.2s ease; + min-width: 2rem; +} + +/* Iconify icons inside kbd elements */ +.shortcut-keys kbd iconify-icon { + color: inherit; + vertical-align: middle; + display: inline-flex; +} + +.shortcut-item:hover .shortcut-keys kbd { + background: rgba(52, 152, 219, 0.15); + border-color: rgba(52, 152, 219, 0.5); + box-shadow: 0 2px 6px rgba(52, 152, 219, 0.25); +} + +.shortcut-desc { + flex: 1; + font-size: 0.95rem; + color: var(--text-gray); + line-height: 1.4; +} + +/* Mobile responsive */ +@media (max-width: 768px) { + #shortcuts-modal { + max-width: calc(100% - 2rem); + } + + #shortcuts-modal .info-modal-body { + grid-template-columns: 1fr; /* Single column on mobile */ + gap: 1.5rem; + } +} + +/* Tablet - 2 columns */ +@media (min-width: 769px) and (max-width: 1024px) { + #shortcuts-modal { + max-width: 700px; + } + + #shortcuts-modal .info-modal-body { + grid-template-columns: 1fr 1fr; /* 2 columns on tablet */ + gap: 1.2rem 1.5rem; + } + + .shortcuts-section-title { + font-size: 1rem; + } + + .shortcut-item { + flex-direction: column; + align-items: flex-start; + gap: 0.35rem; + } + + .shortcut-keys kbd { + font-size: 0.7rem; + padding: 0.2rem 0.4rem; + } + + .shortcut-desc { + font-size: 0.9rem; + } +} + +/* ======================================================================== + PDF DOWNLOAD MODAL STYLES + ======================================================================== */ + +/* PDF Modal Specific Overrides */ +.pdf-download-modal { + max-width: 900px; + width: calc(100% - 2rem); +} + +/* Modal Subtitle */ +.pdf-modal-subtitle { + font-size: 0.95rem; + color: var(--text-gray); + margin-top: 0.5rem; + font-weight: 400; +} + +/* PDF Options Grid */ +.pdf-options-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 24px; + margin: 2rem 0 1.5rem 0; +} + +/* PDF Option Card */ +.pdf-option-card { + border: 2px solid transparent; + border-radius: 12px; + padding: 16px; + cursor: pointer; + transition: all 250ms ease; + position: relative; + background: #ffffff; + display: flex; + flex-direction: column; + gap: 12px; +} + +.pdf-option-card:hover { + border-color: #e0e0e0; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + transform: translateY(-2px); +} + +.pdf-option-card:focus { + outline: 2px solid #4caf50; + outline-offset: 2px; +} + +/* Selected State */ +.pdf-option-card.selected { + border-color: #4caf50; + box-shadow: 0 6px 16px rgba(76, 175, 80, 0.2); + background: #f9fff9; +} + +/* PDF Thumbnail Container */ +.pdf-thumbnail { + background: #ffffff; + border: 1px solid #e0e0e0; + border-radius: 8px; + padding: 16px; + height: 280px; + display: flex; + flex-direction: column; + gap: 12px; + position: relative; + overflow: hidden; +} + +/* Skeleton Blocks inside Thumbnails */ +.pdf-thumbnail .skeleton-block { + background: linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 50%, #f0f0f0 75%); + background-size: 200% 100%; + animation: skeleton-shimmer 1.8s ease-in-out infinite; + border-radius: 4px; +} + +/* Custom Placeholder (for Custom CV card) */ +.custom-placeholder { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100%; + color: #999; + text-align: center; +} + +.custom-placeholder iconify-icon { + margin-bottom: 12px; + opacity: 0.5; +} + +.custom-placeholder p { + font-size: 0.9rem; + font-weight: 500; + color: #666; + margin: 0; +} + +/* Thumbnail Badge (Page Count / Coming Soon) */ +.thumbnail-badge { + position: absolute; + top: 8px; + right: 8px; + background: rgba(0, 0, 0, 0.75); + color: white; + font-size: 0.7rem; + font-weight: 600; + padding: 4px 8px; + border-radius: 4px; + letter-spacing: 0.5px; + text-transform: uppercase; +} + +/* PDF Option Info */ +.pdf-option-info { + text-align: center; +} + +.pdf-option-info h3 { + font-size: 1.1rem; + font-weight: 600; + color: var(--text-dark); + margin: 0 0 4px 0; +} + +.pdf-option-info p { + font-size: 0.875rem; + color: var(--text-gray); + margin: 0; + line-height: 1.4; +} + +/* PDF Option Badge (Checkmark) */ +.pdf-option-badge { + position: absolute; + top: 8px; + left: 8px; + opacity: 0; + transform: scale(0.8); + transition: all 250ms ease; + color: #4caf50; +} + +.pdf-option-card.selected .pdf-option-badge { + opacity: 1; + transform: scale(1); +} + +/* PDF Modal Footer */ +.pdf-modal-footer { + display: flex; + justify-content: center; + padding-top: 1rem; + border-top: 1px solid #e0e0e0; + margin-top: 0.5rem; +} + +/* PDF Download Button */ +.pdf-download-btn { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 12px 32px; + font-size: 1rem; + font-weight: 600; + border: none; + border-radius: 8px; + cursor: pointer; + transition: all 250ms ease; + font-family: inherit; +} + +.pdf-download-btn iconify-icon { + flex-shrink: 0; +} + +/* Disabled State */ +.pdf-download-btn:disabled { + background: #e0e0e0; + color: #999999; + cursor: not-allowed; + opacity: 0.6; +} + +/* Enabled State */ +.pdf-download-btn:not(:disabled) { + background: #4caf50; + color: white; +} + +.pdf-download-btn:not(:disabled):hover { + background: #45a049; + box-shadow: 0 4px 12px rgba(76, 175, 80, 0.3); + transform: translateY(-1px); +} + +.pdf-download-btn:not(:disabled):active { + transform: translateY(0); +} + +/* Screen Reader Only */ +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; +} + +/* ======================================================================== + RESPONSIVE DESIGN - PDF MODAL + ======================================================================== */ + +/* Tablet: Two columns */ +@media (min-width: 480px) and (max-width: 767px) { + .pdf-options-grid { + grid-template-columns: repeat(2, 1fr); + gap: 16px; + } + + /* Custom card spans full width */ + .pdf-option-card[data-cv-format="custom"] { + grid-column: 1 / -1; + } + + .pdf-thumbnail { + height: 220px; + } +} + +/* Mobile: Single column */ +@media (max-width: 479px) { + .pdf-download-modal { + max-width: calc(100% - 1rem); + } + + .pdf-options-grid { + display: flex; + flex-direction: column; + gap: 16px; + } + + .pdf-thumbnail { + height: 200px; + } + + .pdf-option-info h3 { + font-size: 1rem; + } + + .pdf-option-info p { + font-size: 0.8rem; + } + + .pdf-download-btn { + padding: 10px 24px; + font-size: 0.9rem; + } +} + +/* ======================================================================== + ACCESSIBILITY - REDUCED MOTION + ======================================================================== */ + +@media (prefers-reduced-motion: reduce) { + .pdf-thumbnail .skeleton-block { + animation: none; + background: #e8e8e8; + } + + .pdf-option-card { + transition: none; + } + + .pdf-option-badge { + transition: none; + } + + .pdf-download-btn { + transition: none; + } +} diff --git a/static/css/04-interactive/_toggles.css b/static/css/04-interactive/_toggles.css new file mode 100644 index 0000000..24a9671 --- /dev/null +++ b/static/css/04-interactive/_toggles.css @@ -0,0 +1,260 @@ +/* Toggle Components - Unified Design */ +.language-toggle, +.cv-length-toggle, +.logo-toggle { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + white-space: nowrap; +} + +.toggle-switch { + display: inline-block; + cursor: pointer; + user-select: none; + position: relative; +} + +.toggle-switch input[type="checkbox"] { + position: absolute; + opacity: 0; + width: 0; + height: 0; +} + +.toggle-slider { + position: relative; + display: inline-block; + width: 50px; + height: 26px; + background-color: #555; + border-radius: 26px; + transition: background-color 0.3s ease; +} + +.toggle-slider::after { + content: ''; + position: absolute; + width: 20px; + height: 20px; + border-radius: 50%; + background-color: white; + top: 3px; + left: 3px; + transition: transform 0.3s ease; + box-shadow: 0 2px 4px rgba(0,0,0,0.2); +} + +.toggle-switch input[type="checkbox"]:checked + .toggle-slider { + background-color: var(--accent-blue); +} + +.toggle-switch input[type="checkbox"]:checked + .toggle-slider::after { + transform: translateX(24px); +} + +.toggle-switch input[type="checkbox"]:focus + .toggle-slider { + box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.2); +} + +.toggle-label-left, +.toggle-label-right { + font-size: 0.8rem; + font-weight: 500; + color: #999; + transition: all 0.3s ease; + white-space: nowrap; + display: flex; + align-items: center; + justify-content: center; + height: 28px; +} + +/* Flag icons - special styling */ +.flag-icon { + border-radius: 50%; + overflow: hidden; + display: flex; + align-items: center; + justify-content: center; +} + +/* Highlight active label/icon based on parent container state */ +.language-toggle:has(#langToggle:not(:checked)) .toggle-label-left, +.cv-length-toggle:has(#lengthToggle:not(:checked)) .toggle-label-left, +.logo-toggle:has(#logoToggle:not(:checked)) .toggle-label-left { + color: #fff; + opacity: 1; +} + +.language-toggle:has(#langToggle:checked) .toggle-label-right, +.cv-length-toggle:has(#lengthToggle:checked) .toggle-label-right, +.logo-toggle:has(#logoToggle:checked) .toggle-label-right { + color: #fff; + opacity: 1; +} + +/* Dim inactive icons */ +.language-toggle:has(#langToggle:not(:checked)) .toggle-label-right, +.cv-length-toggle:has(#lengthToggle:not(:checked)) .toggle-label-right, +.logo-toggle:has(#logoToggle:not(:checked)) .toggle-label-right { + opacity: 0.4; +} + +.language-toggle:has(#langToggle:checked) .toggle-label-left, +.cv-length-toggle:has(#lengthToggle:checked) .toggle-label-left, +.logo-toggle:has(#logoToggle:checked) .toggle-label-left { + opacity: 0.4; +} + +/* Experience Item with Logo Support */ +.experience-item, +.award-item { + margin-bottom: 2.5rem; + padding-bottom: 2rem; + border-bottom: 2px solid #ddd; + page-break-inside: avoid; + display: flex; + gap: 1.2rem; + position: relative; + transition: gap 0.3s ease-in-out; +} + +.experience-item:last-child, +.award-item:last-child { + border-bottom: none; + padding-bottom: 0; +} + +/* Adjust gap when icons are hidden */ +.cv-paper:not(.show-icons) .experience-item, +.cv-paper:not(.show-icons) .award-item { + gap: 0; +} + +.company-logo, +.award-logo, +.project-icon, +.course-icon { + display: block; + flex-shrink: 0; +} + +.company-logo img, +.award-logo img, +.project-icon img, +.course-icon img { + width: 80px; + height: 80px; + object-fit: contain; + border-radius: 4px; + border: 1px solid #ddd; + background: transparent; + padding: 10px; +} + +.default-company-icon, +.default-award-icon, +.default-project-icon, +.default-course-icon { + width: 80px !important; + height: 80px !important; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + border: 1px solid #ddd; + background: transparent; + color: #999; + padding: 10px; +} + +.experience-content, +.award-content { + flex: 1; + min-width: 0; /* Prevents flex item from overflowing */ +} + +/* Animate icons with fade and scale */ +.company-logo, +.award-logo, +.section-icon, +.default-company-icon, +.project-icon, +.default-project-icon, +.course-icon, +.default-course-icon { + overflow: hidden; + transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out, width 0.3s ease-in-out, height 0.3s ease-in-out, margin 0.3s ease-in-out; + opacity: 1; + transform: scale(1); + width: auto; + height: auto; +} + +/* Hide icons when toggle is OFF - with animation */ +.cv-paper:not(.show-icons) .company-logo, +.cv-paper:not(.show-icons) .award-logo, +.cv-paper:not(.show-icons) .section-icon, +.cv-paper:not(.show-icons) .default-company-icon, +.cv-paper:not(.show-icons) .project-icon, +.cv-paper:not(.show-icons) .default-project-icon, +.cv-paper:not(.show-icons) .course-icon, +.cv-paper:not(.show-icons) .default-course-icon { + opacity: 0; + transform: scale(0.8); + width: 0; + height: 0; + margin: 0; + padding: 0; + pointer-events: none; + overflow: hidden; +} + +/* Show icons when toggle is ON (default) - with animation */ +.show-icons .company-logo, +.show-icons .award-logo, +.show-icons .section-icon, +.show-icons .default-company-icon, +.show-icons .project-icon, +.show-icons .default-project-icon, +.show-icons .course-icon, +.show-icons .default-course-icon { + opacity: 1; + transform: scale(1); + width: auto; + height: auto; +} + +/* Company icons visible in print - styling controlled by print.css */ + +/* Mobile responsiveness */ +@media (max-width: 768px) { + .logo-toggle { + order: 3; /* Move to bottom on mobile */ + } + + .toggle-label { + font-size: 0.85rem; + } + + .toggle-slider { + width: 38px; + height: 20px; + } + + .toggle-slider::after { + width: 14px; + height: 14px; + } + + .toggle-switch input[type="checkbox"]:checked + .toggle-slider::after { + transform: translateX(18px); + } + + .company-logo img { + width: 40px; + height: 40px; + } +} diff --git a/static/css/06-effects/_skeleton.css b/static/css/06-effects/_skeleton.css new file mode 100644 index 0000000..b181f49 --- /dev/null +++ b/static/css/06-effects/_skeleton.css @@ -0,0 +1,603 @@ +/** + * Component-Level Skeleton Loaders for Language Transitions + * ========================================================== + * Each CV component has dual-state structure: + * - .actual-content (real CV content) + * - .skeleton-content (gray pulsing placeholders) + * + * Loading state controlled via .loading class on component wrapper + */ + +/* ======================================================================== + BASE SKELETON STYLES + ======================================================================== */ + +.skeleton { + background: linear-gradient( + 90deg, + #f0f0f0 0%, + #e8e8e8 20%, + #f0f0f0 40%, + #f0f0f0 100% + ); + background-size: 200% 100%; + animation: skeleton-shimmer 1.8s ease-in-out infinite; + border-radius: 4px; + will-change: background-position; +} + +@keyframes skeleton-shimmer { + 0% { + background-position: 200% 0; + } + 100% { + background-position: -200% 0; + } +} + +/* ======================================================================== + COMPONENT WRAPPER STATE TOGGLING + ======================================================================== */ + +/* Default state: Show actual content, hide skeleton */ +.component-wrapper { + position: relative; +} + +.component-wrapper .actual-content { + opacity: 1; + transition: opacity 250ms ease-out; +} + +.component-wrapper .skeleton-content { + position: absolute; + top: 0; + left: 0; + right: 0; + opacity: 0; + pointer-events: none; + transition: opacity 250ms ease-out; +} + +/* Loading state: Hide actual content, show skeleton */ +/* Triggered by manual .loading class OR when parent page container has .loading */ +.component-wrapper.loading .actual-content, +.loading .component-wrapper .actual-content { + opacity: 0; + pointer-events: none; +} + +.component-wrapper.loading .skeleton-content, +.loading .component-wrapper .skeleton-content { + opacity: 1; + pointer-events: all; +} + +/* ======================================================================== + SKELETON SHAPE DEFINITIONS + ======================================================================== */ + +/* Header Section Skeleton */ +/* Matches actual header layout with photo absolutely positioned on right */ +.skeleton-header { + position: relative; + padding-right: 185px; /* Match .cv-header-left padding */ + min-height: 200px; /* Ensure space for photo */ +} + +.skeleton-header-text { + position: relative; + z-index: 1; +} + +.skeleton-name { + height: 40px; /* Larger to match h1 */ + width: 75%; + margin-bottom: 12px; +} + +.skeleton-experience-years { + height: 24px; /* Larger subtitle */ + width: 55%; + margin-bottom: 24px; +} + +.skeleton-photo { + width: 150px; /* Match actual photo */ + height: 200px; /* Match actual photo */ + border-radius: 0; /* No border-radius on actual photo */ + border: 3px solid #e8e8e8; /* Match photo border style */ + + /* Absolute positioning to match actual layout */ + position: absolute; + top: 15px; + right: 15px; + flex-shrink: 0; +} + +.skeleton-intro { + height: 90px; /* Taller for 3-4 lines of text */ + width: 100%; + margin-top: 12px; +} + +/* Section Title Skeleton */ +.skeleton-section-title { + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 16px; +} + +.skeleton-icon { + width: 24px; + height: 24px; + border-radius: 4px; + flex-shrink: 0; +} + +.skeleton-title-text { + height: 24px; + width: 40%; +} + +/* Skill Item Skeleton (Sidebar) */ +.skeleton-skill-category { + margin-bottom: 20px; +} + +.skeleton-skill-title { + height: 20px; + width: 60%; + margin-bottom: 12px; +} + +.skeleton-skill-items { + display: flex; + flex-direction: column; + gap: 8px; +} + +.skeleton-skill-item { + height: 32px; + width: 100%; +} + +.skeleton-skill-item:nth-child(2) { + width: 85%; +} + +.skeleton-skill-item:nth-child(3) { + width: 90%; +} + +.skeleton-skill-item:nth-child(4) { + width: 75%; +} + +/* Experience Entry Skeleton */ +.skeleton-experience-item { + display: flex; + gap: 16px; + margin-bottom: 24px; +} + +.skeleton-company-logo { + width: 60px; + height: 60px; + border-radius: 8px; + flex-shrink: 0; +} + +.skeleton-experience-content { + flex: 1; + display: flex; + flex-direction: column; + gap: 8px; +} + +/* NEW: Structural skeleton lines for experience */ +.skeleton-position-line { + height: 20px; + width: 80%; +} + +.skeleton-date-line { + height: 14px; + width: 50%; +} + +.skeleton-description-line { + height: 16px; + width: 100%; + margin-top: 4px; +} + +.skeleton-responsibility-line { + height: 14px; + width: 100%; + margin-left: 16px; /* Indent like list items */ +} + +/* Legacy styles (keeping for backward compatibility) */ +.skeleton-position { + height: 20px; + width: 80%; +} + +.skeleton-company-info { + height: 16px; + width: 60%; +} + +.skeleton-description { + height: 40px; + width: 100%; + margin-top: 4px; +} + +.skeleton-description.short { + width: 85%; +} + +/* Section Skeleton Base */ +.skeleton-section { + padding: 16px 0; +} + +.skeleton-section-title { + height: 28px; + width: 35%; + margin-bottom: 20px; +} + +/* Education Item Skeleton */ +.skeleton-education-item { + height: 48px; + width: 100%; + margin-bottom: 12px; +} + +.skeleton-education-item:last-child { + margin-bottom: 0; +} + +/* Skills Summary Skeleton */ +.skeleton-summary-paragraph { + height: 18px; + width: 100%; + margin-bottom: 10px; +} + +.skeleton-summary-paragraph:last-child { + margin-bottom: 0; +} + +/* Award Item Skeleton */ +.skeleton-award-item { + display: flex; + gap: 16px; + margin-bottom: 24px; +} + +.skeleton-award-logo { + width: 60px; + height: 60px; + border-radius: 8px; + flex-shrink: 0; +} + +.skeleton-award-content { + flex: 1; + display: flex; + flex-direction: column; + gap: 8px; +} + +/* NEW: Structural skeleton lines for awards */ +.skeleton-award-title-line { + height: 20px; + width: 70%; +} + +.skeleton-award-info-line { + height: 14px; + width: 50%; +} + +/* Legacy styles (keeping for backward compatibility) */ +.skeleton-award-title { + height: 20px; + width: 70%; +} + +.skeleton-award-info { + height: 16px; + width: 50%; +} + +.skeleton-award-description { + height: 40px; + width: 100%; + margin-top: 4px; +} + +/* Project Item Skeleton */ +.skeleton-project-item { + display: flex; + gap: 16px; + margin-bottom: 24px; +} + +.skeleton-project-icon { + width: 80px; + height: 80px; + border-radius: 8px; + flex-shrink: 0; +} + +.skeleton-project-content { + flex: 1; + display: flex; + flex-direction: column; + gap: 8px; +} + +/* NEW: Structural skeleton lines for projects */ +.skeleton-project-title-line { + height: 20px; + width: 75%; +} + +.skeleton-tech-line { + height: 14px; + width: 85%; + margin-top: 4px; +} + +.skeleton-footer-line { + height: 16px; + width: 70%; + margin-top: 16px; +} + +/* Legacy styles (keeping for backward compatibility) */ +.skeleton-project-title { + height: 20px; + width: 75%; +} + +.skeleton-project-info { + height: 16px; + width: 55%; +} + +.skeleton-project-description { + height: 40px; + width: 100%; + margin-top: 4px; +} + +.skeleton-project-description.short { + width: 80%; +} + +/* Course Item Skeleton */ +.skeleton-course-item { + display: flex; + gap: 16px; + margin-bottom: 20px; +} + +.skeleton-course-icon { + width: 80px; + height: 80px; + border-radius: 8px; + flex-shrink: 0; +} + +.skeleton-course-content { + flex: 1; + display: flex; + flex-direction: column; + gap: 8px; +} + +/* NEW: Structural skeleton lines for courses */ +.skeleton-course-title-line { + height: 18px; + width: 70%; +} + +.skeleton-course-info-line { + height: 14px; + width: 60%; +} + +/* Legacy styles (keeping for backward compatibility) */ +.skeleton-course-title { + height: 18px; + width: 70%; +} + +.skeleton-course-info { + height: 16px; + width: 60%; +} + +/* Language Item Skeleton */ +.skeleton-language-item { + height: 20px; + width: 100%; + margin-bottom: 12px; +} + +.skeleton-language-item:last-child { + margin-bottom: 0; +} + +/* Reference Item Skeleton */ +.skeleton-reference-item { + height: 22px; + width: 100%; + margin-bottom: 10px; +} + +.skeleton-reference-item:last-child { + margin-bottom: 0; +} + +/* Other Section Skeleton */ +.skeleton-other-item { + height: 20px; + width: 60%; +} + +/* Sidebar Skeleton */ +.skeleton-sidebar { + padding: 16px 0; +} + +.skeleton-sidebar-header { + height: 28px; + width: 80%; + margin-bottom: 20px; +} + +/* Skill Item Skeleton (Sidebar) - Already defined above but keeping for reference */ + +/* Footer Skeleton */ +.skeleton-footer { + display: flex; + flex-direction: column; + gap: 12px; + padding: 16px 0; +} + +.skeleton-footer-item { + height: 20px; + width: 100%; +} + +.skeleton-footer-item:nth-child(2) { + width: 90%; +} + +.skeleton-footer-item:nth-child(3) { + width: 85%; +} + +.skeleton-footer-item:nth-child(4) { + width: 80%; +} + +.skeleton-footer-item:nth-child(5) { + width: 75%; +} + +/* Text Block Skeletons (Generic) */ +.skeleton-text { + height: 16px; + margin-bottom: 8px; +} + +.skeleton-text.short { + width: 60%; +} + +.skeleton-text.medium { + width: 80%; +} + +.skeleton-text.long { + width: 95%; +} + +/* ======================================================================== + RESPONSIVE ADJUSTMENTS + ======================================================================== */ + +@media (max-width: 768px) { + .skeleton-header { + flex-direction: column; + align-items: center; + } + + .skeleton-header-text { + text-align: center; + width: 100%; + } + + .skeleton-name, + .skeleton-experience-years { + width: 80%; + margin-left: auto; + margin-right: auto; + } + + .skeleton-photo { + width: 100px; + height: 100px; + border-radius: 8px; + } + + .skeleton-experience-item { + flex-direction: column; + gap: 12px; + } + + .skeleton-company-logo { + width: 50px; + height: 50px; + } +} + +/* ======================================================================== + ACCESSIBILITY - REDUCED MOTION + ======================================================================== */ + +@media (prefers-reduced-motion: reduce) { + .skeleton { + animation: none; + background: #e8e8e8; + } + + .component-wrapper .actual-content, + .component-wrapper .skeleton-content { + transition: none; + } +} + +/* ======================================================================== + PRINT STYLES + ======================================================================== */ + +@media print { + .skeleton-content { + display: none !important; + } + + .component-wrapper .actual-content { + opacity: 1 !important; + } +} + +/* ======================================================================== + PERFORMANCE OPTIMIZATIONS + ======================================================================== */ + +/* Force GPU acceleration for skeleton elements */ +.skeleton { + transform: translateZ(0); + backface-visibility: hidden; +} + +/* Contain layout/paint/style to prevent reflow */ +.component-wrapper { + contain: layout style; +} + +/* Optimize skeleton rendering */ +.skeleton-content { + contain: layout paint; +} diff --git a/static/css/08-contexts/_print.css b/static/css/08-contexts/_print.css new file mode 100644 index 0000000..12767b7 --- /dev/null +++ b/static/css/08-contexts/_print.css @@ -0,0 +1,662 @@ +/* Print Styles - A4 Optimized - Consolidated & Fixed */ + +@media print { + /* =================================== + CRITICAL: Print Color Accuracy + =================================== */ + * { + -webkit-print-color-adjust: exact !important; + print-color-adjust: exact !important; + color-adjust: exact !important; + } + + /* =================================== + PAGE SETUP - A4 with Minimal Margins + =================================== */ + @page { + size: A4 portrait; + margin: 8mm; /* Minimal printer margins */ + } + + body { + background: white !important; + margin: 0 !important; + padding: 0 !important; + } + + /* =================================== + HIDE NON-PRINT ELEMENTS + =================================== */ + .no-print, + .action-bar, + .navigation-menu, + .hamburger-btn, + footer, + .back-to-top, + .info-button, + .info-modal, + .error-toast, + .cv-sidebar, + .cv-sidebar-left, + .cv-sidebar-right, + .cv-title-badges-header, + .cv-footer { + display: none !important; + } + + /* =================================== + SHOW ALL ICONS, ICONS, AND BADGES - Print Default + =================================== */ + + /* Section title icons - smaller for print */ + .section-icon { + width: 16px !important; + height: 16px !important; + vertical-align: middle !important; + margin-right: 4px !important; + } + + /* Company/Project/Course icons - compact for print */ + .company-logo, + .project-icon, + .course-icon, + .award-logo { + width: 40px !important; + height: 40px !important; + flex-shrink: 0 !important; + } + + .company-logo img, + .project-icon img, + .course-icon img, + .award-logo img { + width: 40px !important; + height: 40px !important; + object-fit: contain !important; + } + + /* Default fallback icons - show at print size */ + .default-company-icon, + .default-project-icon, + .default-course-icon, + .default-award-icon { + width: 40px !important; + height: 40px !important; + } + + /* Badges - keep visible for print */ + .current-badge, + .live-badge, + .expired-badge, + .maintained-badge { + font-size: 7pt !important; + padding: 1px 4px !important; + } + + .live-badge iconify-icon { + width: 10px !important; + height: 10px !important; + } + + /* =================================== + REMOVE ALL SHADOWS & BORDERS (Nuclear Option) + =================================== */ + *, + *::before, + *::after { + box-shadow: none !important; + text-shadow: none !important; + } + + /* =================================== + CV CONTAINER - Full Page Width + =================================== */ + .cv-container { + width: 100%; + max-width: 100%; + margin: 0; + padding: 0; + gap: 0; + } + + .cv-container.theme-clean { + padding: 0; + } + + /* =================================== + CV PAPER - Reduced Padding (20mm → 12mm) + =================================== */ + .cv-paper { + width: 100%; + min-height: auto !important; + background: white !important; + padding: 12mm !important; /* Reduced from 20mm */ + box-shadow: none !important; + border: none !important; + margin: 0 !important; + page-break-after: auto; + transform: none !important; + } + + /* =================================== + CV PAGE - Remove All Decorations & Page Breaks + =================================== */ + .cv-page, + .theme-clean .cv-page { + box-shadow: none !important; + border: none !important; + background: white !important; + margin: 0 !important; + padding: 0 !important; + transform: scale(1) !important; + max-width: 100% !important; + page-break-after: auto !important; /* Let content flow naturally */ + page-break-inside: auto !important; /* Allow breaking inside */ + } + + .cv-page.page-2 { + page-break-after: auto !important; + } + + /* =================================== + PAGE CONTENT GRID - Allow Natural Flow + =================================== */ + .page-content { + page-break-inside: auto !important; /* Allow content to break naturally */ + display: block !important; /* Remove grid for print */ + } + + /* =================================== + PAGE BREAKS - Optimized for Content Flow + =================================== */ + .page-break { + page-break-after: auto !important; /* Remove forced page breaks */ + break-after: auto !important; + } + + /* Sections CAN break across pages - flow naturally */ + .cv-section { + page-break-inside: auto !important; + break-inside: auto !important; + page-break-before: auto !important; /* No forced breaks before sections */ + page-break-after: auto !important; /* No forced breaks after sections */ + } + + /* Keep individual items together */ + .avoid-break, + .experience-item, + .project-item, + .course-item, + .award-item { + page-break-inside: avoid !important; + break-inside: avoid !important; + } + + /* Experience section should flow into Awards - no page break */ + #experience { + page-break-after: auto !important; + } + + /* =================================== + HEADER - Reduced Spacing with Desktop Layout + =================================== */ + .cv-header { + page-break-after: avoid; + margin-bottom: 8mm !important; /* Reduced from 15mm */ + } + + /* Override mobile layout - use positioned layout for print */ + .cv-header-content { + display: block !important; /* Use block instead of flex */ + position: relative !important; + } + + .cv-header-left { + display: block !important; + position: static !important; + padding-right: 130px !important; /* Make room for bigger photo on the right */ + text-align: right !important; /* Right-align name and years */ + } + + .cv-name { + font-size: 20pt; + margin-bottom: 4pt; + text-align: right !important; /* Override mobile center alignment */ + } + + .cv-title { + font-size: 12pt; + } + + .years-experience, + .cv-experience-years { + font-size: 10pt; + text-align: right !important; /* Override mobile center alignment */ + } + + /* =================================== + PHOTO - FIXED ASPECT RATIO (3:4 Portrait) - RIGHT SIDE + =================================== */ + .cv-photo { + width: 110px !important; /* Increased from 90px */ + height: 147px !important; /* Maintains 3:4 ratio (110 * 1.33) */ + object-fit: contain !important; /* Show full photo, no crop */ + border: none !important; /* Remove border */ + box-shadow: none !important; + page-break-inside: avoid; + /* Position photo to the right */ + position: absolute !important; + top: 0 !important; + right: 0 !important; + margin: 10px 0 0 0!important; + max-width: none !important; + } + + .cv-photo img { + width: 100%; + height: 100%; + object-fit: contain !important; + } + + /* Intro text should be justified and below name/years */ + .intro-text { + font-size: 9pt !important; + line-height: 1.5 !important; + text-align: justify !important; /* Justified text for print */ + margin-top: 3mm !important; + width: 100% !important; + padding-right: 0 !important; /* Intro text extends full width below photo */ + text-align-last: left !important; /* Last line left-aligned */ + } + + /* =================================== + SECTIONS - REDUCED SPACING (48px → 19px) + =================================== */ + .cv-section { + margin-bottom: 5mm !important; /* ~19px, down from 48px */ + margin-top: 7mm !important; /* More breathing space between sections */ + } + + .section-title { + font-size: 12pt !important; /* Equalized size for all titles */ + font-weight: 600 !important; + margin-top: 0 !important; + margin-bottom: 1mm !important; /* Minimal bottom margin - matches Training/Skills */ + page-break-after: avoid; + border-bottom: 0.5pt solid #dddddd !important; + padding-bottom: 2mm !important; + padding-top: 2mm !important; /* Breathing space above */ + line-height: 1.3 !important; /* Consistent line height */ + } + + /* Languages and References need more breathing space below title */ + #languages .section-title, + #references .section-title { + margin-bottom: 3mm !important; /* More space for lists */ + } + + .summary-text { + font-size: 9pt; + line-height: 1.5; + } + + /* =================================== + EXPERIENCE - REDUCED SPACING (60px → 26px) + =================================== */ + .experience-item { + display: flex !important; /* Show icons side-by-side with content */ + gap: 12px !important; + margin-bottom: 4mm !important; /* ~15px, down from 40px */ + padding-bottom: 3mm !important; /* ~11px, down from 32px */ + border-bottom: 0.5pt solid #dddddd !important; + } + + .experience-item:last-child { + border-bottom: none !important; + margin-bottom: 0 !important; /* Remove bottom margin from last experience */ + padding-bottom: 2mm !important; /* Minimal padding */ + } + + .position { + font-size: 10pt; + margin-bottom: 2pt; + } + + .company, + .company-link { + font-size: 9pt; + } + + .experience-period, + .experience-location, + .experience-duration { + font-size: 8pt; + } + + .short-desc { + font-size: 9pt !important; + line-height: 1.4 !important; + margin-top: 1mm !important; + margin-bottom: 1mm !important; + } + + .responsibilities { + margin-top: 2mm; + } + + .responsibilities li { + font-size: 9pt !important; + line-height: 1.4 !important; + margin-bottom: 1mm; + } + + /* Ensure all experience content is properly sized */ + .experience-item p, + .experience-item div { + font-size: 9pt !important; + line-height: 1.4 !important; + } + + /* Logos are visible at 40x40 for compact print layout */ + + /* =================================== + PROJECTS & COURSES + =================================== */ + .project-item, + .course-item, + .award-item { + display: flex !important; /* Show icons side-by-side with content */ + gap: 12px !important; + margin-bottom: 4mm !important; + padding-bottom: 3mm !important; + border-bottom: 0.5pt solid #dddddd !important; + } + + .project-item:last-child, + .course-item:last-child, + .award-item:last-child { + border-bottom: none !important; /* Remove border from last item */ + } + + /* Projects footer - "See all projects" link */ + .projects-footer { + margin-top: 4mm !important; + padding-top: 3mm !important; + text-align: center !important; + font-size: 9pt !important; + border-top: 0.5pt solid #dddddd !important; /* Single separator */ + } + + .projects-footer p { + margin: 0 !important; + padding: 2mm 0 !important; + } + + .projects-footer a { + color: #0066cc !important; + text-decoration: none !important; + font-weight: 600 !important; + } + + /* Logos visible at 40x40 - default icons remain hidden */ + + /* Consistent item titles */ + .project-title, + .course-title, + .experience-title, + .award-title { + font-size: 10pt !important; + font-weight: 600 !important; + line-height: 1.3 !important; + display: block !important; + margin-bottom: 1mm !important; + } + + .project-desc, + .course-desc, + .award-desc { + font-size: 9pt !important; + line-height: 1.4 !important; + margin-top: 1mm !important; + } + + /* Course/Project headers - match Experience spacing */ + .course-header, + .project-header { + margin-bottom: 0.5mm !important; /* Minimal spacing */ + } + + .course-item small, + .project-item small { + font-size: 8pt !important; + color: #666 !important; + display: inline !important; /* Inline like experience dates */ + margin-top: 0 !important; + margin-left: 0.5mm !important; + } + + /* Course metadata (date, location) - match experience style */ + .course-period, + .course-location, + .course-separator { + font-size: 8pt !important; + color: #666 !important; + display: inline !important; + } + + /* Ensure all text and paragraphs in course items are properly sized */ + .course-item p, + .course-item div, + .project-item p, + .project-item div { + font-size: 9pt !important; + line-height: 1.4 !important; + margin-top: 1mm !important; + margin-bottom: 1mm !important; + } + + .project-technologies, + .technologies { + font-size: 8pt; + } + + /* =================================== + EDUCATION & SKILLS + =================================== */ + .degree, + .skill-title, + .project-name { + font-size: 9.5pt; + } + + .institution, + .skill-list, + .project-description { + font-size: 8.5pt; + } + + .education-item { + margin-bottom: 3mm; + font-size: 9pt !important; /* Match body text size (equivalent to 0.95rem) */ + line-height: 1.5 !important; + } + + .education-item strong { + font-size: 9pt !important; /* Ensure degree title matches body text */ + font-weight: 600 !important; + } + + /* =================================== + CERTIFICATIONS & AWARDS + =================================== */ + .cert-item, + .award-item { + margin-bottom: 3mm !important; + padding-bottom: 2mm !important; + } + + .award-item strong, + .cert-item strong { + font-size: 10pt !important; + font-weight: 600 !important; + display: block !important; + margin-bottom: 1mm !important; + } + + .award-item small, + .cert-item small { + font-size: 8pt !important; + color: #666 !important; + } + + /* Ensure all award/cert content is properly sized */ + .award-item p, + .award-item div, + .cert-item p, + .cert-item div { + font-size: 9pt !important; + line-height: 1.4 !important; + margin-top: 1mm !important; + margin-bottom: 1mm !important; + } + + /* =================================== + LANGUAGES + =================================== */ + .languages-list { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 2mm; + } + + .language-item { + font-size: 9pt !important; + line-height: 1.3 !important; + margin-bottom: 1mm !important; + } + + .language-item small { + font-size: 8pt; + } + + /* =================================== + REFERENCES & OTHER + =================================== */ + .reference-item, + .other-content { + font-size: 9pt !important; + line-height: 1.3 !important; + margin-bottom: 1mm !important; + } + + /* =================================== + CONTACT INFO + =================================== */ + .cv-contact { + font-size: 8.5pt; + grid-template-columns: repeat(2, 1fr); + gap: 2mm; + } + + /* =================================== + CLEAN THEME - Full Width Main Content + =================================== */ + .theme-clean .page-content, + .page-content { + display: block !important; + grid-template-columns: 1fr !important; + } + + .theme-clean .cv-main, + .cv-main { + grid-column: 1 !important; + padding: 0 !important; + max-width: 100% !important; + } + + /* =================================== + LINKS - Print Styling + =================================== */ + a { + color: #0066cc; + text-decoration: none; + font-weight: 600; + } + + /* =================================== + CV LENGTH TOGGLE - Force Short Version for Print Friendly + =================================== */ + /* Show short descriptions */ + .cv-short .short-desc { + display: block !important; + font-size: 9pt; + line-height: 1.5; + margin-top: 2mm; + } + + /* Hide long-only content (detailed descriptions) */ + .cv-short .long-only, + .long-only { + display: none !important; + } + + /* Hide responsibilities (detailed bullet points) */ + .cv-short .responsibilities, + .responsibilities { + display: none !important; + } + + /* Long version rules (should not apply, but just in case) */ + .cv-long .short-desc { + display: none !important; + } + + .cv-long .long-only { + display: block !important; + } + + .cv-long .responsibilities { + display: block !important; + } + + /* =================================== + THEME CLEAN - Minimal Print Mode + =================================== */ + /* All sidebars, headers, footers already hidden above */ + /* Main content takes full width */ + + /* =================================== + COLLAPSIBLE SECTIONS - Force Open + =================================== */ + details { + display: block !important; + } + + summary { + display: block !important; + list-style: none !important; + } + + summary::after, + summary .section-title::after, + .sidebar-section summary::after { + display: none !important; /* Hide collapse indicators */ + } + + details > *:not(summary) { + display: block !important; + opacity: 1 !important; + max-height: none !important; + transform: none !important; + } + + /* =================================== + ENSURE PROPER TEXT RENDERING + =================================== */ + body, + .cv-paper { + font-smoothing: antialiased; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } +} diff --git a/static/css/color-theme.css b/static/css/color-theme.css index 2d0a147..431b44b 100644 --- a/static/css/color-theme.css +++ b/static/css/color-theme.css @@ -182,11 +182,11 @@ /* Dynamic colors ONLY on hover based on active theme mode */ .color-theme-switcher:hover[data-theme-mode="light"] { - background: #ffd700 !important; /* Bright sun yellow (gold) for light mode */ + background: #d4b200 !important; /* Bright sun yellow (gold) for light mode */ } .color-theme-switcher:hover[data-theme-mode="dark"] { - background: #2c3e50 !important; /* Dark nighty blue for dark mode */ + background: #013c77 !important; /* Dark nighty blue for dark mode */ } .color-theme-switcher:hover[data-theme-mode="auto"] { @@ -202,12 +202,12 @@ /* At-bottom state - dynamic colors based on theme mode (matches hover) */ .color-theme-switcher.at-bottom[data-theme-mode="light"] { opacity: 1; - background: #ffd700 !important; /* Bright sun yellow (gold) for light mode */ + background: #d4b200 !important; /* Bright sun yellow (gold) for light mode */ } .color-theme-switcher.at-bottom[data-theme-mode="dark"] { opacity: 1; - background: #2c3e50 !important; /* Dark nighty blue for dark mode */ + background: #013c77 !important; /* Dark nighty blue for dark mode */ } .color-theme-switcher.at-bottom[data-theme-mode="auto"] { diff --git a/static/css/main.css b/static/css/main.css index 1c9aba9..2e1c228 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -1,4711 +1,36 @@ -/* CV Design - Original Style Recreation */ - -/* Import Fonts */ -@import url('https://fonts.googleapis.com/css2?family=Quicksand:wght@400;500;600;700&family=Source+Sans+Pro:wght@400;600&family=Inter:wght@400;500;600;700&display=swap'); - -:root { - --bg-gray: rgb(82, 86, 89); - --sidebar-gray: #d1d4d2; - --black-bar: #2b2b2b; - --paper-white: #ffffff; - --text-dark: rgb(0, 0, 0); - --text-gray: rgb(51, 51, 51); - --accent-blue: #0066cc; - --border-gray: #dddddd; -} - -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -body { - font-family: 'Quicksand', 'Source Sans Pro', -apple-system, system-ui, sans-serif; - background-color: var(--page-bg); - background-image: - linear-gradient(90deg, rgba(0, 0, 0, 0.05) 1px, transparent 1px), - linear-gradient(180deg, rgba(0, 0, 0, 0.05) 1px, transparent 1px), - linear-gradient(90deg, rgba(0, 0, 0, 0.02) 1px, transparent 1px), - linear-gradient(180deg, rgba(0, 0, 0, 0.02) 1px, transparent 1px); - background-size: 50px 50px, 50px 50px, 10px 10px, 10px 10px; - background-attachment: fixed; - color: var(--text-secondary); - line-height: 1.5; - font-size: 16px; - font-weight: 400; - overflow-x: auto; /* Allow horizontal scroll when zoomed */ -} - -a { - color: var(--accent-blue); - text-decoration: none; -} - -a:hover { - text-decoration: underline; -} - -/* Single Black Top Bar */ -.action-bar { - background: var(--action-bar-bg); - color: var(--action-bar-text); - position: sticky; - top: 0; - z-index: 100; - box-shadow: var(--shadow-md); - font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; -} - -.action-bar-content { - max-width: 100%; - margin: 0 auto; - padding: 0; - display: grid; - grid-template-columns: 1fr auto 1fr; - align-items: stretch; - gap: 2rem; - height: 50px; -} - -/* Left: Site Title */ -.site-title { - display: flex; - align-items: center; - gap: 0.75rem; - justify-self: start; - white-space: nowrap; - padding: 0; - height: 100%; -} - -.site-title-left { - display: flex; - align-items: center; - gap: 0.75rem; -} - -.site-icon { - color: #fff; - flex-shrink: 0; - display: inline-flex; - align-items: center; - justify-content: center; - height: 36px; - padding: 0 .5rem 0 1.5rem; -} - -/* Mobile icon hidden by default, shown only on mobile */ -.site-icon-mobile { - display: none; - color: #fff; - flex-shrink: 0; - margin-right: 0.5rem; -} - -/* Site logo and title links */ -.site-logo-link, -.site-title-link { - text-decoration: none; - color: inherit; - display: flex; - align-items: center; - height: 36px; - transition: opacity 0.2s ease; -} - -.site-logo-link:hover, -.site-title-link:hover { - opacity: 0.8; - text-decoration: none; -} - -.site-logo-link { - padding: 0; -} - -/* Ensure Iconify icons display properly */ -.iconify, -iconify-icon { - display: inline-block; - vertical-align: middle; -} - -.site-title-text { - font-size: 1.05rem; - font-weight: 500; - color: #fff; - letter-spacing: -0.01em; - line-height: 1; - display: flex; - align-items: center; - height: 36px; - padding: 0 1rem 0 0rem; -} - -/* Center: View controls with labels */ -.view-controls-center { - display: flex; - flex-direction: row; - align-items: center; - gap: 2.5rem; - justify-self: center; - flex-shrink: 0; - white-space: nowrap; - height: 100%; -} - -.selector-group { - display: flex; - align-items: center; - gap: 0.75rem; -} - -.selector-label { - font-size: 0.875rem; - color: rgba(255,255,255,0.85); - font-weight: 500; - white-space: nowrap; - letter-spacing: -0.01em; - line-height: 1; - display: flex; - align-items: center; - height: 36px; -} - -.selector-label span { - color: #27ae60; - font-weight: 600; -} - -.language-toggle, -.cv-length-toggle, -.logo-toggle { - flex-shrink: 0; -} - -/* Right: Action buttons */ -.action-buttons { - justify-self: end; - flex-shrink: 0; -} - -.htmx-indicator { - flex-shrink: 0; -} - -.lang-btn { - padding: 0.4rem 1rem; - border: 1px solid rgba(255,255,255,0.3); - background: transparent; - color: white; - border-radius: 3px; - cursor: pointer; - font-size: 1rem; - font-weight: 400; - text-transform: capitalize; - transition: all 0.2s ease; -} - -.lang-btn:hover { - background: rgba(255,255,255,0.1); - border-color: rgba(255,255,255,0.5); -} - -.lang-btn.active { - background: #27ae60 !important; - border-color: #27ae60 !important; - font-weight: 500; -} - -/* Icon Toggle Switches */ -.icon-toggle { - position: relative; - display: flex; - cursor: pointer; -} - -.icon-toggle input[type="checkbox"] { - position: absolute; - opacity: 0; - width: 0; - height: 0; -} - -.icon-toggle-slider { - position: relative; - display: inline-flex; - align-items: center; - justify-content: space-between; - width: 75px; - height: 30px; - background: #e0e0e0; - border: 2px solid #d0d0d0; - border-radius: 15px; - padding: 0 6px; - transition: all 0.3s ease; -} - -.icon-toggle-slider::before { - content: ''; - position: absolute; - width: 24px; - height: 24px; - left: 2px; - background: white; - border-radius: 50%; - transition: transform 0.3s ease; - box-shadow: 0 2px 4px rgba(0,0,0,0.3); - z-index: 2; - pointer-events: none; -} - -.icon-toggle input:checked + .icon-toggle-slider::before { - transform: translateX(43px); -} - -.icon-toggle input:checked + .icon-toggle-slider { - background: #27ae60; - border-color: #229954; -} - -.icon-toggle-slider .icon-left, -.icon-toggle-slider .icon-right { - position: absolute; - z-index: 3; - transition: all 0.3s ease; - flex-shrink: 0; - pointer-events: none; -} - -.icon-toggle-slider .icon-left { - left: 6px; -} - -.icon-toggle-slider .icon-right { - right: 6px; -} - -.icon-toggle input:not(:checked) + .icon-toggle-slider .icon-left { - color: #333 !important; - font-weight: bold; -} - -.icon-toggle input:not(:checked) + .icon-toggle-slider .icon-right { - color: #999 !important; - opacity: 0.5; -} - -.icon-toggle input:checked + .icon-toggle-slider .icon-left { - color: rgba(255,255,255,0.4) !important; - opacity: 0.5; -} - -.icon-toggle input:checked + .icon-toggle-slider .icon-right { - color: white !important; - font-weight: bold; -} - -.icon-toggle input:focus + .icon-toggle-slider { - box-shadow: 0 0 0 3px rgba(39, 174, 96, 0.2); -} - -/* Language selector wrapper - contains indicators outside swap target */ -.language-selector-wrapper { - position: relative; - display: inline-flex; - height: 100%; - /* Ensure wrapper doesn't create extra spacing */ - width: fit-content; -} - -/* Language selector - matching action button style */ -.language-selector { - display: inline-flex; - gap: 0; - padding: 0; - padding-left: 1rem; /* Space after the title */ - margin-right: 0; - background: transparent; - border-radius: 0; - height: 100%; - align-items: stretch; -} - -/* Position language indicators next to their respective buttons */ -#lang-indicator-en, -#lang-indicator-es { - position: absolute; - top: 50%; - transform: translateY(-50%); - pointer-events: none; - z-index: 10; -} - -/* Position indicators inside the button visual area */ -#lang-indicator-en { - left: calc(1rem + 50px); /* Inside first button */ -} - -#lang-indicator-es { - left: calc(1rem + 135px); /* Inside second button */ -} - -.selector-btn { - padding: 0 1.5rem; - background: transparent; - color: white; - border: none; - border-radius: 0; - cursor: pointer; - font-size: 1rem; - font-weight: 500; - display: inline-flex; - align-items: center; - justify-content: center; - /* gap: 0.5rem; */ - gap: 0rem; - text-decoration: none; - white-space: nowrap; - letter-spacing: -0.01em; - height: 100%; - line-height: 1; - transition: all 0.2s ease; - outline: none !important; - box-shadow: none !important; - min-width: 50px!important; -} - -.selector-btn:focus, -.selector-btn:focus-visible, -.selector-btn:active { - outline: none !important; - box-shadow: none !important; -} - -.selector-btn:hover { - background: #666; -} - -.selector-btn:hover iconify-icon { - color: #27ae60; -} - -.selector-btn.active { - background: #27ae60; - color: white; -} - -.selector-btn:not(.active) { - background: transparent; - color: white; -} - -/* Language selector buttons - no global animations (applied in responsive range only) */ - -/* Action buttons - transparent with white text */ -.action-btn { - padding: 0 1.5rem; - background: transparent; - color: white; - border: none; - border-radius: 0; - cursor: pointer; - font-size: 1rem; - font-weight: 500; - display: inline-flex; - align-items: center; - justify-content: center; - gap: 0.5rem; - text-decoration: none; - white-space: nowrap; - letter-spacing: -0.01em; - height: 100%; - line-height: 1; - transition: background-color 0.3s ease, color 0.3s ease; /* Smooth color transitions */ -} - -.action-btn iconify-icon { - color: white; - transition: color 0.3s ease; /* Smooth icon color transition */ -} - -.action-btn:hover { - background: #ddd; - color: #333; - text-decoration: none; -} - -.action-btn:hover iconify-icon { - color: #27ae60; -} - -/* PDF Download button - gray by default, red on hover */ -.pdf-btn { - background: transparent !important; /* Transparent like other buttons */ - color: white !important; -} - -.pdf-btn:hover, -.pdf-btn.pdf-hover-sync { - background: #cd6060 !important; /* PDF red on hover */ - color: white !important; -} - -.pdf-btn iconify-icon { - color: white !important; - filter: brightness(0) invert(1); /* Always white */ - transition: filter 0.3s ease; -} - -.pdf-btn:hover iconify-icon { - color: white !important; - filter: brightness(0) invert(1); /* Keep white on hover */ -} - -/* Print Friendly button - white bg with green icon on hover */ -.print-btn { - background: transparent !important; - color: white !important; -} - -.print-btn:hover, -.print-btn.print-hover-sync { - background: white !important; /* White background on hover */ - color: #27ae60 !important; /* Green icon on hover */ -} - -.print-btn iconify-icon { - color: white; /* White icon by default */ -} - -.print-btn:hover iconify-icon, -.print-btn.print-hover-sync iconify-icon { - color: #27ae60; /* Green icon on hover */ -} - -/* CV Length Toggle - Center of action bar */ -.cv-length-toggle { - display: flex; - gap: 0.5rem; - justify-self: center; -} - -.length-btn { - padding: 0.4rem 1rem; - border: 1px solid rgba(255,255,255,0.4); - background: rgba(255,255,255,0.1); - color: white; - border-radius: 4px; - cursor: pointer; - font-size: 0.9rem; - font-weight: 500; - transition: all 0.2s ease; -} - -.length-btn:hover { - background: rgba(255,255,255,0.2); - border-color: rgba(255,255,255,0.6); -} - -.length-btn.active { - background: white; - color: #1a1a1a; - border-color: white; - font-weight: 600; -} - -/* Action buttons styling (already positioned by grid) */ -.action-buttons, -.action-buttons-right { - display: flex; - gap: 0; - align-items: stretch; - height: 100%; -} - -.action-buttons-right { - justify-self: end; - margin-left: auto; -} - /* ============================================================================ - HTMX Loading Indicators - ========================================================================= */ - -/* Base indicator styles - hidden by default with opacity for smooth transitions */ -.htmx-indicator { - opacity: 0; /* Hidden by default */ - transition: opacity 200ms ease-in-out; - pointer-events: none; - display: inline-flex; - align-items: center; - justify-content: center; - position: absolute; /* Remove from layout flow to prevent spacing issues */ -} - -/* Override for when request is active - must come AFTER base rule */ -.htmx-indicator.htmx-request, -#lang-indicator-en.htmx-request, -#lang-indicator-es.htmx-request { - opacity: 1 !important; /* Force visible state */ -} - -/* Ensure iconify-icon indicators override global iconify-icon display style */ -iconify-icon.htmx-indicator { - display: inline-flex; - align-items: center; - justify-content: center; -} - -/* Show indicators during HTMX requests */ -/* Using span wrapper, so target span.htmx-request specifically */ -span.htmx-request.htmx-indicator, -.htmx-request .htmx-indicator, -.htmx-request.htmx-indicator { - opacity: 1 !important; -} - -/* Spinning animation for loading icons */ -.htmx-indicator.spinning { - animation: htmx-spin 1s linear infinite; -} - -@keyframes htmx-spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } -} - -/* Indicator size variants */ -.htmx-indicator.small { - width: 14px; - height: 14px; - font-size: 14px; -} - -.htmx-indicator.medium { - width: 18px; - height: 18px; - font-size: 18px; -} - -.htmx-indicator.large { - width: 24px; - height: 24px; - font-size: 24px; -} - -/* Positioning variants */ -.htmx-indicator.inline { - display: inline-flex; - margin-left: 8px; - vertical-align: middle; -} - -.htmx-indicator.inline-start { - display: inline-flex; - margin-right: 8px; - vertical-align: middle; -} - -/* Color variants for different contexts */ -.htmx-indicator.light { - color: rgba(255, 255, 255, 0.9); -} - -.htmx-indicator.dark { - color: rgba(0, 0, 0, 0.7); -} - -.htmx-indicator.accent { - color: #27ae60; -} - -/* Respect reduced motion preference */ -@media (prefers-reduced-motion: reduce) { - .htmx-indicator.spinning { - animation: none; - } - .htmx-indicator { - transition: none; - } -} - -/* Legacy loader class for backward compatibility */ -.loader { - border: 2px solid #f3f3f3; - border-top: 2px solid white; - border-radius: 50%; - width: 20px; - height: 20px; - animation: htmx-spin 1s linear infinite; -} - -/* ============================================================================ - Inline Loading States for HTMX Transitions - ========================================================================= */ - -/* Inline loading states - no blocking overlay, smooth transitions only */ -/* Language selector buttons already have htmx-indicator spinners */ -/* CV content areas show subtle fade during swap */ - -/* Zoom Wrapper - wraps cv-container for zoom functionality */ -.zoom-wrapper { - /* CSS zoom property changes actual layout space (not just visual) */ - /* This allows footer to naturally position right after zoomed content */ -} - -/* Main CV Container */ -.cv-container { - width: 100%; - max-width: 100%; /* Full width to accommodate pages */ - margin: 0 auto; - padding: 20px 0 0 0; /* Top padding to prevent sticky action bar overlap */ - display: block; /* Changed from flex */ -} - -/* Clean theme - no sidebars, centered content */ -.cv-container.theme-clean { - padding: 20px 0 0 0; - transition: all 0.3s ease-in-out; -} - -.theme-clean .cv-page { - box-shadow: var(--shadow-lg); - border: 1px solid var(--border-color); - margin: 0 auto; - max-width: 900px; - transition: all 0.3s ease-in-out; -} - -/* Animate sidebar, header, footer when hiding/showing */ -.cv-sidebar, -.cv-title-badges-header, -.cv-footer { - overflow: hidden; - transition: all 0.3s ease-in-out; -} - -.theme-clean .cv-sidebar, -.theme-clean .cv-title-badges-header, -.theme-clean .cv-footer { - display: none !important; - animation: fadeOutShrink 0.3s ease-in-out; -} - -.theme-clean .page-content { - grid-template-columns: 1fr !important; - transition: grid-template-columns 0.3s ease-in-out; -} - -.theme-clean .cv-main { - grid-column: 1 !important; - padding: 2rem 3rem!important; - transition: all 0.3s ease-in-out; -} - -/* CV Paper - Container for two-page layout */ -.cv-paper { - width: 100%; - background: transparent; /* Remove white background - each page has its own */ - box-shadow: none; /* Remove shadow - each page has its own */ - margin: 0; - position: relative; - display: block; /* Changed from grid to block for stacking pages */ - min-height: auto; /* Changed from 100vh */ - - /* Zoom transform properties */ - transform-origin: top center; /* Scale from top center - page stays anchored at top */ - transition: transform 0.08s linear; /* Smooth, immediate zoom response */ - will-change: transform; /* Hint browser to optimize for transforms */ -} - -/* Page break helpers */ -.page-break { - page-break-after: always; - break-after: page; -} - -.avoid-break { - page-break-inside: avoid; - break-inside: avoid; -} - -/* Sidebar - Left column */ -.cv-sidebar { - background: var(--sidebar-gray); - padding: 4rem 1.5rem; - font-size: 0.9rem; -} - -/* Sidebar Accordion - Hidden on desktop, visible on mobile */ -.sidebar-accordion-header { - display: none; -} - -.sidebar-accordion-content { - /* Always visible on desktop */ -} - -.sidebar-section { - margin-bottom: 2rem; -} - -/* Add margin when sidebar section is collapsed */ -.sidebar-section:has(details:not([open])) { - margin-bottom: 3rem; - margin-top: 0rem; -} - -.sidebar-title { - font-family: 'Quicksand', sans-serif; - font-size: 1.4em; - font-weight: 700; - line-height: 1.3em; - margin-bottom: 10px; - padding: 0; - color: rgb(51, 51, 51); - text-align: left; -} - -/* Collapsible Sidebar Section Styles */ -.sidebar-section details { - margin: 0; -} - -.sidebar-section details summary ~ * { - overflow: hidden; - max-height: 0; - opacity: 0; - transform: translateY(-8px); - transition: max-height 0.5s ease-in-out, - opacity 0.3s ease-in-out, - transform 0.3s ease-in-out; -} - -.sidebar-section details[open] summary ~ * { - max-height: 1500px; - opacity: 1; - transform: translateY(0); -} - -.sidebar-section summary { - cursor: pointer; - list-style: none; - user-select: none; - position: relative; - display: flex; - align-items: center; - justify-content: space-between; -} - -/* Remove default triangle marker */ -.sidebar-section summary::-webkit-details-marker, -.sidebar-section summary::marker { - display: none; -} - -/* Sidebar title - no special positioning */ -.sidebar-section summary .sidebar-title { - margin-bottom: 0; -} - -/* Add custom collapse indicator at the far right (left sidebar) */ -.cv-sidebar-left .sidebar-section summary::after { - content: '▶'; - font-size: 0.8em; - color: rgb(100, 100, 100); - transition: transform 0.2s ease, opacity 0.2s ease; - opacity: 0; - margin-left: 15px; - flex-shrink: 0; -} - -/* Add custom collapse indicator at the far left (right sidebar) */ -.cv-sidebar-right .sidebar-section summary { - flex-direction: row-reverse; - justify-content: space-between; -} - -.cv-sidebar-right .sidebar-section summary .sidebar-title { - text-align: right; - width: 100%; -} - -/* Left-align content in left sidebar */ -.cv-sidebar-left .sidebar-content { - text-align: left; -} - -.cv-sidebar-left .skill-item { - text-align: left; -} - -/* Right-align content in right sidebar */ -.cv-sidebar-right .sidebar-content { - text-align: right; -} - -.cv-sidebar-right .skill-item { - text-align: right; -} - -.cv-sidebar-right .sidebar-section summary::after { - content: '▶'; - font-size: 0.8em; - color: rgb(100, 100, 100); - transition: transform 0.2s ease, opacity 0.2s ease; - opacity: 0; - margin-right: 15px; - flex-shrink: 0; -} - -/* Show indicator on hover or when closed */ -.sidebar-section summary:hover::after, -.sidebar-section details:not([open]) summary::after { - opacity: 1; -} - -/* Rotate indicator when open */ -.sidebar-section details[open] summary::after { - transform: rotate(90deg); -} - -/* Hover effect on sidebar summary */ -.sidebar-section summary:hover .sidebar-title { - color: var(--accent-blue); -} - -.sidebar-content { - font-family: 'Quicksand', sans-serif; - font-size: 0.95rem; - font-weight: 400; - line-height: 1.5; -} - -/* Add breathing space when sidebar section is open */ -.sidebar-section details[open] .sidebar-content { - margin-top: 0.5rem; -} - -.skill-item { - margin-bottom: 0.15rem; - color: rgb(0, 0, 0); - font-weight: 400; -} - -/* Main Content - Right column */ -.cv-main { - background: var(--paper-white); - padding: 3rem 2.5rem 8rem 2.5rem; /* Bottom padding for footer and zoom control clearance */ -} - -/* Professional Title Badges - Spans Both Columns */ -.cv-title-badges-header { - grid-column: 1 / -1; /* Span all columns */ - background: #303030 !important; /* Elegant dark gray */ - padding: 10px 20px; - display: flex; - flex-wrap: wrap; - justify-content: center; - align-items: center; - gap: 0; - border-bottom: 2px solid #34495e; -} - -.title-badge { - font-size: 0.9em; - font-weight: normal; - color: #ccc; - text-transform: uppercase; - white-space: nowrap; -} - -.badge-separator { - color: #ccc; - font-weight: normal; - padding: 0 15px; - position: relative; - top: -1px; -} - -/* Header with photo and name */ -.cv-header { - margin-bottom: 2rem; -} - -.cv-header-content { - display: flex; - justify-content: space-between; - align-items: flex-start; - gap: 2rem; -} - -.cv-header-left { - flex: 1; - position: relative; - /* Desktop: Add right padding to make room for the photo */ - padding-right: 185px; /* Photo width (150px) + gap (35px) */ -} - -.cv-photo { - width: 150px; - height: 200px; - flex-shrink: 0; - overflow: hidden; - border: 3px solid white; - box-shadow: 0 2px 8px rgba(0,0,0,0.15); - - /* Desktop: Position photo in the right padding area */ - position: absolute; - top: 15px; - right: 15px; /* Margin from the right edge */ -} - -.cv-photo img { - width: 100%; - height: 100%; - object-fit: cover; -} - -.cv-name { - font-family: 'Quicksand', sans-serif; - font-size: 2.2em; - font-weight: 400; - {{/* font-style: italic; */}} - line-height: 1.1; - margin-bottom: 8px; - color: rgb(0, 0, 0); - text-align: right; -} - -.cv-experience-years { - font-family: 'Quicksand', sans-serif; - font-size: 0.9em; - font-weight: 500; - line-height: 1.5; - color: rgb(0, 0, 0); - margin: 0; -} - -.years-experience { - font-family: 'Quicksand', sans-serif; - font-size: 1.25em; - font-weight: 400; - color: #666; - margin: 4px 0 0 0; - line-height: 1.4; - text-align: right; -} - -/* Intro/Excerpt Text - Positioned inside header, matching old React CV */ -.intro-text { - font-family: 'Quicksand', sans-serif; - font-size: 1.0em; - line-height: 1.6; - color: rgb(51, 51, 51); - margin-top: 20px; - text-align: justify; - font-style: italic; -} - -/* Sections */ -.cv-section { - margin-bottom: 3rem; - page-break-inside: avoid; -} - -/* Remove margin when section is collapsed */ -.cv-section:has(details:not([open])) { - margin-bottom: 0; -} - -.section-title { - font-family: 'Quicksand', sans-serif; - font-size: 1.4em; - font-weight: 500; - line-height: 1.2em; - margin: 20px 0 25px 0; - padding: 0; - color: rgb(51, 51, 51); -} - -/* Collapsible Section Styles */ -.cv-section details { - margin: 0; -} - -.cv-section details summary ~ * { - overflow: hidden; - max-height: 0; - opacity: 0; - transform: translateY(-8px); - transition: max-height 0.5s ease-in-out, - opacity 0.3s ease-in-out, - transform 0.3s ease-in-out; -} - -.cv-section details[open] summary ~ * { - max-height: 3000px; - opacity: 1; - transform: translateY(0); -} - -.cv-section summary { - cursor: pointer; - list-style: none; - user-select: none; - position: relative; -} - -/* Remove default triangle marker in all browsers */ -.cv-section summary::-webkit-details-marker, -.cv-section summary::marker { - display: none; -} - -/* Add custom collapse indicator after the title */ -.cv-section summary .section-title { - display: inline-flex; - align-items: center; - gap: 0.5rem; -} - -.cv-section summary .section-title::after { - content: '▼'; - font-size: 0.8em; - color: rgb(100, 100, 100); - transition: transform 0.2s ease, opacity 0.2s ease; - opacity: 0; - margin-left: 0.5rem; -} - -/* Show indicator on hover or when closed */ -.cv-section summary:hover .section-title::after, -.cv-section details:not([open]) summary .section-title::after { - opacity: 1; -} - -/* Rotate indicator when closed */ -.cv-section details:not([open]) summary .section-title::after { - transform: rotate(-90deg); -} - -/* Hover effect on summary */ -.cv-section summary:hover .section-title { - color: var(--accent-blue); -} - -.summary-text { - font-family: 'Quicksand', sans-serif; - line-height: 1.5; - text-align: justify; - font-size: 0.9em; - font-weight: 400; - color: rgb(0, 0, 0); -} - -/* Experience */ -/* Experience item layout moved to logo-toggle.css */ - -.experience-header { - margin-bottom: 0.6rem; -} - -.experience-title-line { - margin-bottom: 0.3em; -} - -.position { - font-size: 1rem; - font-weight: 500; - margin: 0; - color: var(--text-dark); - margin-bottom: 4px; -} - -.position .position-title { - display: inline-block; - margin-right: 0.3em; -} - -.position .company-name { - display: inline-block; -} - -.current-badge { - display: inline-block; - background: #27ae60; - color: white; - font-weight: 700; - font-size: 0.7em; - padding: 0.2em 0.5em; - border-radius: 3px; - margin-left: 0.5em; - vertical-align: middle; - letter-spacing: 0.5px; -} - -.live-badge { - display: inline-flex; - align-items: center; - gap: 0.3em; - background: #27ae60; - color: white; - font-weight: 700; - font-size: 0.7em; - padding: 0.2em 0.5em; - border-radius: 3px; - margin-left: 0.5em; - vertical-align: middle; - letter-spacing: 0.5px; -} - -.live-badge iconify-icon { - font-size: 1.2em; -} - -.expired-badge { - display: inline-block; - background: #e74c3c; - color: white; - font-weight: 700; - font-size: 0.7em; - padding: 0.2em 0.5em; - border-radius: 3px; - margin-left: 0.5em; - vertical-align: middle; - letter-spacing: 0.5px; -} - -.maintained-badge { - display: inline-block; - background: #3498db; - color: white; - font-weight: 700; - font-size: 0.7em; - padding: 0.2em 0.5em; - border-radius: 3px; - margin-left: 0.5em; - vertical-align: middle; - letter-spacing: 0.5px; -} - -.experience-period, -.experience-separator, -.experience-location, -.experience-duration { - color: #555; - font-weight: 600; - display: inline-block; - font-size: 1.05rem; -} - -.experience-duration { - font-style: italic; -} - -.short-desc { - color: var(--text-dark); - font-size: 0.95rem; - line-height: 1.6; - margin-top: 0.5rem; -} - -.duration-text { - color: #aaa; - font-weight: 500; -} - -.responsibilities { - list-style: none; - margin-top: 1rem; - padding-left: 0; -} - -.responsibilities li { - padding-left: 1.2rem; - margin-bottom: 0.4rem; - position: relative; - font-size: 0.95rem; - color: var(--text-dark); - line-height: 1.5; -} - -.responsibilities li:before { - content: "•"; - position: absolute; - left: 0; - color: var(--text-gray); -} - -/* Responsibilities with company icons (similar to main experience layout) */ -.responsibilities li:has(img), -.responsibilities li:has(iconify-icon) { - display: grid; - grid-template-columns: 60px 1fr; - gap: 1rem; - padding-left: 0; - margin-bottom: 1rem; - align-items: start; -} - -.responsibilities li:has(img):before, -.responsibilities li:has(iconify-icon):before { - display: none; -} - -.responsibilities li img { - width: 60px; - height: 60px; - object-fit: contain; - border-radius: 4px; - border: 1px solid #ddd; - background: #f5f5f5; - padding: 4px; -} - -.responsibilities li iconify-icon.default-company-icon { - width: 60px; - height: 60px; - display: flex; - align-items: center; - justify-content: center; - border-radius: 4px; - border: 1px solid #ddd; - background: #f5f5f5; - color: #999; - padding: 8px; -} - -/* Education */ -.education-item { - margin-bottom: 1rem; - font-size: 0.95rem; - line-height: 1.6; - color: var(--text-dark); -} - - -/* Languages */ -.languages-list { - display: flex; - flex-wrap: wrap; - gap: 1.5rem; -} - -.language-item { - font-size: 0.95rem!important; - color: var(--text-dark); - margin-bottom: 0.3rem!important; - line-height: 1.4!important; - margin-left: 2rem!important; -} - -.language-item small { - display: block; - font-size: 0.8em; - margin-top: 0.2rem; - font-style: italic; -} - -/* Experience Items */ -.experience-item { - margin-bottom: 2.5rem; - padding-bottom: 2rem; - border-bottom: 1px solid rgba(0, 0, 0, 0.1); -} - -/* Keep border on all experience items including last one */ - -/* Courses */ -.course-item { - display: flex; - gap: 1.2rem; - align-items: flex-start; - margin-bottom: 2.5rem; - padding-bottom: 2rem; - border-bottom: 1px solid rgba(0, 0, 0, 0.1); -} - -/* Keep border on all course items including last one */ - -.course-icon { - flex-shrink: 0; - width: 80px; - height: 80px; - display: flex; - align-items: center; - justify-content: center; -} - -.course-icon img { - width: 80px; - height: 80px; - object-fit: contain; - border-radius: 4px; - border: 1px solid #ddd; - background: #f5f5f5; - padding: 4px; -} - -.default-course-icon { - width: 80px; - height: 80px; - display: flex; - align-items: center; - justify-content: center; - border-radius: 4px; - border: 1px solid #ddd; - background: #f5f5f5; - color: #999; - padding: 10px; -} - -.course-content { - flex: 1; -} - -.course-header { - margin-bottom: 0.5rem; -} - -.course-title { - font-size: 1em; - font-weight: 600; - margin: 0 0 0.3rem 0; - line-height: 1.4; - color: var(--text-dark); -} - -.course-title-text { - display: inline; -} - -.course-institution { - display: inline; - margin-left: 0.5em; - font-weight: normal; -} - -.course-period, -.course-separator, -.course-location, -.course-duration { - color: #555; - font-size: 0.9em; -} - -.course-separator { - color: #999; -} - -.course-desc { - font-size: 0.85em; - color: var(--text-gray); - margin-top: 0.4rem; - line-height: 1.4; - text-align: justify; -} - -/* Projects */ -.project-item { - display: flex; - gap: 1.2rem; - align-items: flex-start; - margin-bottom: 2.5rem; - padding-bottom: 2rem; - border-bottom: 1px solid rgba(0, 0, 0, 0.1); -} - -.project-icon { - flex-shrink: 0; - width: 80px; - height: 80px; - display: flex; - align-items: center; - justify-content: center; -} - -.project-icon img { - width: 80px; - height: 80px; - object-fit: contain; - border-radius: 4px; - border: 1px solid #ddd; - background: #f5f5f5; - padding: 4px; -} - -.default-project-icon { - width: 80px; - height: 80px; - display: flex; - align-items: center; - justify-content: center; - border-radius: 4px; - border: 1px solid #ddd; - background: #f5f5f5; - color: #999; - padding: 10px; -} - -.project-content { - flex: 1; -} - -.project-header { - margin-bottom: 0.5rem; -} - -.project-title { - font-size: 1em; - font-weight: 600; - margin: 0 0 0.3rem 0; - line-height: 1.4; - color: var(--text-dark); -} - -.project-title-text { - display: inline; -} - -.project-title-text a { - color: var(--accent-blue); - text-decoration: none; -} - -.project-title-text a:hover { - text-decoration: underline; -} - -.project-period, -.project-separator, -.project-location { - color: #555; - font-size: 0.9em; - font-weight: 600; -} - -.project-separator { - color: #999; -} - -.project-desc { - font-size: 0.95rem; - color: var(--text-dark); - margin-top: 0.5rem; - line-height: 1.6; - text-align: justify; -} - -.project-technologies { - font-size: 0.85em; - color: var(--text-gray); - margin-top: 0.5rem; - line-height: 1.4; -} - -.projects-footer { - margin-top: -1.5rem; - padding-top: 0rem; - text-align: center; - font-size: 0.95rem; - color: var(--text-gray); -} - -.projects-footer p { - margin: 0; -} - -.projects-footer a { - color: var(--accent-blue); - text-decoration: none; -} - -.projects-footer a:hover { - text-decoration: underline; -} - -/* References */ -.reference-item { - margin-bottom: 0!important; - line-height: 1.4!important; - margin-left: 2rem!important; - font-size: 0.95rem!important; -} - -.reference-item a { - - color: var(--accent-blue); - text-decoration: none; - word-break: break-word; -} - -.reference-item a:hover { - text-decoration: underline; -} - -.ref-type { - display: block; - font-size: 0.8em; - color: var(--text-gray); - font-style: italic; - margin-top: 0.2rem; -} - -/* Footer */ -footer { - text-align: center; - padding: 2rem; - color: rgba(255,255,255,0.7); - font-size: 0.85rem; -} - -/* GitHub repository link styling */ -.github-repo-link { - color: whitesmoke !important; - transition: color 0.2s ease-in-out; -} - -.github-repo-link:hover { - color: #66B3FF !important; -} - - -/* CV Version Toggle Animations */ -@keyframes fadeInGrow { - from { - opacity: 0; - max-height: 0; - transform: scaleY(0.8); - transform-origin: top; - } - to { - opacity: 1; - max-height: 5000px; - transform: scaleY(1); - } -} - -@keyframes fadeOutShrink { - from { - opacity: 1; - max-height: 5000px; - transform: scaleY(1); - } - to { - opacity: 0; - max-height: 0; - transform: scaleY(0.8); - transform-origin: top; - } -} - -/* Elements that appear/disappear */ -.long-only, -.short-desc { - overflow: hidden; - transition: all 0.3s ease-in-out; -} - -/* Short CV - Hide detailed content with animation */ -.cv-short .long-only { - display: none; - animation: fadeOutShrink 0.3s ease-in-out; -} - -.cv-short .short-desc { - display: block; - animation: fadeInGrow 0.3s ease-in-out; -} - -/* Long CV - Hide short descriptions with animation */ -.cv-long .short-desc, -.short-desc { - display: none; - animation: fadeOutShrink 0.3s ease-in-out; -} - -.cv-long .long-only { - display: block; - animation: fadeInGrow 0.3s ease-in-out; -} - -.cv-long .responsibilities { - display: block; - animation: fadeInGrow 0.3s ease-in-out; -} - -/* Responsive - tablet/mobile */ -@media (max-width: 900px) { - .cv-paper { - grid-template-columns: 1fr; - box-shadow: none; - } - - .cv-sidebar { - padding: 1.5rem 1rem; - } - - .cv-main { - padding: 1.5rem 1rem; - } - - .cv-name { - font-size: 1.8rem; - } - - .intro-text { - font-size: 0.9em; - margin-top: 15px; - } - - .action-bar-content { - grid-template-columns: 1fr; - gap: 1rem; - padding: 0rem; - } - - .language-toggle, - .cv-length-toggle, - .action-buttons { - justify-self: center !important; - justify-content: center; - width: 100%; - } - - .experience-title-line { - flex-direction: column; - align-items: flex-start; - gap: 0.25rem; - } - - /* ========== Hide header controls, show in menu ========== */ - /* Keep language selector visible in header */ - .view-controls-center { - display: none !important; - } - - .action-buttons-right { - display: none !important; - } - - /* Show controls and actions in hamburger menu */ - .menu-controls-section, - .menu-actions-section { - display: block !important; - } -} - -.no-print {} - -/* Smooth Transitions for HTMX Swaps */ -.cv-paper { - transition: opacity 200ms ease-in-out; -} - -/* Inline loading states for CV content during language transitions */ -.cv-page-content-wrapper.htmx-swapping { - opacity: 0.5; - transform: scale(0.99); - pointer-events: none; - filter: blur(1px); -} - -.cv-page-content-wrapper.htmx-settling { - opacity: 1; - transform: scale(1); - pointer-events: auto; - filter: blur(0); -} - -/* Respect reduced motion preference */ -@media (prefers-reduced-motion: reduce) { - .cv-page-content-wrapper.htmx-swapping { - transform: none; - filter: none; - opacity: 0.7; - } -} - -/* Focus Styles for Accessibility */ -button:focus, -a:focus { - outline: 2px solid var(--accent-blue); - outline-offset: 2px; -} - -/* Loading indicator animation */ -@keyframes spin { - to { transform: rotate(360deg); } -} - -/* Error Toast */ -.error-toast { - position: fixed; - bottom: 2rem; - right: 2rem; - background: #fee2e2; - color: #dc2626; - padding: 1rem 1.5rem; - border-radius: 8px; - border-left: 4px solid #dc2626; - box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); - display: none; /* Hidden by default */ - align-items: center; - gap: 1rem; - max-width: 400px; - z-index: 1000; - font-size: 0.95rem; -} - -/* Show toast with full animation cycle: slide in -> stay -> fade out */ -.error-toast.show { - display: flex; - animation: toastLifecycle 5.5s ease-out forwards; -} - -/* Full lifecycle animation: slide in (0-0.3s), stay (0.3-5s), fade out (5-5.5s) */ -@keyframes toastLifecycle { - 0% { - transform: translateX(120%); - opacity: 0; - } - 5.5% { /* 0.3s / 5.5s = 5.5% */ - transform: translateX(0); - opacity: 1; - } - 90.9% { /* 5s / 5.5s = 90.9% - stay visible */ - transform: translateX(0); - opacity: 1; - } - 100% { /* Final 0.5s - fade out and slide right */ - transform: translateX(120%); - opacity: 0; - } -} - -.error-icon { - font-size: 1.25rem; - flex-shrink: 0; -} - -.error-toast button.error-close { - background: none; - border: none; - font-size: 1.5rem; - color: #dc2626; - cursor: pointer; - padding: 0; - width: 24px; - height: 24px; - display: flex; - align-items: center; - justify-content: center; - transition: opacity 0.2s; - flex-shrink: 0; - line-height: 1; -} - -.error-toast button.error-close:hover { - opacity: 0.7; -} - -.error-toast button.error-close:focus { - outline: 2px solid #dc2626; - outline-offset: 2px; -} - -/* Mobile responsive error toast */ -@media (max-width: 768px) { - .error-toast { - left: 1rem; - right: 1rem; - bottom: 1rem; - max-width: none; - } -} - -/* =============================================== - TWO-PAGE LAYOUT STYLES - =============================================== */ - -/* Page Container - Each CV page */ -.cv-page { - background: var(--paper-bg); - max-width: 1200px; - margin: 2rem auto; - box-shadow: var(--shadow-lg); - border: 1px solid var(--border-color); - transform: scale(0.95); - transform-origin: top center; - transition: transform 0.3s ease; -} - -/* Page Content Grid */ -.page-content { - display: grid; -} - -/* Page 1: Left sidebar + Main content */ -.page-1 .page-content { - grid-template-columns: 300px 1fr; -} - -/* Page 2: Main content + Right sidebar */ -.page-2 .page-content { - grid-template-columns: 1fr 300px; -} - -/* Sidebar positioning */ -.cv-sidebar-left { - grid-column: 1; - grid-row: 1; -} - -.cv-sidebar-right { - grid-column: 2; - grid-row: 1; - text-align: right; -} - -/* Main content positioning */ -.page-1 .cv-main { - grid-column: 2; - grid-row: 1; -} - -.page-2 .cv-main { - grid-column: 1; - grid-row: 1; -} - -/* =============================================== - FOOTER STYLES - =============================================== */ - -.cv-footer { - background: #303030; - color: #ccc; - padding: 20px 0; - margin: 0; - grid-column: 1 / -1; /* Span all columns */ -} - -.footer-content { - list-style: none; - text-align: center; - margin: 0; - padding: 0; -} - -.footer-content li { - display: inline-block; - margin: 0; -} - -.footer-content li > div { - display: inline-block; - margin: 0 20px; - text-align: left; -} - -.footer-label { - width: 200px; - font-size: 1.7em; -} - -.footer-value { - width: 450px; - font-size: 1em; -} - -.footer-value b { - font-weight: normal; - font-size: 1.7em; -} - -.footer-separator { - position: relative; - left: -4%; - font-size: 0.6em; -} - -.footer-separator i { - opacity: 0.3; -} - -.cv-footer a { - color: inherit; -} - -.cv-footer a:hover { - color: #0275d8; - text-decoration: none; - font-weight: bold; -} - -/* =============================================== - PRINT STYLES - Handled by print.css - =============================================== */ -/* All print styles consolidated in /static/css/print.css */ - -/* =============================================== - SECTION STYLES FOR PAGE 2 - =============================================== */ - -.language-item, -.reference-item, -.other-content { - margin-bottom: 0!important; - line-height: 1.4!important; - margin-left: 2rem!important; - font-size: 0.95rem!important; -} - -/* Award item with logo */ -.award-item { - display: flex; - gap: 1.2rem; - align-items: flex-start; - margin-bottom: 2.5rem; - padding-bottom: 2rem; - border-bottom: 1px solid rgba(0, 0, 0, 0.1); - page-break-inside: avoid; - transition: gap 0.3s ease-in-out; -} - -/* Keep border on all award items including last one */ - -/* ======================================== - HIDE ICONS, ICONS, AND BADGES MODE - ======================================== */ - -/* Adjust gap when icons are hidden */ -.cv-paper:not(.show-icons) .award-item { - gap: 0; -} - -/* Hide all icons when .show-icons is not present */ -.cv-paper:not(.show-icons) .company-logo, -.cv-paper:not(.show-icons) .award-logo, -.cv-paper:not(.show-icons) .project-icon, -.cv-paper:not(.show-icons) .course-icon { - display: none !important; -} - -/* Hide icons inside responsibilities (Drolosoft sub-clients, Third Party projects) */ -.cv-paper:not(.show-icons) .responsibilities li img, -.cv-paper:not(.show-icons) .responsibilities li iconify-icon.default-company-icon { - display: none !important; -} - -/* Adjust layout for responsibilities without icons */ -.cv-paper:not(.show-icons) .responsibilities li:has(img), -.cv-paper:not(.show-icons) .responsibilities li:has(iconify-icon) { - display: block !important; - grid-template-columns: none !important; - padding-left: 1.2rem !important; -} - -/* Restore bullet points for responsibilities without icons */ -.cv-paper:not(.show-icons) .responsibilities li:has(img):before, -.cv-paper:not(.show-icons) .responsibilities li:has(iconify-icon):before { - display: block !important; -} - -/* Hide all section icons */ -.cv-paper:not(.show-icons) .section-icon { - display: none !important; -} - -/* Hide all badges (Current, Expired, Maintained By) */ -.cv-paper:not(.show-icons) .current-badge, -.cv-paper:not(.show-icons) .expired-badge, -.cv-paper:not(.show-icons) .maintained-badge { - display: none !important; -} - -/* Adjust experience items layout when icons are hidden */ -.cv-paper:not(.show-icons) .experience-item { - display: block !important; -} - -/* Adjust project and course items layout when icons are hidden */ -.cv-paper:not(.show-icons) .project-item, -.cv-paper:not(.show-icons) .course-item, -.cv-paper:not(.show-icons) .award-item { - display: block !important; - gap: 0 !important; -} - -.award-logo { - flex-shrink: 0; - display: block; -} - -.award-logo img { - width: 80px; - height: 80px; - object-fit: contain; - border-radius: 4px; - border: 1px solid #ddd; - background: white; - padding: 10px; -} - -.default-award-icon { - width: 80px; - height: 80px; - display: flex; - align-items: center; - justify-content: center; - border-radius: 4px; - border: 1px solid #ddd; - background: #f5f5f5; - color: #999; - padding: 10px; -} - -.award-content { - flex: 1; -} - -.award-item strong, -.course-item strong, -.language-item strong { - font-weight: 600; - color: var(--text-dark); -} - -/* Add checkmarks before language items */ -.language-item::before { - content: "✓"; - color: var(--text-dark); - font-weight: normal; - font-size: 0.85em; - margin-right: 0.4em; -} - -.award-item small, -.course-item small { - color: #666; - font-size: 0.875em; -} - -.award-desc, -.course-desc { - margin-top: 0.5em; - color: var(--text-gray); - font-size: 0.95rem; -} - -.reference-item { - margin-bottom: 0.4em; - line-height: 1.4; -} - -/* Add checkmarks before reference items */ -.reference-item::before { - content: "✓"; - color: var(--accent-blue); - font-weight: normal; - font-size: 0.85em; - margin-right: 0.4em; -} - -.reference-item a { - font-weight: 500; -} - -.ref-type { - color: #999; - margin-left: 0.5em; - font-size: 0.875em; -} - -/* Add checkmark before other content */ -.other-content::before { - content: "✓"; - color: var(--text-dark); - font-weight: normal; - font-size: 0.85em; - margin-right: 0.4em; -} - -/* =============================================== - MOBILE RESPONSIVE - TWO-PAGE LAYOUT - =============================================== */ - -@media (max-width: 900px) { - .cv-page { - margin: 0.5rem; - transform: scale(1); - border: none; - box-shadow: none; - } - - /* Stack layout on mobile using flexbox for proper flow */ - .page-1 .page-content, - .page-2 .page-content { - display: flex !important; - flex-direction: column; - gap: 0; - } - - .cv-sidebar-left, - .cv-sidebar-right { - width: 100% !important; - position: static !important; - grid-column: unset; - grid-row: unset; - padding: 0 !important; - } - - /* ========== Sidebar Accordion on Mobile ========== */ - .sidebar-accordion-header { - display: flex !important; - align-items: center; - gap: 0.5rem; - padding: 0.75rem 1rem; - background: var(--sidebar-gray); - cursor: pointer; - user-select: none; - border-bottom: 2px solid rgba(0, 0, 0, 0.1); - transition: background-color 0.2s ease; -text-align: center; - } - - .sidebar-accordion-header:hover { - background: #c5c5c5; - } - - .sidebar-accordion-header:active { - background: #b8b8b8; - } - - .sidebar-accordion-header iconify-icon { - flex-shrink: 0; - } - - .sidebar-accordion-header span { - font-weight: 700; - font-size: 1.3rem; - flex: 1; - } - - .sidebar-accordion-header .chevron { - transition: transform 0.3s ease; - } - - .sidebar-accordion-header.active .chevron { - transform: rotate(180deg); - } - - .sidebar-accordion-content { - max-height: 0; - overflow: hidden; - transition: max-height 0.3s ease-out; - padding: 0 1rem; - } - - .sidebar-accordion-content.active { - max-height: 5000px; - transition: max-height 0.5s ease-in; - padding: 1rem 1rem 0.5rem 1rem; - } - - /* Reduce font sizes inside accordion content */ - .sidebar-accordion-content .sidebar-title { - font-size: 1rem; - } - - .sidebar-accordion-content .sidebar-content, - .sidebar-accordion-content .skill-item { - font-size: 0.8rem; - } - - .page-1 .cv-main, - .page-2 .cv-main { - width: 100% !important; - position: static !important; - grid-column: unset; - grid-row: unset; - padding: 2rem 1.5rem !important; - } - - /* Adjust title badges header for mobile */ - .cv-title-badges-header { - padding: 0.75rem 1rem !important; - font-size: 0.85rem; - } - - .badge { - font-size: 0.75rem !important; - padding: 0.25rem 0.5rem !important; - } - - /* Hide header on page 2 for mobile to merge pages */ - .page-2 .cv-title-badges-header { - display: none; - } - - /* Adjust footer for mobile */ - .cv-footer { - padding: 1.5rem 1rem; - } - - .footer-content li { - display: block !important; - margin-bottom: 1.5rem; - } - - .footer-content li > div { - display: block; - margin: 0; - text-align: center; - width: 100%; - } - - .footer-label { - font-size: 0.9rem; - margin-top: 1rem; - color: #777; - } - - .footer-separator { - display: none; - } - - .footer-value { - font-size: 1.2rem; - margin-bottom: 0; - padding: 0; - } - - .footer-value b { - font-size: 1.3rem; - } - - .site-title { - justify-content: space-between; - width: 100%; - } - - /* Ensure proper stacking order */ - .cv-sidebar-left { - order: 1; - } - - .cv-title-badges-header { - order: 2; - } - - .cv-main { - order: 3; - } - - .cv-sidebar-right { - order: 4; - } - - .cv-footer { - order: 5; - } -} - -/* =============================================== - TABLET RESPONSIVE - =============================================== */ - -@media (max-width: 768px) { - /* Further reduce padding on smaller screens */ - .cv-page { - margin: 0.25rem; - } - - .cv-sidebar-left, - .cv-sidebar-right { - width: 100% !important; - padding: 1.5rem 1rem; - } - - /* Force left alignment for all sidebar content on mobile */ - .cv-sidebar-left .sidebar-content, - .cv-sidebar-left .skill-item { - text-align: left !important; - } - /* Force right alignment for all sidebar content on mobile */ - .cv-sidebar-right .sidebar-content, - .cv-sidebar-right .skill-item { - text-align: right !important; - } - .page-1 .cv-main, - .page-2 .cv-main { - width: 100% !important; - padding: 1.5rem 1rem !important; - } - - .cv-title-badges-header { - padding: 0.5rem 0.75rem !important; - font-size: 0.8rem; - } - - .badge { - font-size: 0.7rem !important; - padding: 0.2rem 0.4rem !important; - } - - /* Footer refinements */ - .cv-footer { - padding: 1rem 0.75rem; - } - - .footer-label { - font-size: 1.1rem; - margin-top: 0.75rem; - } - - .footer-value { - font-size: 0.85rem; - } - - .footer-value b { - font-size: 0.95rem; - } - - /* Sidebar title sizing */ - .sidebar-title { - font-size: 1.1rem; - } - - .sidebar-content { - font-size: 0.85rem; - } - - /* Section titles */ - .section-title { - font-size: 1.1rem; - margin-bottom: 1rem; - } -} - -/* Company link styling */ -.company-link { - color: var(--accent-blue); - font-weight: 500; - text-decoration: none; -} - -.company-link:hover { - text-decoration: underline; - color: #0052a3; -} - -/* =============================================== - HAMBURGER MENU & NAVIGATION - =============================================== */ - -/* Hamburger button */ -.hamburger-btn { - background: transparent; - border: none; - color: #fff; - cursor: pointer; - padding: 0.5rem; - display: flex; - align-items: center; - justify-content: center; - transition: background-color 0.2s ease; - border-radius: 4px; - margin: 0 0.5rem; - position: relative; /* For CSS-only hover trigger */ -} - - -.hamburger-btn:hover { - background-color: rgba(255, 255, 255, 0.1); -} - -.hamburger-btn:active { - background-color: rgba(255, 255, 255, 0.2); -} - -/* Navigation Menu */ -.navigation-menu { - position: fixed; - top: 50px; /* Height of action bar */ - left: 0; - width: 280px; - max-height: 0; - background: #ffffff; - box-shadow: 2px 0 10px rgba(0, 0, 0, 0.15); - transition: max-height 0.5s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease; - overflow-y: auto; - z-index: 1000; /* Above fixed buttons (z-index: 999) */ - pointer-events: none; /* Disable pointer events when hidden */ - opacity: 0; -} - -/* Pure CSS Menu Activation - Show menu when hovering hamburger OR menu */ -/* Show when hovering the hamburger button (adjacent in DOM after site-title-left) */ -.hamburger-btn:hover ~ .navigation-menu, -.hamburger-btn:focus ~ .navigation-menu, -/* Show when hovering the menu itself */ -.navigation-menu:hover, -/* Legacy class for backward compatibility */ -.navigation-menu.menu-hover, -.navigation-menu.menu-open { - max-height: calc(100vh - 60px); /* Viewport height minus header + some spacing */ - pointer-events: auto; /* Enable pointer events when visible */ - opacity: 1; -} - -.menu-content { - padding: 1rem 0; -} - -.menu-item { - display: flex; - align-items: center; - gap: 1rem; - padding: 0.875rem 1.5rem; - color: var(--text-dark); - text-decoration: none; - transition: background-color 0.2s ease, color 0.2s ease; - font-size: 0.95rem; - font-weight: 500; - border-left: 3px solid transparent; -} - -.menu-item:hover { - background-color: rgba(0, 102, 204, 0.08); - color: var(--accent-blue); - border-left-color: var(--accent-blue); - text-decoration: none; -} - -.menu-item iconify-icon { - color: var(--text-gray); - flex-shrink: 0; - transition: color 0.2s ease; -} - -.menu-item:hover iconify-icon { - color: var(--accent-blue); -} - -/* Menu item action controls (Expand All, Collapse All) */ -/* Removed centered text styling - action items now behave like regular menu items */ - -/* Remove extra padding - all menu items should align consistently */ - -/* Submenu styles - hover triggered, opens to the right */ -.menu-item-submenu { - position: relative; - border-bottom: 1px solid rgba(0, 0, 0, 0.1); - padding: 0 0 1rem 0; -} - -.menu-item.has-submenu { - justify-content: space-between; - position: relative; -} - -.submenu-arrow { - transition: transform 0.2s ease; - margin-left: auto; -} - -/* Rotate arrow slightly on hover */ -.menu-item-submenu:hover .submenu-arrow { - transform: translateX(3px); -} - -.submenu-content { - position: fixed; /* Changed from absolute to fixed to break out of parent overflow */ - left: 232px; /* Slight overlap with menu to eliminate any gap */ - background: #ffffff; - box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.15); - border-radius: 8px; - min-width: 250px; - max-width: 300px; - opacity: 0; - visibility: hidden; - transform: translateX(-3px); - transition: all 0.3s ease; - z-index: 1000; /* Higher z-index to appear above everything */ - padding: 0.5rem 0; - max-height: calc(100vh - 100px); /* Ensure it fits viewport */ - overflow-y: auto; /* Scroll if content is too long */ -} - -/* Show submenu when hovering the submenu container OR the submenu itself */ -.menu-item-submenu:hover .submenu-content, -.submenu-content:hover { - opacity: 1; - visibility: visible; - transform: translateX(0); -} - -/* Legacy class for JS compatibility */ -.menu-item-submenu.submenu-open .submenu-arrow { - transform: translateX(3px); -} - -.menu-item-submenu.submenu-open .submenu-content { - opacity: 1; - visibility: visible; - transform: translateX(0); -} - -.submenu-content .menu-item { - padding: 0.875rem 1.5rem; - font-size: 0.9rem; - border-left: 3px solid transparent; - border-radius: 0; -} - -.submenu-content .menu-item:first-child { - border-top-left-radius: 8px; - border-top-right-radius: 8px; -} - -.submenu-content .menu-item:last-child { - border-bottom-left-radius: 8px; - border-bottom-right-radius: 8px; -} - -/* ========== Menu Sections with Separators ========== */ -/* Quick Actions section - always visible */ -.menu-section-wrapper { - padding: 0.5rem 1.5rem 1rem; - border-bottom: 1px solid rgba(0, 0, 0, 0.1); -} - -/* Remove border from last visible section */ -.menu-content > *:last-child, -.menu-content > div:last-child { - border-bottom: none !important; -} - -/* ========== Menu Controls & Actions (Always Visible) ========== */ -/* Always visible in hamburger menu at all screen sizes */ -.menu-controls-section, -.menu-actions-section { - display: block; - padding: 0.5rem 1.5rem 1rem; - border-bottom: 1px solid rgba(0, 0, 0, 0.1); -} - -.menu-item-header { - display: flex; - align-items: center; - gap: 1rem; - padding: 0.875rem 0 0.875rem 0; - color: var(--text-dark); - font-size: 0.85rem; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.5px; - cursor: default; -} - -/* Disable hover effect for headers */ -.menu-item-header:hover { - background-color: transparent !important; - color: var(--text-dark) !important; - border-left-color: transparent !important; -} - -.menu-item-header iconify-icon { - color: var(--text-gray); - flex-shrink: 0; -} - -.menu-item-header:hover iconify-icon { - color: var(--text-gray) !important; -} - -.menu-item-header span { - flex: 1; -} - -.menu-control-item { - display: flex; - align-items: center; - justify-content: space-between; - padding: 0.75rem 0; -} - -.menu-control-label { - display: flex; - align-items: center; - gap: 0.75rem; - color: var(--text-dark); - font-size: 0.9rem; - font-weight: 500; -} - -.menu-control-label iconify-icon { - color: var(--text-gray); -} - -.menu-action-btn { - display: flex; - align-items: center; - justify-content: center; - gap: 1rem; - padding: 0.875rem 1rem; - margin: 0.25rem 0; - background: rgba(0, 0, 0, 0.03); - border: none; - border-radius: 8px; - color: var(--text-dark); - text-decoration: none; - font-size: 0.9rem; - font-weight: 500; - cursor: pointer; - transition: all 0.2s ease; - width: 100%; -} - -.menu-action-btn:hover { - background: rgba(0, 102, 204, 0.08); - color: var(--accent-blue); - text-decoration: none; -} - -.menu-action-btn iconify-icon { - color: var(--text-gray); - flex-shrink: 0; - transition: color 0.2s ease; -} - -.menu-action-btn:hover iconify-icon { - color: var(--accent-blue); -} - -/* PDF button in menu - White bg with red icon on hover */ -.menu-pdf-btn:hover, -.menu-pdf-btn.pdf-hover-sync { - background: white !important; - color: #e74c3c !important; -} - -.menu-pdf-btn:hover iconify-icon, -.menu-pdf-btn.pdf-hover-sync iconify-icon { - color: #e74c3c !important; -} - -/* Print button in menu - White bg with green icon on hover */ -.menu-print-btn:hover, -.menu-print-btn.print-hover-sync { - background: white !important; - color: #27ae60 !important; -} - -.menu-print-btn:hover iconify-icon, -.menu-print-btn.print-hover-sync iconify-icon { - color: #27ae60 !important; -} - -/* Section icons in titles */ -.section-icon { - vertical-align: middle; - margin-right: 0.5rem; - color: #7d7d7d; -} - -/* Add invisible separator (blank space) below section titles */ -#experience .section-title, -#awards .section-title, -#courses .section-title, -#projects .section-title { - margin-bottom: 40px !important; -} - -/* Smooth scrolling */ -html { - scroll-behavior: smooth; -} - -/* Add scroll padding to account for fixed header */ -html { - scroll-padding-top: 70px; /* Action bar height + some spacing */ -} - -/* Mobile responsive */ -@media (max-width: 768px) { - .navigation-menu { - width: 240px; - } - - .menu-item { - padding: 0.75rem 1rem; - font-size: 0.9rem; - } - - .site-title { - justify-content: space-between; - width: 100%; - } -} - -/* Hide menu overlay on print */ -@media print { - .navigation-menu { - display: none !important; - } - - .hamburger-btn { - display: none !important; - } -} - -/* ======================================== - Scroll Direction - Hide/Show Header - ======================================== */ - -/* Add smooth transition to header elements */ -.action-bar, -.navigation-menu { - transition: transform 0.3s ease-in-out; -} - -/* Hide header when scrolling down */ -.action-bar.header-hidden { - transform: translateY(-100%); -} - -.navigation-menu.header-hidden { - transform: translateY(-100%); -} - -/* ======================================== - Back to Top Button - ======================================== */ - -.back-to-top { - position: fixed; - bottom: 2rem; - right: 2rem; - width: 50px; - height: 50px; - background: var(--black-bar); - color: white; - border: none; - border-radius: 50%; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); - z-index: 99; - transition: all 0.3s ease; - opacity: 0.2; -} - -.back-to-top:hover { - opacity: 1; - transform: translateY(-3px); - box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); - background: #27ae60; -} - -.back-to-top.at-bottom { - opacity: 1; - background: #27ae60; -} - -.back-to-top:active { - transform: translateY(-1px); - box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3); -} - -/* Mobile adjustments */ -@media (max-width: 768px) { - .back-to-top { - bottom: 1.5rem; - right: 1.5rem; - width: 45px; - height: 45px; - } -} - -/* ======================================== - Info Button (Bottom Left) - ======================================== */ - -.info-button { - position: fixed; - bottom: 2rem; - left: 2rem; - width: 50px; - height: 50px; - background: var(--black-bar); - color: white; - border: none; - border-radius: 50%; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); - z-index: 99; - transition: all 0.3s ease; - opacity: 0.6; /* Increased from 0.2 for better discoverability */ -} - -.info-button:hover { - opacity: 1; - transform: translateY(-3px); - box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); - background: #27ae60; -} - -.info-button.at-bottom { - opacity: 1; - background: #27ae60; -} - -.info-button:active { - transform: translateY(-1px); - box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3); -} - -/* Mobile adjustments - Flexbox button layout at bottom center */ -@media (max-width: 900px) { - /* Hide only zoom control on mobile */ - .zoom-toggle-btn, - .zoom-control { - display: none !important; - } - - /* Reset fixed positioning for FLEXBOX buttons on mobile (exclude back-to-top) */ - .download-btn, - .print-friendly-btn, - .shortcuts-btn, - .info-button { - position: fixed !important; - bottom: 1.5rem !important; - left: auto !important; - right: auto !important; - width: 50px !important; - height: 50px !important; - opacity: 0.7 !important; - transform: none !important; - } - - /* Keep back-to-top button at bottom-right (same as desktop) */ - .back-to-top { - position: fixed !important; - bottom: 1.5rem !important; - right: 1.5rem !important; - width: 50px !important; - height: 50px !important; - } - - /* Flexbox container behavior - buttons arrange themselves */ - /* Buttons will be positioned using JavaScript or individual positioning */ - /* For now, use fixed spacing from center */ - - /* 5 buttons: Download, Print, Shortcuts, Theme, Info */ - /* Spacing: 10px gap between buttons, centered horizontally */ - /* Total width: 5 * 50px + 4 * 10px = 290px */ - /* Start position: 50% - 145px */ - - .download-btn { - left: calc(50% - 145px) !important; /* First button */ - } - - .print-friendly-btn { - left: calc(50% - 85px) !important; /* Second button */ - } - - .shortcuts-btn { - left: calc(50% - 25px) !important; /* Third button */ - } - - /* Theme switcher button - fourth position (defined in color-theme.css) */ - /* left: calc(50% + 35px) !important; */ - - .info-button { - left: calc(50% + 95px) !important; /* Fifth button (last) */ - } - - /* Hover effects - only Y transform + enhanced shadow */ - .download-btn:hover, - .download-btn.pdf-hover-sync, - .print-friendly-btn:hover, - .print-friendly-btn.print-hover-sync, - .shortcuts-btn:hover, - .info-button:hover, - .back-to-top:hover { - transform: translateY(-3px) !important; - opacity: 1 !important; - box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4) !important; - } - - /* Keep at-bottom state without transform */ - .info-button.at-bottom, - .shortcuts-btn.at-bottom { - opacity: 1 !important; - transform: none !important; - } -} - -/* Very narrow mobile - Move back-to-top UP on RIGHT side to avoid overlap */ -@media (max-width: 483px) { - .back-to-top { - /* Stay on RIGHT side, just move UP higher */ - right: 1.5rem !important; - bottom: 5.5rem !important; /* Higher position to clear bottom button row */ - } -} - -/* ======================================== - Info Modal - Modern Glassmorphism Design - ======================================== */ - -/* Native element - force centering */ -.info-modal { - border: none; - border-radius: 24px; - padding: 0; - max-width: 420px; - width: calc(100% - 2rem); - background: transparent; - /* Force centering - override any browser defaults */ - position: fixed; - inset: 0; - margin: auto; - /* Constrain height so margin:auto can center vertically */ - max-height: fit-content; -} - -/* Native ::backdrop pseudo-element replaces manual backdrop div */ -.info-modal::backdrop { - background: rgba(0, 0, 0, 0.7); - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); -} - -/* Dialog opening animation - native dialog uses [open] attribute */ -.info-modal[open] { - animation: modalFadeIn 0.3s ease; -} - -@keyframes modalFadeIn { - from { - opacity: 0; - transform: scale(0.9) translateY(20px); - } - to { - opacity: 1; - transform: scale(1) translateY(0); - } -} - -.info-modal-content { - background: linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.9) 100%); - backdrop-filter: blur(20px); - -webkit-backdrop-filter: blur(20px); - border-radius: 24px; - box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3), 0 0 100px rgba(39, 174, 96, 0.1); - width: 100%; - padding: 2.5rem; - position: relative; - border: 1px solid rgba(255, 255, 255, 0.8); -} - -.info-modal-close { - position: absolute; - top: 1rem; - right: 1rem; - background: rgba(0, 0, 0, 0.05); - border: none; - width: 40px; - height: 40px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - color: #333; - transition: all 0.2s ease; - z-index: 10; -} - -.info-modal-close:hover { - background: rgba(0, 0, 0, 0.1); - transform: rotate(90deg); -} - -.info-modal-header { - text-align: center; - margin-bottom: 2rem; -} - -.info-modal-header h2 { - font-size: 1.5rem; - font-weight: 600; - color: #333; - margin: 0 0 1.5rem 0; -} - -.info-modal-cv-title { - font-size: 1.5rem; - font-weight: 700; - color: #f39c12; /* Orange subtitle */ - margin-bottom: 0; - letter-spacing: 0.05em; - display: flex; - align-items: center; - gap: 0.5rem; - justify-content: center; -} - -#info-modal .info-modal-cv-title { - color: #27ae60; -} - -.info-modal-photo { - width: 40px; - height: 53px; - object-fit: cover; - border-radius: 4px; - border: none; - box-shadow: none; -} - -.photo-bracket-wrapper { - position: relative; - display: inline-flex; - align-items: center; - padding: 0 22px; -} - -.photo-bracket-wrapper::before { - content: '{'; - position: absolute; - left: 2px; - font-size: 2rem; - font-weight: 700; - color: #27ae60; - line-height: 1; - top: 8px; -} - -.photo-bracket-wrapper::after { - content: '}'; - position: absolute; - right: 2px; - font-size: 2rem; - font-weight: 700; - color: #27ae60; - line-height: 1; - top: 8px; -} - -.info-modal-body { - color: #333; -} - -.info-modal-description { - font-size: 1rem; - line-height: 1.6; - margin-bottom: 2rem; - color: #444; -} - -.info-modal-description strong { - color: #27ae60; - font-weight: 600; -} - -.info-modal-tech { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 1rem; - margin-bottom: 2rem; -} - -.info-tech-item { - display: flex; - align-items: center; - justify-content: center; - gap: 0.75rem; - padding: 0.75rem; - background: rgba(39, 174, 96, 0.05); - border-radius: 12px; - border: 1px solid rgba(39, 174, 96, 0.1); - transition: all 0.3s ease; -} - -.info-tech-item:hover { - background: rgba(39, 174, 96, 0.1); - transform: translateY(-2px); - box-shadow: 0 4px 12px rgba(39, 174, 96, 0.2); -} - -.info-tech-item iconify-icon { - color: #27ae60; - flex-shrink: 0; -} - -.info-tech-item span { - font-size: 0.9rem; - font-weight: 500; - color: #333; -} - -.info-modal-github { - display: flex; - align-items: center; - justify-content: center; - gap: 0.75rem; - padding: 1rem 1.5rem; - background: linear-gradient(135deg, #27ae60 0%, #229954 100%); - color: white; - text-decoration: none; - border-radius: 12px; - font-weight: 600; - font-size: 1rem; - transition: all 0.3s ease; - box-shadow: 0 4px 15px rgba(39, 174, 96, 0.3); -} - -.info-modal-github:hover { - transform: translateY(-2px); - box-shadow: 0 8px 25px rgba(39, 174, 96, 0.4); - background: linear-gradient(135deg, #229954 0%, #27ae60 100%); -} - -.info-modal-github:active { - transform: translateY(0); - box-shadow: 0 4px 15px rgba(39, 174, 96, 0.3); -} - -.info-modal-github-subtext { - text-align: center; - font-size: 0.9rem; - color: #666; - margin-top: 1.5rem; - margin-bottom: 1rem; - font-style: italic; -} - -/* Mobile responsive */ -@media (max-width: 768px) { - .info-modal-content { - padding: 2rem 1.5rem; - max-width: calc(100% - 2rem); - } - - .info-modal-header h2 { - font-size: 1.5rem; - } - - .info-modal-tech { - grid-template-columns: 1fr; - } - - .info-modal-description { - font-size: 0.95rem; - } -} - -/* ======================================== - Desktop: Ensure Sidebar Content Visible (>1280px) - ======================================== */ - -/* ======================================== - Responsive: Medium Screens (901px - 1023px) - ======================================== */ - -@media (min-width: 901px) and (max-width: 1023px) { - - /* ========== Global Font Size Reduction ========== */ - html { - font-size: 14px; /* Reduced from default 16px */ - } - - .cv-name { - font-size: 1.8em; /* Reduced from 2.2em */ - } - - .sidebar-title { - font-size: 0.95rem; - } - - .sidebar-content { - font-size: 0.9rem; - } - - /* ========== Selector Labels - Hide, Show on Hover ========== */ - .selector-label { - max-width: 0; - overflow: hidden; - opacity: 0; - transition: all 0.3s ease; - white-space: nowrap; - } - - .selector-group:hover .selector-label { - max-width: 200px; - opacity: 1; - margin-right: 0.75rem; - } - - /* ========== Language Selector - Collapse to EN/ES ========== */ - .language-selector .selector-btn { - position: relative; - padding: 0.4rem 1rem; /* Keep padding consistent */ - min-width: 50px; - font-size: 0; /* Hide actual text */ - overflow: visible; - transition: font-size 0.3s ease; /* Slower animation */ - display: inline-flex; - justify-content: center; - align-items: center; - } - - /* Show only short version (EN/ES) */ - .language-selector .selector-btn::before { - content: attr(data-short); - font-size: 1rem; /* Restore font size for pseudo-element */ - opacity: 1; - transition: opacity 0.3s ease; /* Slower animation */ - display: block; - width: 100%; - text-align: center; - } - - /* On hover of INDIVIDUAL button only, show full text */ - .language-selector .selector-btn:hover { - font-size: 1rem; /* Restore font size to show full text */ - min-width: auto; - } - - .language-selector .selector-btn:hover::before { - content: ''; /* Hide short version */ - opacity: 0; - } - - /* ========== Action Buttons - Icon Only, Expand on Hover ========== */ - .action-btn { - position: relative; - width: 45px; - overflow: hidden; - transition: width 0.3s ease, padding 0.3s ease; - white-space: nowrap; - text-indent: 0; - } - - /* Hide button text, keep icon */ - .action-btn iconify-icon { - flex-shrink: 0; - } - - .action-btn { - font-size: 0; - padding: 0 0.65rem; - justify-content: center; - } - - /* On hover, show text */ - .action-btn:hover { - width: auto; - font-size: 0.95rem; - padding: 0.65rem 1.5rem; - gap: 0.5rem; - } - - /* ========== Sidebar Content - Hide Text, Show on Hover ========== */ - .sidebar-content { - max-height: 0 !important; - overflow: hidden !important; - opacity: 0 !important; - } - - /* Show sidebar content on hover */ - .skill-category:hover .sidebar-content, - .cv-sidebar-section:hover .sidebar-content { - max-height: 1000px !important; - opacity: 1 !important; - margin-top: 10px !important; - } -} - -/* ======================================== - Responsive: Medium Screens (1024px - 1280px) - ======================================== */ - -@media (min-width: 1024px) and (max-width: 1280px) { - - /* ========== Global Font Size Reduction ========== */ - html { - font-size: 14px; /* Reduced from default 16px */ - } - - .cv-name { - font-size: 1.8em; /* Reduced from 2.2em */ - } - - .sidebar-title { - font-size: 0.95rem; - } - - .sidebar-content { - font-size: 0.9rem; - } - - /* ========== Selector Labels - Hide, Show on Hover ========== */ - .selector-label { - max-width: 0; - overflow: hidden; - opacity: 0; - transition: all 0.3s ease; - white-space: nowrap; - } - - .selector-group:hover .selector-label { - max-width: 200px; - opacity: 1; - margin-right: 0.75rem; - } - - /* ========== Language Selector - Collapse to EN/ES ========== */ - .language-selector .selector-btn { - position: relative; - padding: 0.4rem 1rem; /* Keep padding consistent */ - min-width: 50px; - font-size: 0; /* Hide actual text */ - overflow: visible; - transition: font-size 0.3s ease; /* Slower animation */ - display: inline-flex; - justify-content: center; - align-items: center; - } - - /* Show only short version (EN/ES) */ - .language-selector .selector-btn::before { - content: attr(data-short); - font-size: 1rem; /* Restore font size for pseudo-element */ - opacity: 1; - transition: opacity 0.3s ease; /* Slower animation */ - display: block; - width: 100%; - text-align: center; - } - - /* On hover of INDIVIDUAL button only, show full text */ - .language-selector .selector-btn:hover { - font-size: 1rem; /* Restore font size to show full text */ - min-width: auto; - } - - .language-selector .selector-btn:hover::before { - content: ''; /* Hide short version */ - opacity: 0; - } - - /* ========== Action Buttons - Icon Only, Expand on Hover ========== */ - .action-btn { - position: relative; - width: 45px; - overflow: hidden; - transition: width 0.3s ease, padding 0.3s ease; - white-space: nowrap; - text-indent: 0; - } - - /* Hide button text, keep icon */ - .action-btn iconify-icon { - flex-shrink: 0; - } - - .action-btn { - font-size: 0; - padding: 0 0.65rem; - justify-content: center; - } - - /* On hover, show text */ - .action-btn:hover { - width: auto; - font-size: 0.95rem; - padding: 0.65rem 1.5rem; - gap: 0.5rem; - } - - /* ========== Sidebar Content - Hide Text, Show on Hover ========== */ - .sidebar-content { - max-height: 0 !important; - overflow: hidden !important; - opacity: 0 !important; - } - - /* Show sidebar content on hover */ - .skill-category:hover .sidebar-content, - .cv-sidebar-section:hover .sidebar-content { - max-height: 1000px !important; - opacity: 1 !important; - margin-top: 10px !important; - } -} - -/* ======================================== - Responsive: Small Screens (up to 540px) - ======================================== */ - -/* ======================================== - Responsive: Tablet Screens - Center Photo (up to 768px) - ======================================== */ - -@media (max-width: 768px) { - /* ======================================== - TYPOGRAPHY - Subtle font size reductions - ======================================== */ - .cv-name { - text-align: center; - font-size: 1.6rem; - } - - .years-experience { - text-align: center; - font-size: 1.1em; - } - - .section-title { - font-size: 1.2em; - } - - .sidebar-title { - font-size: 1.2em; - } - - .experience-period, - .experience-separator, - .experience-location, - .experience-duration { - font-size: 0.95rem; - } - - .position { - font-size: 0.95rem; - } - - .short-desc, - .responsibilities li { - font-size: 0.85rem; - } - - /* ======================================== - TEXT ALIGNMENT FIXES - Selective alignment - ======================================== */ - /* Keep justified for intro and skills */ - .intro-text, - .summary-text { - text-align: justify; - font-size: 0.85rem; - line-height: 1.5; - } - - .intro-text { - margin-top: 0; - width: 100%; - } - - /* Left-align for course/project descriptions */ - .course-desc, - .project-desc { - text-align: left !important; - font-size: 0.85rem !important; - line-height: 1.5; - } - - /* ======================================== - HEADER LAYOUT - Centered photo - ======================================== */ - .cv-header-content { - flex-direction: column; - align-items: center; - gap: 1rem; - } - - .cv-header-left { - width: 100%; - position: static; - padding-right: 0; - } - - .cv-photo { - position: static; - width: auto; - height: auto; - max-width: 250px; - margin: 1.5rem auto; - text-align: center; - right: auto; - top: auto; - } - - .cv-photo img { - width: 100%; - height: auto; - max-height: none; - } - - /* ======================================== - UNIFIED LOGO/ICON SIZING - Consistent 60px - ======================================== */ - .company-logo, - .course-icon, - .project-icon, - .award-logo { - width: 60px !important; - height: 60px !important; - flex-shrink: 0; - } - - .company-logo img, - .course-icon img, - .project-icon img, - .award-logo img { - width: 60px !important; - height: 60px !important; - object-fit: contain; - } - - .default-company-icon, - .default-course-icon, - .default-project-icon, - .default-award-icon { - width: 60px !important; - height: 60px !important; - } - - /* ======================================== - CONSISTENT ITEM LAYOUT - Uniform spacing - ======================================== */ - .experience-item, - .course-item, - .project-item, - .award-item { - display: flex; - flex-direction: row; - gap: 1rem !important; - align-items: flex-start; - margin-bottom: 2rem !important; - padding-bottom: 1.5rem !important; - border-bottom: 1px solid rgba(0, 0, 0, 0.1); - } - - .experience-item { - margin-bottom: 1.8rem !important; - } - - .experience-content, - .course-content, - .project-content, - .award-content { - flex: 1; - min-width: 0; - } - - /* ======================================== - FONT SIZE CONSISTENCY - Titles and descriptions - ======================================== */ - .course-title, - .project-title, - .award-item strong { - font-size: 0.95rem !important; - line-height: 1.4; - } - - .course-item small, - .project-item small, - .award-item small { - font-size: 0.8rem !important; - } - - .course-desc, - .project-desc, - .award-desc { - font-size: 0.85rem !important; - line-height: 1.5; - } - - /* ======================================== - RESPONSIBILITIES MOBILE OPTIMIZATION - ======================================== */ - .responsibilities li:has(img), - .responsibilities li:has(iconify-icon) { - grid-template-columns: 60px 1fr !important; - gap: 0.75rem !important; - margin-bottom: 0.75rem !important; - } - - .responsibilities li img, - .responsibilities li iconify-icon.default-company-icon { - width: 60px !important; - height: 60px !important; - } - - /* ======================================== - SIDEBAR ITEMS MOBILE OPTIMIZATION - ======================================== */ - .language-item, - .reference-item, - .other-content { - margin-bottom: 0 !important; - line-height: 1.4 !important; - margin-left: 1rem !important; - font-size: 0.85rem !important; - } -} - -/* ======================================== - Responsive: All Mobile Screens (up to 540px) - ======================================== */ - -@media (max-width: 540px) { - /* Simplify action bar grid for mobile: single column */ - .action-bar-content { - grid-template-columns: 1fr; - gap: 0; - padding: 0; - } - - /* Hide center controls on mobile (moved to hamburger menu) */ - .view-controls-center { - display: none; - } - - /* Hide action buttons on small screens (available in hamburger menu) */ - .action-buttons-right { - display: none; - } - - /* Site title uses flexbox with percentage widths */ - .site-title { - display: flex; - justify-content: space-between; - align-items: center; - width: 100%; - padding: 0 0.5rem; - gap: 0.5rem; - } - - /* Left group (hamburger + title) takes ~50-60% */ - .site-title-left { - display: flex; - align-items: center; - gap: 0.5rem; - flex: 1 1 1; - min-width: 0; - } - - /* Title link is flexible within left group */ - .site-title-link { - flex: 1 1 auto; - min-width: 0; - overflow: hidden; - } - - .site-title-text { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } - - /* Language selector takes ~30-35% */ - .language-selector { - display: flex; - flex: 0 0 35%; - margin-left: auto; - padding-left: 0; - margin-right: 0; - justify-content: flex-end; - gap: 0.25rem; - } - - /* Hide year from title in mobile view */ - .site-title-year { - display: none; - } - - /* Hide desktop logo, show mobile icon in title */ - .site-logo-link { - display: none; - } - - .site-icon-mobile { - display: inline-flex; - } - - /* ========== Language Selector - Show Short Names Only ========== */ - .language-selector .selector-btn { - position: relative; - padding: 0.4rem 0.75rem; - min-width: 40px; - font-size: 0; /* Hide actual text */ - overflow: visible; - transition: font-size 0.3s ease; - display: inline-flex; - justify-content: center; - align-items: center; - } - - /* Show only short version (EN/ES) */ - .language-selector .selector-btn::before { - content: attr(data-short); - font-size: 0.95rem; - opacity: 1; - transition: opacity 0.3s ease; - display: block; - width: 100%; - text-align: center; - } - - /* Keep short names on hover (no expansion) */ - .language-selector .selector-btn:hover { - font-size: 0; - min-width: 40px; - } - - .language-selector .selector-btn:hover::before { - content: attr(data-short); - opacity: 1; - } -} - -/* ========================================================================== - ZOOM CONTROL - Fixed Bottom Center - ========================================================================== */ - -.zoom-control { - position: fixed; - bottom: 100px; /* Default position, can be dragged */ - left: 50%; - transform: translateX(-50%); - z-index: 900; - display: flex; - align-items: center; - gap: 0.75rem; - padding: 0.65rem 1.25rem; - background: rgba(128, 128, 128, 0.7); - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); - border-radius: 50px; - box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2); - transition: all 0.3s ease; - opacity: 0.7; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; - cursor: move; /* Indicate draggability */ - user-select: none; /* Prevent text selection while dragging */ -} - -/* Zoom control highlight when hovering zoom toggle button */ -.zoom-control.zoom-highlight { - opacity: 1; - box-shadow: 0px 0px 10px 4px rgb(1 113 188 / 80%); - background: rgb(91 91 91); -} - -/* Hidden state for zoom control and show button */ -.zoom-hidden { - display: none !important; -} - -/* Close button for zoom control */ -.zoom-close-btn { - position: absolute; - top: -8px; - right: -8px; - width: 24px; - height: 24px; - background: rgba(128, 128, 128, 0.6); /* Subtle grey */ - border: 2px solid rgba(255, 255, 255, 0.3); - border-radius: 50%; - color: rgba(255, 255, 255, 0.8); /* Light grey icon */ - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - padding: 0; - transition: all 0.2s ease; - z-index: 1; - opacity: 0.7; /* Subtle by default */ -} - -.zoom-close-btn:hover { - background: rgba(220, 53, 69, 0.9); /* Red on hover */ - color: white; /* White icon on hover */ - opacity: 1; /* Fully visible on hover */ - transform: scale(1.1); - box-shadow: 0 2px 8px rgba(220, 53, 69, 0.4); -} - -.zoom-control:hover { - opacity: 1; - background: rgb(91 91 91); - box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); -} - -/* Zoom Values (Labels) */ -.zoom-value { - color: rgba(255, 255, 255, 1); /* 100% white */ - font-size: 0.95rem; /* Bigger */ - font-weight: 500; /* Medium weight */ - min-width: 30px; - text-align: center; -} - -.zoom-value-current { - color: rgba(255, 255, 255, 1); /* 100% white */ - font-weight: 600; - font-size: 1.05rem; /* Bigger */ - min-width: 35px; -} - -/* Range Slider Styling */ -.zoom-slider { - -webkit-appearance: none; - appearance: none; - width: 180px; - height: 5px; - border-radius: 3px; - background: rgba(200, 200, 200, 0.5); - outline: none; - cursor: pointer; - transition: all 0.3s ease; -} - -/* Solid blue color on hover - no gradient */ -.zoom-control:hover .zoom-slider, -.zoom-slider:hover { - background: rgba(145, 190, 236, 1); /* solid blue */ -} - -.zoom-slider:focus { - outline: 2px solid rgba(255, 255, 255, 0.6); - outline-offset: 2px; -} - -/* Webkit Slider Thumb */ -.zoom-slider::-webkit-slider-thumb { - -webkit-appearance: none; - appearance: none; - width: 18px; - height: 18px; - border-radius: 50%; - background: white; - border: 2px solid rgba(180, 180, 180, 0.8); - cursor: pointer; - box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); - transition: all 0.2s ease; -} - -.zoom-slider::-webkit-slider-thumb:hover { - transform: scale(1.1); - border-color: rgba(200, 200, 200, 1); - box-shadow: 0 3px 8px rgba(0, 0, 0, 0.4); -} - -.zoom-slider::-webkit-slider-thumb:active { - transform: scale(1.05); -} - -/* Firefox Slider Thumb */ -.zoom-slider::-moz-range-thumb { - width: 18px; - height: 18px; - border-radius: 50%; - background: white; - border: 2px solid rgba(180, 180, 180, 0.8); - cursor: pointer; - box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); - transition: all 0.2s ease; -} - -.zoom-slider::-moz-range-thumb:hover { - transform: scale(1.1); - border-color: rgba(200, 200, 200, 1); - box-shadow: 0 3px 8px rgba(0, 0, 0, 0.4); -} - -.zoom-slider::-moz-range-thumb:active { - transform: scale(1.05); -} - -/* Firefox Range Track */ -.zoom-slider::-moz-range-track { - height: 5px; - border-radius: 3px; - background: rgba(200, 200, 200, 0.5); - transition: all 0.3s ease; -} - -/* Firefox Range Track - Solid blue on hover */ -.zoom-control:hover .zoom-slider::-moz-range-track, -.zoom-slider:hover::-moz-range-track { - background: #3b82f6; /* solid blue */ -} - -/* Reset Button - Circular with dynamic value inside */ -.zoom-reset-btn { - display: flex; - align-items: center; - justify-content: center; - min-width: 44px; - min-height: 44px; - padding: 0.5rem; - background: rgba(200, 200, 200, 0.2); - border: 2px solid rgba(220, 220, 220, 0.3); - border-radius: 50%; - color: rgba(255, 255, 255, 0.8); - font-size: 0.85rem; - font-weight: 700; - cursor: pointer; - transition: all 0.3s ease; - flex-shrink: 0; - margin: 0 -5px 0 10px; -} - -.zoom-reset-btn #zoom-value-current { - color: inherit; - font-size: inherit; - font-weight: inherit; - min-width: auto; -} - -.zoom-reset-btn:hover { - background: rgba(220, 220, 220, 0.4); - border-color: rgba(240, 240, 240, 0.6); - color: white; -} - -/* Green hover only when zoom is not at default (100) */ -.zoom-reset-btn.zoom-not-default:hover { - background: #74aacd; - border-color: #74aacd; - color: white; -} - -.zoom-reset-btn:active { - transform: scale(0.95); -} - -.zoom-reset-btn:focus { - outline: 2px solid rgba(255, 255, 255, 0.6); - outline-offset: 2px; -} - -/* Mobile Responsive - Horizontal button layout defined below (around line 2867) */ -/* Old mobile styles removed - now using horizontal layout with all three buttons */ - -/* Very Small Screens - Ultra Compact */ -@media (max-width: 480px) { - .zoom-control { - bottom: 40px; - padding: 0.35rem 0.7rem; - gap: 0.35rem; - } - - .zoom-slider { - width: 100px; - } - - /* Hide min/max labels on very small screens */ - .zoom-value-min, - .zoom-value-max { - display: none; - } -} - -/* ============================================================================= - HTMX CSS TRANSITIONS - ============================================================================= */ - -/* Inline loading transition styles moved to main section above (~line 1677) */ -/* Prevent layout shift during content fade */ -.cv-page-content-wrapper { - position: relative; -} - -/* ============================================================================= - KEYBOARD SHORTCUTS BUTTON & MODAL - ============================================================================= */ - -/* Shortcuts Button (Fixed Left) - Mirrors info-button on opposite side */ -/* Zoom Toggle Button (above shortcuts button) */ -.zoom-toggle-btn { - position: fixed; - bottom: 10rem; /* Above shortcuts button */ - left: 2rem; - width: 50px; - height: 50px; - background: var(--black-bar); - color: white; /* Match other buttons when inactive */ - border: none; - border-radius: 50%; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); - transition: all 0.3s ease; - z-index: 999; - opacity: 0.6; /* Match shortcuts button opacity */ -} - -.zoom-toggle-btn:hover { - opacity: 1; - transform: translateY(-3px); - box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); - background: #3498db; /* Blue hover */ -} - -.zoom-toggle-btn.at-bottom { - opacity: 1; - background: #3498db; /* Blue - matches hover */ -} - -/* No special styling for active state - button looks same whether zoom is on or off */ - -.shortcuts-btn { - position: fixed; - bottom: 6rem; /* Above back-to-top button (2rem + 50px + gap) */ - left: 2rem; /* LEFT SIDE instead of right */ - width: 50px; - height: 50px; - background: var(--black-bar); - color: white; - border: none; - border-radius: 50%; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); - z-index: 99; - transition: all 0.3s ease; - opacity: 0.6; /* Increased from 0.2 for better discoverability */ -} - -.shortcuts-btn:hover { - opacity: 1; - transform: translateY(-3px); - box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); - background: #f39c12; /* Orange hover */ -} - -.shortcuts-btn.at-bottom { - opacity: 1; - background: #f39c12; /* Orange when at bottom */ -} - -.shortcuts-btn:active { - transform: translateY(-1px); -} - -/* Print-Friendly Button (second from top) */ -.print-friendly-btn { - position: fixed; - bottom: 18rem; /* Below download button (22rem) */ - left: 2rem; - width: 50px; - height: 50px; - background: var(--black-bar); /* Dark background by default */ - color: white; /* White icon by default */ - border: none; - border-radius: 50%; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); - transition: all 0.3s ease; - z-index: 999; - opacity: 0.6; -} - -.print-friendly-btn iconify-icon { - color: white; /* White icon by default */ -} - -.print-friendly-btn:hover, -.print-friendly-btn.print-hover-sync { - opacity: 1; - transform: translateY(-3px); - box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); - background: white !important; /* White background on hover */ - color: #27ae60; /* Green icon on hover */ -} - -.print-friendly-btn:hover iconify-icon, -.print-friendly-btn.print-hover-sync iconify-icon { - color: #27ae60; /* Green icon on hover */ -} - -.print-friendly-btn.at-bottom { - opacity: 1; - background: white !important; /* White background - matches hover */ - color: #27ae60; /* Green - matches hover */ -} - -.print-friendly-btn.at-bottom iconify-icon { - color: #27ae60; /* Green icon when at bottom */ -} - -/* Download Button (TOP POSITION) */ -.download-btn { - position: fixed; - bottom: 22rem; /* Top button position */ - left: 2rem; - width: 50px; - height: 50px; - background: var(--black-bar); - color: white; - border: none; - border-radius: 50%; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); - transition: all 0.3s ease; - z-index: 999; - opacity: 0.6; -} - -.download-btn { - background: var(--black-bar); /* Gray by default like other buttons */ - opacity: 0.6; /* Match other buttons */ -} - -.download-btn:hover, -.download-btn.pdf-hover-sync { - opacity: 1; - transform: translateY(-3px); - box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); - background: #cd6060 !important; /* PDF red on hover */ -} - -.download-btn iconify-icon { - filter: brightness(0) invert(1); /* Always white */ - transition: filter 0.3s ease; -} - -.download-btn:hover iconify-icon { - filter: brightness(0) invert(1); /* Keep white on hover */ -} - -.download-btn.at-bottom { - opacity: 1; - background: #cd6060 !important; /* PDF red - matches hover */ -} - -/* Mobile adjustments */ -@media (max-width: 768px) { - .shortcuts-btn { - bottom: 5.5rem; /* Above back-to-top button (1.5rem + 45px + gap) */ - left: 1.5rem; /* LEFT SIDE on mobile too */ - width: 45px; - height: 45px; - } -} - -/* Shortcuts Modal - Very wide for 3-column grid, less tall */ -#shortcuts-modal { - max-width: 900px; /* Much wider - was 750px */ - max-height: 80vh; /* Limit height */ -} - -/* Keyboard icon with green curly brackets (matching info modal style) */ -.keyboard-icon-wrapper { - position: relative; - display: inline-flex; - align-items: center; - padding: 0 22px; -} - -.keyboard-icon-wrapper::before { - content: '{'; - position: absolute; - left: 2px; - font-size: 2rem; - font-weight: 700; - color: #575757ff; /* Dark brackets - matching info modal */ - line-height: 1; - top: -3px; -} - -.keyboard-icon-wrapper::after { - content: '}'; - position: absolute; - right: 2px; - font-size: 2rem; - font-weight: 700; - color: #575757ff; /* Dark brackets - matching info modal */ - line-height: 1; - top: -3px; -} - -.keyboard-icon-wrapper iconify-icon { - color: #f39c12; - position: relative; - top: 1px; -} - -/* Add margin-bottom to subtitle */ -#shortcuts-modal .info-modal-cv-title { - margin-bottom: 0.5rem; -} - -#shortcuts-modal .info-modal-body { - display: grid; - grid-template-columns: 1fr 1fr; /* 2 columns for 5 sections (3+2) */ - gap: 1.2rem 1.5rem; /* row gap, column gap */ - margin-top: 1.5rem; /* Increased spacing since no description */ -} - -/* Shortcuts Modal Content - Extends info-modal styles */ -.shortcuts-section { - margin-top: 0; /* Grid handles spacing */ - background: #f8f9fa; - border: 1px solid #e1e4e8; - border-radius: 8px; - padding: 1rem; - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); -} - -.shortcuts-section:first-of-type { - margin-top: 0; -} - -.shortcuts-section-title { - font-size: 1.05rem; - font-weight: 600; - color: #827a6e; /* Brownish-gray for section header text */ - margin-bottom: 0.75rem; - display: flex; - align-items: center; - gap: 0.5rem; - padding-bottom: 0.5rem; - border-bottom: 2px solid rgba(130, 122, 110, 0.2); /* Matching border */ -} - -.shortcuts-section-title iconify-icon { - color: #f39c12; /* ORANGE icons for section headers */ -} - -.shortcuts-list { - display: flex; - flex-direction: column; - gap: 0.5rem; -} - -.shortcut-item { - display: flex; - align-items: center; - justify-content: space-between; - gap: 1rem; - padding: 0.5rem 0; -} - -.shortcut-keys { - display: flex; - align-items: center; - gap: 0.4rem; - flex-wrap: wrap; -} - -.shortcut-keys kbd { - font-family: 'Monaco', 'Courier New', monospace; - font-size: 0.75rem; - font-weight: 600; - background: rgba(52, 152, 219, 0.08); /* Light blue background */ - border: 1px solid rgba(52, 152, 219, 0.35); /* Blue border */ - border-radius: 6px; - padding: 0.3rem 0.6rem; - box-shadow: 0 2px 4px rgba(52, 152, 219, 0.12), inset 0 -1px 0 rgba(52, 152, 219, 0.25); - white-space: nowrap; - text-align: center; - color: #3498db; /* Blue text */ - display: inline-flex; - align-items: center; - justify-content: center; - gap: 0.2rem; - transition: all 0.2s ease; - min-width: 2rem; -} - -/* Iconify icons inside kbd elements */ -.shortcut-keys kbd iconify-icon { - color: inherit; - vertical-align: middle; - display: inline-flex; -} - -.shortcut-item:hover .shortcut-keys kbd { - background: rgba(52, 152, 219, 0.15); - border-color: rgba(52, 152, 219, 0.5); - box-shadow: 0 2px 6px rgba(52, 152, 219, 0.25); -} - -.shortcut-desc { - flex: 1; - font-size: 0.95rem; - color: var(--text-gray); - line-height: 1.4; -} - -/* Mobile responsive */ -@media (max-width: 768px) { - #shortcuts-modal { - max-width: calc(100% - 2rem); - } - - #shortcuts-modal .info-modal-body { - grid-template-columns: 1fr; /* Single column on mobile */ - gap: 1.5rem; - } -} - -/* Tablet - 2 columns */ -@media (min-width: 769px) and (max-width: 1024px) { - #shortcuts-modal { - max-width: 700px; - } - - #shortcuts-modal .info-modal-body { - grid-template-columns: 1fr 1fr; /* 2 columns on tablet */ - gap: 1.2rem 1.5rem; - } - - .shortcuts-section-title { - font-size: 1rem; - } - - .shortcut-item { - flex-direction: column; - align-items: flex-start; - gap: 0.35rem; - } - - .shortcut-keys kbd { - font-size: 0.7rem; - padding: 0.2rem 0.4rem; - } - - .shortcut-desc { - font-size: 0.9rem; - } -} - -/* ======================================================================== - PDF DOWNLOAD MODAL STYLES - ======================================================================== */ - -/* PDF Modal Specific Overrides */ -.pdf-download-modal { - max-width: 900px; - width: calc(100% - 2rem); -} - -/* Modal Subtitle */ -.pdf-modal-subtitle { - font-size: 0.95rem; - color: var(--text-gray); - margin-top: 0.5rem; - font-weight: 400; -} - -/* PDF Options Grid */ -.pdf-options-grid { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 24px; - margin: 2rem 0 1.5rem 0; -} - -/* PDF Option Card */ -.pdf-option-card { - border: 2px solid transparent; - border-radius: 12px; - padding: 16px; - cursor: pointer; - transition: all 250ms ease; - position: relative; - background: #ffffff; - display: flex; - flex-direction: column; - gap: 12px; -} - -.pdf-option-card:hover { - border-color: #e0e0e0; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); - transform: translateY(-2px); -} - -.pdf-option-card:focus { - outline: 2px solid #4caf50; - outline-offset: 2px; -} - -/* Selected State */ -.pdf-option-card.selected { - border-color: #4caf50; - box-shadow: 0 6px 16px rgba(76, 175, 80, 0.2); - background: #f9fff9; -} - -/* PDF Thumbnail Container */ -.pdf-thumbnail { - background: #ffffff; - border: 1px solid #e0e0e0; - border-radius: 8px; - padding: 16px; - height: 280px; - display: flex; - flex-direction: column; - gap: 12px; - position: relative; - overflow: hidden; -} - -/* Skeleton Blocks inside Thumbnails */ -.pdf-thumbnail .skeleton-block { - background: linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 50%, #f0f0f0 75%); - background-size: 200% 100%; - animation: skeleton-shimmer 1.8s ease-in-out infinite; - border-radius: 4px; -} - -/* Custom Placeholder (for Custom CV card) */ -.custom-placeholder { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 100%; - color: #999; - text-align: center; -} - -.custom-placeholder iconify-icon { - margin-bottom: 12px; - opacity: 0.5; -} - -.custom-placeholder p { - font-size: 0.9rem; - font-weight: 500; - color: #666; - margin: 0; -} - -/* Thumbnail Badge (Page Count / Coming Soon) */ -.thumbnail-badge { - position: absolute; - top: 8px; - right: 8px; - background: rgba(0, 0, 0, 0.75); - color: white; - font-size: 0.7rem; - font-weight: 600; - padding: 4px 8px; - border-radius: 4px; - letter-spacing: 0.5px; - text-transform: uppercase; -} - -/* PDF Option Info */ -.pdf-option-info { - text-align: center; -} - -.pdf-option-info h3 { - font-size: 1.1rem; - font-weight: 600; - color: var(--text-dark); - margin: 0 0 4px 0; -} - -.pdf-option-info p { - font-size: 0.875rem; - color: var(--text-gray); - margin: 0; - line-height: 1.4; -} - -/* PDF Option Badge (Checkmark) */ -.pdf-option-badge { - position: absolute; - top: 8px; - left: 8px; - opacity: 0; - transform: scale(0.8); - transition: all 250ms ease; - color: #4caf50; -} - -.pdf-option-card.selected .pdf-option-badge { - opacity: 1; - transform: scale(1); -} - -/* PDF Modal Footer */ -.pdf-modal-footer { - display: flex; - justify-content: center; - padding-top: 1rem; - border-top: 1px solid #e0e0e0; - margin-top: 0.5rem; -} - -/* PDF Download Button */ -.pdf-download-btn { - display: inline-flex; - align-items: center; - gap: 8px; - padding: 12px 32px; - font-size: 1rem; - font-weight: 600; - border: none; - border-radius: 8px; - cursor: pointer; - transition: all 250ms ease; - font-family: inherit; -} - -.pdf-download-btn iconify-icon { - flex-shrink: 0; -} - -/* Disabled State */ -.pdf-download-btn:disabled { - background: #e0e0e0; - color: #999999; - cursor: not-allowed; - opacity: 0.6; -} - -/* Enabled State */ -.pdf-download-btn:not(:disabled) { - background: #4caf50; - color: white; -} - -.pdf-download-btn:not(:disabled):hover { - background: #45a049; - box-shadow: 0 4px 12px rgba(76, 175, 80, 0.3); - transform: translateY(-1px); -} - -.pdf-download-btn:not(:disabled):active { - transform: translateY(0); -} - -/* Screen Reader Only */ -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; -} - -/* ======================================================================== - RESPONSIVE DESIGN - PDF MODAL - ======================================================================== */ - -/* Tablet: Two columns */ -@media (min-width: 480px) and (max-width: 767px) { - .pdf-options-grid { - grid-template-columns: repeat(2, 1fr); - gap: 16px; - } - - /* Custom card spans full width */ - .pdf-option-card[data-cv-format="custom"] { - grid-column: 1 / -1; - } - - .pdf-thumbnail { - height: 220px; - } -} - -/* Mobile: Single column */ -@media (max-width: 479px) { - .pdf-download-modal { - max-width: calc(100% - 1rem); - } - - .pdf-options-grid { - display: flex; - flex-direction: column; - gap: 16px; - } - - .pdf-thumbnail { - height: 200px; - } - - .pdf-option-info h3 { - font-size: 1rem; - } - - .pdf-option-info p { - font-size: 0.8rem; - } - - .pdf-download-btn { - padding: 10px 24px; - font-size: 0.9rem; - } -} - -/* ======================================================================== - ACCESSIBILITY - REDUCED MOTION - ======================================================================== */ - -@media (prefers-reduced-motion: reduce) { - .pdf-thumbnail .skeleton-block { - animation: none; - background: #e8e8e8; - } - - .pdf-option-card { - transition: none; - } - - .pdf-option-badge { - transition: none; - } - - .pdf-download-btn { - transition: none; - } -} - -/* ======================================================================== - PRINT STYLES - PDF MODAL - ======================================================================== */ - -@media print { - .pdf-download-modal { - display: none !important; - } -} + MAIN.CSS - Entry Point (New Modular Structure) + ============================================================================ */ + +/* 01 - Foundation */ +@import './01-foundation/_reset.css'; +@import './01-foundation/_variables.css'; +@import './01-foundation/_typography.css'; +@import './01-foundation/_themes.css'; + +/* 02 - Layout */ +@import './02-layout/_container.css'; +@import './02-layout/_page.css'; +@import './02-layout/_grid.css'; +@import './02-layout/_paper.css'; + +/* 03 - Components */ +@import './03-components/_action-bar.css'; +@import './03-components/_sidebar.css'; +@import './03-components/_cv-header.css'; +@import './03-components/_cv-section.css'; +@import './03-components/_experience.css'; +@import './03-components/_projects.css'; +@import './03-components/_courses.css'; +@import './03-components/_education.css'; +@import './03-components/_languages.css'; + +/* 04 - Interactive (includes hamburger, buttons, modals, zoom - TO BE SPLIT LATER) */ +@import './04-interactive/_toggles.css'; +@import './04-interactive/_remaining.css'; + +/* 06 - Effects */ +@import './06-effects/_skeleton.css'; + +/* 08 - Contexts */ +@import './08-contexts/_print.css'; diff --git a/static/css/main.css.backup b/static/css/main.css.backup new file mode 100644 index 0000000..1c9aba9 --- /dev/null +++ b/static/css/main.css.backup @@ -0,0 +1,4711 @@ +/* CV Design - Original Style Recreation */ + +/* Import Fonts */ +@import url('https://fonts.googleapis.com/css2?family=Quicksand:wght@400;500;600;700&family=Source+Sans+Pro:wght@400;600&family=Inter:wght@400;500;600;700&display=swap'); + +:root { + --bg-gray: rgb(82, 86, 89); + --sidebar-gray: #d1d4d2; + --black-bar: #2b2b2b; + --paper-white: #ffffff; + --text-dark: rgb(0, 0, 0); + --text-gray: rgb(51, 51, 51); + --accent-blue: #0066cc; + --border-gray: #dddddd; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Quicksand', 'Source Sans Pro', -apple-system, system-ui, sans-serif; + background-color: var(--page-bg); + background-image: + linear-gradient(90deg, rgba(0, 0, 0, 0.05) 1px, transparent 1px), + linear-gradient(180deg, rgba(0, 0, 0, 0.05) 1px, transparent 1px), + linear-gradient(90deg, rgba(0, 0, 0, 0.02) 1px, transparent 1px), + linear-gradient(180deg, rgba(0, 0, 0, 0.02) 1px, transparent 1px); + background-size: 50px 50px, 50px 50px, 10px 10px, 10px 10px; + background-attachment: fixed; + color: var(--text-secondary); + line-height: 1.5; + font-size: 16px; + font-weight: 400; + overflow-x: auto; /* Allow horizontal scroll when zoomed */ +} + +a { + color: var(--accent-blue); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +/* Single Black Top Bar */ +.action-bar { + background: var(--action-bar-bg); + color: var(--action-bar-text); + position: sticky; + top: 0; + z-index: 100; + box-shadow: var(--shadow-md); + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; +} + +.action-bar-content { + max-width: 100%; + margin: 0 auto; + padding: 0; + display: grid; + grid-template-columns: 1fr auto 1fr; + align-items: stretch; + gap: 2rem; + height: 50px; +} + +/* Left: Site Title */ +.site-title { + display: flex; + align-items: center; + gap: 0.75rem; + justify-self: start; + white-space: nowrap; + padding: 0; + height: 100%; +} + +.site-title-left { + display: flex; + align-items: center; + gap: 0.75rem; +} + +.site-icon { + color: #fff; + flex-shrink: 0; + display: inline-flex; + align-items: center; + justify-content: center; + height: 36px; + padding: 0 .5rem 0 1.5rem; +} + +/* Mobile icon hidden by default, shown only on mobile */ +.site-icon-mobile { + display: none; + color: #fff; + flex-shrink: 0; + margin-right: 0.5rem; +} + +/* Site logo and title links */ +.site-logo-link, +.site-title-link { + text-decoration: none; + color: inherit; + display: flex; + align-items: center; + height: 36px; + transition: opacity 0.2s ease; +} + +.site-logo-link:hover, +.site-title-link:hover { + opacity: 0.8; + text-decoration: none; +} + +.site-logo-link { + padding: 0; +} + +/* Ensure Iconify icons display properly */ +.iconify, +iconify-icon { + display: inline-block; + vertical-align: middle; +} + +.site-title-text { + font-size: 1.05rem; + font-weight: 500; + color: #fff; + letter-spacing: -0.01em; + line-height: 1; + display: flex; + align-items: center; + height: 36px; + padding: 0 1rem 0 0rem; +} + +/* Center: View controls with labels */ +.view-controls-center { + display: flex; + flex-direction: row; + align-items: center; + gap: 2.5rem; + justify-self: center; + flex-shrink: 0; + white-space: nowrap; + height: 100%; +} + +.selector-group { + display: flex; + align-items: center; + gap: 0.75rem; +} + +.selector-label { + font-size: 0.875rem; + color: rgba(255,255,255,0.85); + font-weight: 500; + white-space: nowrap; + letter-spacing: -0.01em; + line-height: 1; + display: flex; + align-items: center; + height: 36px; +} + +.selector-label span { + color: #27ae60; + font-weight: 600; +} + +.language-toggle, +.cv-length-toggle, +.logo-toggle { + flex-shrink: 0; +} + +/* Right: Action buttons */ +.action-buttons { + justify-self: end; + flex-shrink: 0; +} + +.htmx-indicator { + flex-shrink: 0; +} + +.lang-btn { + padding: 0.4rem 1rem; + border: 1px solid rgba(255,255,255,0.3); + background: transparent; + color: white; + border-radius: 3px; + cursor: pointer; + font-size: 1rem; + font-weight: 400; + text-transform: capitalize; + transition: all 0.2s ease; +} + +.lang-btn:hover { + background: rgba(255,255,255,0.1); + border-color: rgba(255,255,255,0.5); +} + +.lang-btn.active { + background: #27ae60 !important; + border-color: #27ae60 !important; + font-weight: 500; +} + +/* Icon Toggle Switches */ +.icon-toggle { + position: relative; + display: flex; + cursor: pointer; +} + +.icon-toggle input[type="checkbox"] { + position: absolute; + opacity: 0; + width: 0; + height: 0; +} + +.icon-toggle-slider { + position: relative; + display: inline-flex; + align-items: center; + justify-content: space-between; + width: 75px; + height: 30px; + background: #e0e0e0; + border: 2px solid #d0d0d0; + border-radius: 15px; + padding: 0 6px; + transition: all 0.3s ease; +} + +.icon-toggle-slider::before { + content: ''; + position: absolute; + width: 24px; + height: 24px; + left: 2px; + background: white; + border-radius: 50%; + transition: transform 0.3s ease; + box-shadow: 0 2px 4px rgba(0,0,0,0.3); + z-index: 2; + pointer-events: none; +} + +.icon-toggle input:checked + .icon-toggle-slider::before { + transform: translateX(43px); +} + +.icon-toggle input:checked + .icon-toggle-slider { + background: #27ae60; + border-color: #229954; +} + +.icon-toggle-slider .icon-left, +.icon-toggle-slider .icon-right { + position: absolute; + z-index: 3; + transition: all 0.3s ease; + flex-shrink: 0; + pointer-events: none; +} + +.icon-toggle-slider .icon-left { + left: 6px; +} + +.icon-toggle-slider .icon-right { + right: 6px; +} + +.icon-toggle input:not(:checked) + .icon-toggle-slider .icon-left { + color: #333 !important; + font-weight: bold; +} + +.icon-toggle input:not(:checked) + .icon-toggle-slider .icon-right { + color: #999 !important; + opacity: 0.5; +} + +.icon-toggle input:checked + .icon-toggle-slider .icon-left { + color: rgba(255,255,255,0.4) !important; + opacity: 0.5; +} + +.icon-toggle input:checked + .icon-toggle-slider .icon-right { + color: white !important; + font-weight: bold; +} + +.icon-toggle input:focus + .icon-toggle-slider { + box-shadow: 0 0 0 3px rgba(39, 174, 96, 0.2); +} + +/* Language selector wrapper - contains indicators outside swap target */ +.language-selector-wrapper { + position: relative; + display: inline-flex; + height: 100%; + /* Ensure wrapper doesn't create extra spacing */ + width: fit-content; +} + +/* Language selector - matching action button style */ +.language-selector { + display: inline-flex; + gap: 0; + padding: 0; + padding-left: 1rem; /* Space after the title */ + margin-right: 0; + background: transparent; + border-radius: 0; + height: 100%; + align-items: stretch; +} + +/* Position language indicators next to their respective buttons */ +#lang-indicator-en, +#lang-indicator-es { + position: absolute; + top: 50%; + transform: translateY(-50%); + pointer-events: none; + z-index: 10; +} + +/* Position indicators inside the button visual area */ +#lang-indicator-en { + left: calc(1rem + 50px); /* Inside first button */ +} + +#lang-indicator-es { + left: calc(1rem + 135px); /* Inside second button */ +} + +.selector-btn { + padding: 0 1.5rem; + background: transparent; + color: white; + border: none; + border-radius: 0; + cursor: pointer; + font-size: 1rem; + font-weight: 500; + display: inline-flex; + align-items: center; + justify-content: center; + /* gap: 0.5rem; */ + gap: 0rem; + text-decoration: none; + white-space: nowrap; + letter-spacing: -0.01em; + height: 100%; + line-height: 1; + transition: all 0.2s ease; + outline: none !important; + box-shadow: none !important; + min-width: 50px!important; +} + +.selector-btn:focus, +.selector-btn:focus-visible, +.selector-btn:active { + outline: none !important; + box-shadow: none !important; +} + +.selector-btn:hover { + background: #666; +} + +.selector-btn:hover iconify-icon { + color: #27ae60; +} + +.selector-btn.active { + background: #27ae60; + color: white; +} + +.selector-btn:not(.active) { + background: transparent; + color: white; +} + +/* Language selector buttons - no global animations (applied in responsive range only) */ + +/* Action buttons - transparent with white text */ +.action-btn { + padding: 0 1.5rem; + background: transparent; + color: white; + border: none; + border-radius: 0; + cursor: pointer; + font-size: 1rem; + font-weight: 500; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + text-decoration: none; + white-space: nowrap; + letter-spacing: -0.01em; + height: 100%; + line-height: 1; + transition: background-color 0.3s ease, color 0.3s ease; /* Smooth color transitions */ +} + +.action-btn iconify-icon { + color: white; + transition: color 0.3s ease; /* Smooth icon color transition */ +} + +.action-btn:hover { + background: #ddd; + color: #333; + text-decoration: none; +} + +.action-btn:hover iconify-icon { + color: #27ae60; +} + +/* PDF Download button - gray by default, red on hover */ +.pdf-btn { + background: transparent !important; /* Transparent like other buttons */ + color: white !important; +} + +.pdf-btn:hover, +.pdf-btn.pdf-hover-sync { + background: #cd6060 !important; /* PDF red on hover */ + color: white !important; +} + +.pdf-btn iconify-icon { + color: white !important; + filter: brightness(0) invert(1); /* Always white */ + transition: filter 0.3s ease; +} + +.pdf-btn:hover iconify-icon { + color: white !important; + filter: brightness(0) invert(1); /* Keep white on hover */ +} + +/* Print Friendly button - white bg with green icon on hover */ +.print-btn { + background: transparent !important; + color: white !important; +} + +.print-btn:hover, +.print-btn.print-hover-sync { + background: white !important; /* White background on hover */ + color: #27ae60 !important; /* Green icon on hover */ +} + +.print-btn iconify-icon { + color: white; /* White icon by default */ +} + +.print-btn:hover iconify-icon, +.print-btn.print-hover-sync iconify-icon { + color: #27ae60; /* Green icon on hover */ +} + +/* CV Length Toggle - Center of action bar */ +.cv-length-toggle { + display: flex; + gap: 0.5rem; + justify-self: center; +} + +.length-btn { + padding: 0.4rem 1rem; + border: 1px solid rgba(255,255,255,0.4); + background: rgba(255,255,255,0.1); + color: white; + border-radius: 4px; + cursor: pointer; + font-size: 0.9rem; + font-weight: 500; + transition: all 0.2s ease; +} + +.length-btn:hover { + background: rgba(255,255,255,0.2); + border-color: rgba(255,255,255,0.6); +} + +.length-btn.active { + background: white; + color: #1a1a1a; + border-color: white; + font-weight: 600; +} + +/* Action buttons styling (already positioned by grid) */ +.action-buttons, +.action-buttons-right { + display: flex; + gap: 0; + align-items: stretch; + height: 100%; +} + +.action-buttons-right { + justify-self: end; + margin-left: auto; +} + +/* ============================================================================ + HTMX Loading Indicators + ========================================================================= */ + +/* Base indicator styles - hidden by default with opacity for smooth transitions */ +.htmx-indicator { + opacity: 0; /* Hidden by default */ + transition: opacity 200ms ease-in-out; + pointer-events: none; + display: inline-flex; + align-items: center; + justify-content: center; + position: absolute; /* Remove from layout flow to prevent spacing issues */ +} + +/* Override for when request is active - must come AFTER base rule */ +.htmx-indicator.htmx-request, +#lang-indicator-en.htmx-request, +#lang-indicator-es.htmx-request { + opacity: 1 !important; /* Force visible state */ +} + +/* Ensure iconify-icon indicators override global iconify-icon display style */ +iconify-icon.htmx-indicator { + display: inline-flex; + align-items: center; + justify-content: center; +} + +/* Show indicators during HTMX requests */ +/* Using span wrapper, so target span.htmx-request specifically */ +span.htmx-request.htmx-indicator, +.htmx-request .htmx-indicator, +.htmx-request.htmx-indicator { + opacity: 1 !important; +} + +/* Spinning animation for loading icons */ +.htmx-indicator.spinning { + animation: htmx-spin 1s linear infinite; +} + +@keyframes htmx-spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} + +/* Indicator size variants */ +.htmx-indicator.small { + width: 14px; + height: 14px; + font-size: 14px; +} + +.htmx-indicator.medium { + width: 18px; + height: 18px; + font-size: 18px; +} + +.htmx-indicator.large { + width: 24px; + height: 24px; + font-size: 24px; +} + +/* Positioning variants */ +.htmx-indicator.inline { + display: inline-flex; + margin-left: 8px; + vertical-align: middle; +} + +.htmx-indicator.inline-start { + display: inline-flex; + margin-right: 8px; + vertical-align: middle; +} + +/* Color variants for different contexts */ +.htmx-indicator.light { + color: rgba(255, 255, 255, 0.9); +} + +.htmx-indicator.dark { + color: rgba(0, 0, 0, 0.7); +} + +.htmx-indicator.accent { + color: #27ae60; +} + +/* Respect reduced motion preference */ +@media (prefers-reduced-motion: reduce) { + .htmx-indicator.spinning { + animation: none; + } + .htmx-indicator { + transition: none; + } +} + +/* Legacy loader class for backward compatibility */ +.loader { + border: 2px solid #f3f3f3; + border-top: 2px solid white; + border-radius: 50%; + width: 20px; + height: 20px; + animation: htmx-spin 1s linear infinite; +} + +/* ============================================================================ + Inline Loading States for HTMX Transitions + ========================================================================= */ + +/* Inline loading states - no blocking overlay, smooth transitions only */ +/* Language selector buttons already have htmx-indicator spinners */ +/* CV content areas show subtle fade during swap */ + +/* Zoom Wrapper - wraps cv-container for zoom functionality */ +.zoom-wrapper { + /* CSS zoom property changes actual layout space (not just visual) */ + /* This allows footer to naturally position right after zoomed content */ +} + +/* Main CV Container */ +.cv-container { + width: 100%; + max-width: 100%; /* Full width to accommodate pages */ + margin: 0 auto; + padding: 20px 0 0 0; /* Top padding to prevent sticky action bar overlap */ + display: block; /* Changed from flex */ +} + +/* Clean theme - no sidebars, centered content */ +.cv-container.theme-clean { + padding: 20px 0 0 0; + transition: all 0.3s ease-in-out; +} + +.theme-clean .cv-page { + box-shadow: var(--shadow-lg); + border: 1px solid var(--border-color); + margin: 0 auto; + max-width: 900px; + transition: all 0.3s ease-in-out; +} + +/* Animate sidebar, header, footer when hiding/showing */ +.cv-sidebar, +.cv-title-badges-header, +.cv-footer { + overflow: hidden; + transition: all 0.3s ease-in-out; +} + +.theme-clean .cv-sidebar, +.theme-clean .cv-title-badges-header, +.theme-clean .cv-footer { + display: none !important; + animation: fadeOutShrink 0.3s ease-in-out; +} + +.theme-clean .page-content { + grid-template-columns: 1fr !important; + transition: grid-template-columns 0.3s ease-in-out; +} + +.theme-clean .cv-main { + grid-column: 1 !important; + padding: 2rem 3rem!important; + transition: all 0.3s ease-in-out; +} + +/* CV Paper - Container for two-page layout */ +.cv-paper { + width: 100%; + background: transparent; /* Remove white background - each page has its own */ + box-shadow: none; /* Remove shadow - each page has its own */ + margin: 0; + position: relative; + display: block; /* Changed from grid to block for stacking pages */ + min-height: auto; /* Changed from 100vh */ + + /* Zoom transform properties */ + transform-origin: top center; /* Scale from top center - page stays anchored at top */ + transition: transform 0.08s linear; /* Smooth, immediate zoom response */ + will-change: transform; /* Hint browser to optimize for transforms */ +} + +/* Page break helpers */ +.page-break { + page-break-after: always; + break-after: page; +} + +.avoid-break { + page-break-inside: avoid; + break-inside: avoid; +} + +/* Sidebar - Left column */ +.cv-sidebar { + background: var(--sidebar-gray); + padding: 4rem 1.5rem; + font-size: 0.9rem; +} + +/* Sidebar Accordion - Hidden on desktop, visible on mobile */ +.sidebar-accordion-header { + display: none; +} + +.sidebar-accordion-content { + /* Always visible on desktop */ +} + +.sidebar-section { + margin-bottom: 2rem; +} + +/* Add margin when sidebar section is collapsed */ +.sidebar-section:has(details:not([open])) { + margin-bottom: 3rem; + margin-top: 0rem; +} + +.sidebar-title { + font-family: 'Quicksand', sans-serif; + font-size: 1.4em; + font-weight: 700; + line-height: 1.3em; + margin-bottom: 10px; + padding: 0; + color: rgb(51, 51, 51); + text-align: left; +} + +/* Collapsible Sidebar Section Styles */ +.sidebar-section details { + margin: 0; +} + +.sidebar-section details summary ~ * { + overflow: hidden; + max-height: 0; + opacity: 0; + transform: translateY(-8px); + transition: max-height 0.5s ease-in-out, + opacity 0.3s ease-in-out, + transform 0.3s ease-in-out; +} + +.sidebar-section details[open] summary ~ * { + max-height: 1500px; + opacity: 1; + transform: translateY(0); +} + +.sidebar-section summary { + cursor: pointer; + list-style: none; + user-select: none; + position: relative; + display: flex; + align-items: center; + justify-content: space-between; +} + +/* Remove default triangle marker */ +.sidebar-section summary::-webkit-details-marker, +.sidebar-section summary::marker { + display: none; +} + +/* Sidebar title - no special positioning */ +.sidebar-section summary .sidebar-title { + margin-bottom: 0; +} + +/* Add custom collapse indicator at the far right (left sidebar) */ +.cv-sidebar-left .sidebar-section summary::after { + content: '▶'; + font-size: 0.8em; + color: rgb(100, 100, 100); + transition: transform 0.2s ease, opacity 0.2s ease; + opacity: 0; + margin-left: 15px; + flex-shrink: 0; +} + +/* Add custom collapse indicator at the far left (right sidebar) */ +.cv-sidebar-right .sidebar-section summary { + flex-direction: row-reverse; + justify-content: space-between; +} + +.cv-sidebar-right .sidebar-section summary .sidebar-title { + text-align: right; + width: 100%; +} + +/* Left-align content in left sidebar */ +.cv-sidebar-left .sidebar-content { + text-align: left; +} + +.cv-sidebar-left .skill-item { + text-align: left; +} + +/* Right-align content in right sidebar */ +.cv-sidebar-right .sidebar-content { + text-align: right; +} + +.cv-sidebar-right .skill-item { + text-align: right; +} + +.cv-sidebar-right .sidebar-section summary::after { + content: '▶'; + font-size: 0.8em; + color: rgb(100, 100, 100); + transition: transform 0.2s ease, opacity 0.2s ease; + opacity: 0; + margin-right: 15px; + flex-shrink: 0; +} + +/* Show indicator on hover or when closed */ +.sidebar-section summary:hover::after, +.sidebar-section details:not([open]) summary::after { + opacity: 1; +} + +/* Rotate indicator when open */ +.sidebar-section details[open] summary::after { + transform: rotate(90deg); +} + +/* Hover effect on sidebar summary */ +.sidebar-section summary:hover .sidebar-title { + color: var(--accent-blue); +} + +.sidebar-content { + font-family: 'Quicksand', sans-serif; + font-size: 0.95rem; + font-weight: 400; + line-height: 1.5; +} + +/* Add breathing space when sidebar section is open */ +.sidebar-section details[open] .sidebar-content { + margin-top: 0.5rem; +} + +.skill-item { + margin-bottom: 0.15rem; + color: rgb(0, 0, 0); + font-weight: 400; +} + +/* Main Content - Right column */ +.cv-main { + background: var(--paper-white); + padding: 3rem 2.5rem 8rem 2.5rem; /* Bottom padding for footer and zoom control clearance */ +} + +/* Professional Title Badges - Spans Both Columns */ +.cv-title-badges-header { + grid-column: 1 / -1; /* Span all columns */ + background: #303030 !important; /* Elegant dark gray */ + padding: 10px 20px; + display: flex; + flex-wrap: wrap; + justify-content: center; + align-items: center; + gap: 0; + border-bottom: 2px solid #34495e; +} + +.title-badge { + font-size: 0.9em; + font-weight: normal; + color: #ccc; + text-transform: uppercase; + white-space: nowrap; +} + +.badge-separator { + color: #ccc; + font-weight: normal; + padding: 0 15px; + position: relative; + top: -1px; +} + +/* Header with photo and name */ +.cv-header { + margin-bottom: 2rem; +} + +.cv-header-content { + display: flex; + justify-content: space-between; + align-items: flex-start; + gap: 2rem; +} + +.cv-header-left { + flex: 1; + position: relative; + /* Desktop: Add right padding to make room for the photo */ + padding-right: 185px; /* Photo width (150px) + gap (35px) */ +} + +.cv-photo { + width: 150px; + height: 200px; + flex-shrink: 0; + overflow: hidden; + border: 3px solid white; + box-shadow: 0 2px 8px rgba(0,0,0,0.15); + + /* Desktop: Position photo in the right padding area */ + position: absolute; + top: 15px; + right: 15px; /* Margin from the right edge */ +} + +.cv-photo img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.cv-name { + font-family: 'Quicksand', sans-serif; + font-size: 2.2em; + font-weight: 400; + {{/* font-style: italic; */}} + line-height: 1.1; + margin-bottom: 8px; + color: rgb(0, 0, 0); + text-align: right; +} + +.cv-experience-years { + font-family: 'Quicksand', sans-serif; + font-size: 0.9em; + font-weight: 500; + line-height: 1.5; + color: rgb(0, 0, 0); + margin: 0; +} + +.years-experience { + font-family: 'Quicksand', sans-serif; + font-size: 1.25em; + font-weight: 400; + color: #666; + margin: 4px 0 0 0; + line-height: 1.4; + text-align: right; +} + +/* Intro/Excerpt Text - Positioned inside header, matching old React CV */ +.intro-text { + font-family: 'Quicksand', sans-serif; + font-size: 1.0em; + line-height: 1.6; + color: rgb(51, 51, 51); + margin-top: 20px; + text-align: justify; + font-style: italic; +} + +/* Sections */ +.cv-section { + margin-bottom: 3rem; + page-break-inside: avoid; +} + +/* Remove margin when section is collapsed */ +.cv-section:has(details:not([open])) { + margin-bottom: 0; +} + +.section-title { + font-family: 'Quicksand', sans-serif; + font-size: 1.4em; + font-weight: 500; + line-height: 1.2em; + margin: 20px 0 25px 0; + padding: 0; + color: rgb(51, 51, 51); +} + +/* Collapsible Section Styles */ +.cv-section details { + margin: 0; +} + +.cv-section details summary ~ * { + overflow: hidden; + max-height: 0; + opacity: 0; + transform: translateY(-8px); + transition: max-height 0.5s ease-in-out, + opacity 0.3s ease-in-out, + transform 0.3s ease-in-out; +} + +.cv-section details[open] summary ~ * { + max-height: 3000px; + opacity: 1; + transform: translateY(0); +} + +.cv-section summary { + cursor: pointer; + list-style: none; + user-select: none; + position: relative; +} + +/* Remove default triangle marker in all browsers */ +.cv-section summary::-webkit-details-marker, +.cv-section summary::marker { + display: none; +} + +/* Add custom collapse indicator after the title */ +.cv-section summary .section-title { + display: inline-flex; + align-items: center; + gap: 0.5rem; +} + +.cv-section summary .section-title::after { + content: '▼'; + font-size: 0.8em; + color: rgb(100, 100, 100); + transition: transform 0.2s ease, opacity 0.2s ease; + opacity: 0; + margin-left: 0.5rem; +} + +/* Show indicator on hover or when closed */ +.cv-section summary:hover .section-title::after, +.cv-section details:not([open]) summary .section-title::after { + opacity: 1; +} + +/* Rotate indicator when closed */ +.cv-section details:not([open]) summary .section-title::after { + transform: rotate(-90deg); +} + +/* Hover effect on summary */ +.cv-section summary:hover .section-title { + color: var(--accent-blue); +} + +.summary-text { + font-family: 'Quicksand', sans-serif; + line-height: 1.5; + text-align: justify; + font-size: 0.9em; + font-weight: 400; + color: rgb(0, 0, 0); +} + +/* Experience */ +/* Experience item layout moved to logo-toggle.css */ + +.experience-header { + margin-bottom: 0.6rem; +} + +.experience-title-line { + margin-bottom: 0.3em; +} + +.position { + font-size: 1rem; + font-weight: 500; + margin: 0; + color: var(--text-dark); + margin-bottom: 4px; +} + +.position .position-title { + display: inline-block; + margin-right: 0.3em; +} + +.position .company-name { + display: inline-block; +} + +.current-badge { + display: inline-block; + background: #27ae60; + color: white; + font-weight: 700; + font-size: 0.7em; + padding: 0.2em 0.5em; + border-radius: 3px; + margin-left: 0.5em; + vertical-align: middle; + letter-spacing: 0.5px; +} + +.live-badge { + display: inline-flex; + align-items: center; + gap: 0.3em; + background: #27ae60; + color: white; + font-weight: 700; + font-size: 0.7em; + padding: 0.2em 0.5em; + border-radius: 3px; + margin-left: 0.5em; + vertical-align: middle; + letter-spacing: 0.5px; +} + +.live-badge iconify-icon { + font-size: 1.2em; +} + +.expired-badge { + display: inline-block; + background: #e74c3c; + color: white; + font-weight: 700; + font-size: 0.7em; + padding: 0.2em 0.5em; + border-radius: 3px; + margin-left: 0.5em; + vertical-align: middle; + letter-spacing: 0.5px; +} + +.maintained-badge { + display: inline-block; + background: #3498db; + color: white; + font-weight: 700; + font-size: 0.7em; + padding: 0.2em 0.5em; + border-radius: 3px; + margin-left: 0.5em; + vertical-align: middle; + letter-spacing: 0.5px; +} + +.experience-period, +.experience-separator, +.experience-location, +.experience-duration { + color: #555; + font-weight: 600; + display: inline-block; + font-size: 1.05rem; +} + +.experience-duration { + font-style: italic; +} + +.short-desc { + color: var(--text-dark); + font-size: 0.95rem; + line-height: 1.6; + margin-top: 0.5rem; +} + +.duration-text { + color: #aaa; + font-weight: 500; +} + +.responsibilities { + list-style: none; + margin-top: 1rem; + padding-left: 0; +} + +.responsibilities li { + padding-left: 1.2rem; + margin-bottom: 0.4rem; + position: relative; + font-size: 0.95rem; + color: var(--text-dark); + line-height: 1.5; +} + +.responsibilities li:before { + content: "•"; + position: absolute; + left: 0; + color: var(--text-gray); +} + +/* Responsibilities with company icons (similar to main experience layout) */ +.responsibilities li:has(img), +.responsibilities li:has(iconify-icon) { + display: grid; + grid-template-columns: 60px 1fr; + gap: 1rem; + padding-left: 0; + margin-bottom: 1rem; + align-items: start; +} + +.responsibilities li:has(img):before, +.responsibilities li:has(iconify-icon):before { + display: none; +} + +.responsibilities li img { + width: 60px; + height: 60px; + object-fit: contain; + border-radius: 4px; + border: 1px solid #ddd; + background: #f5f5f5; + padding: 4px; +} + +.responsibilities li iconify-icon.default-company-icon { + width: 60px; + height: 60px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + border: 1px solid #ddd; + background: #f5f5f5; + color: #999; + padding: 8px; +} + +/* Education */ +.education-item { + margin-bottom: 1rem; + font-size: 0.95rem; + line-height: 1.6; + color: var(--text-dark); +} + + +/* Languages */ +.languages-list { + display: flex; + flex-wrap: wrap; + gap: 1.5rem; +} + +.language-item { + font-size: 0.95rem!important; + color: var(--text-dark); + margin-bottom: 0.3rem!important; + line-height: 1.4!important; + margin-left: 2rem!important; +} + +.language-item small { + display: block; + font-size: 0.8em; + margin-top: 0.2rem; + font-style: italic; +} + +/* Experience Items */ +.experience-item { + margin-bottom: 2.5rem; + padding-bottom: 2rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} + +/* Keep border on all experience items including last one */ + +/* Courses */ +.course-item { + display: flex; + gap: 1.2rem; + align-items: flex-start; + margin-bottom: 2.5rem; + padding-bottom: 2rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} + +/* Keep border on all course items including last one */ + +.course-icon { + flex-shrink: 0; + width: 80px; + height: 80px; + display: flex; + align-items: center; + justify-content: center; +} + +.course-icon img { + width: 80px; + height: 80px; + object-fit: contain; + border-radius: 4px; + border: 1px solid #ddd; + background: #f5f5f5; + padding: 4px; +} + +.default-course-icon { + width: 80px; + height: 80px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + border: 1px solid #ddd; + background: #f5f5f5; + color: #999; + padding: 10px; +} + +.course-content { + flex: 1; +} + +.course-header { + margin-bottom: 0.5rem; +} + +.course-title { + font-size: 1em; + font-weight: 600; + margin: 0 0 0.3rem 0; + line-height: 1.4; + color: var(--text-dark); +} + +.course-title-text { + display: inline; +} + +.course-institution { + display: inline; + margin-left: 0.5em; + font-weight: normal; +} + +.course-period, +.course-separator, +.course-location, +.course-duration { + color: #555; + font-size: 0.9em; +} + +.course-separator { + color: #999; +} + +.course-desc { + font-size: 0.85em; + color: var(--text-gray); + margin-top: 0.4rem; + line-height: 1.4; + text-align: justify; +} + +/* Projects */ +.project-item { + display: flex; + gap: 1.2rem; + align-items: flex-start; + margin-bottom: 2.5rem; + padding-bottom: 2rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} + +.project-icon { + flex-shrink: 0; + width: 80px; + height: 80px; + display: flex; + align-items: center; + justify-content: center; +} + +.project-icon img { + width: 80px; + height: 80px; + object-fit: contain; + border-radius: 4px; + border: 1px solid #ddd; + background: #f5f5f5; + padding: 4px; +} + +.default-project-icon { + width: 80px; + height: 80px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + border: 1px solid #ddd; + background: #f5f5f5; + color: #999; + padding: 10px; +} + +.project-content { + flex: 1; +} + +.project-header { + margin-bottom: 0.5rem; +} + +.project-title { + font-size: 1em; + font-weight: 600; + margin: 0 0 0.3rem 0; + line-height: 1.4; + color: var(--text-dark); +} + +.project-title-text { + display: inline; +} + +.project-title-text a { + color: var(--accent-blue); + text-decoration: none; +} + +.project-title-text a:hover { + text-decoration: underline; +} + +.project-period, +.project-separator, +.project-location { + color: #555; + font-size: 0.9em; + font-weight: 600; +} + +.project-separator { + color: #999; +} + +.project-desc { + font-size: 0.95rem; + color: var(--text-dark); + margin-top: 0.5rem; + line-height: 1.6; + text-align: justify; +} + +.project-technologies { + font-size: 0.85em; + color: var(--text-gray); + margin-top: 0.5rem; + line-height: 1.4; +} + +.projects-footer { + margin-top: -1.5rem; + padding-top: 0rem; + text-align: center; + font-size: 0.95rem; + color: var(--text-gray); +} + +.projects-footer p { + margin: 0; +} + +.projects-footer a { + color: var(--accent-blue); + text-decoration: none; +} + +.projects-footer a:hover { + text-decoration: underline; +} + +/* References */ +.reference-item { + margin-bottom: 0!important; + line-height: 1.4!important; + margin-left: 2rem!important; + font-size: 0.95rem!important; +} + +.reference-item a { + + color: var(--accent-blue); + text-decoration: none; + word-break: break-word; +} + +.reference-item a:hover { + text-decoration: underline; +} + +.ref-type { + display: block; + font-size: 0.8em; + color: var(--text-gray); + font-style: italic; + margin-top: 0.2rem; +} + +/* Footer */ +footer { + text-align: center; + padding: 2rem; + color: rgba(255,255,255,0.7); + font-size: 0.85rem; +} + +/* GitHub repository link styling */ +.github-repo-link { + color: whitesmoke !important; + transition: color 0.2s ease-in-out; +} + +.github-repo-link:hover { + color: #66B3FF !important; +} + + +/* CV Version Toggle Animations */ +@keyframes fadeInGrow { + from { + opacity: 0; + max-height: 0; + transform: scaleY(0.8); + transform-origin: top; + } + to { + opacity: 1; + max-height: 5000px; + transform: scaleY(1); + } +} + +@keyframes fadeOutShrink { + from { + opacity: 1; + max-height: 5000px; + transform: scaleY(1); + } + to { + opacity: 0; + max-height: 0; + transform: scaleY(0.8); + transform-origin: top; + } +} + +/* Elements that appear/disappear */ +.long-only, +.short-desc { + overflow: hidden; + transition: all 0.3s ease-in-out; +} + +/* Short CV - Hide detailed content with animation */ +.cv-short .long-only { + display: none; + animation: fadeOutShrink 0.3s ease-in-out; +} + +.cv-short .short-desc { + display: block; + animation: fadeInGrow 0.3s ease-in-out; +} + +/* Long CV - Hide short descriptions with animation */ +.cv-long .short-desc, +.short-desc { + display: none; + animation: fadeOutShrink 0.3s ease-in-out; +} + +.cv-long .long-only { + display: block; + animation: fadeInGrow 0.3s ease-in-out; +} + +.cv-long .responsibilities { + display: block; + animation: fadeInGrow 0.3s ease-in-out; +} + +/* Responsive - tablet/mobile */ +@media (max-width: 900px) { + .cv-paper { + grid-template-columns: 1fr; + box-shadow: none; + } + + .cv-sidebar { + padding: 1.5rem 1rem; + } + + .cv-main { + padding: 1.5rem 1rem; + } + + .cv-name { + font-size: 1.8rem; + } + + .intro-text { + font-size: 0.9em; + margin-top: 15px; + } + + .action-bar-content { + grid-template-columns: 1fr; + gap: 1rem; + padding: 0rem; + } + + .language-toggle, + .cv-length-toggle, + .action-buttons { + justify-self: center !important; + justify-content: center; + width: 100%; + } + + .experience-title-line { + flex-direction: column; + align-items: flex-start; + gap: 0.25rem; + } + + /* ========== Hide header controls, show in menu ========== */ + /* Keep language selector visible in header */ + .view-controls-center { + display: none !important; + } + + .action-buttons-right { + display: none !important; + } + + /* Show controls and actions in hamburger menu */ + .menu-controls-section, + .menu-actions-section { + display: block !important; + } +} + +.no-print {} + +/* Smooth Transitions for HTMX Swaps */ +.cv-paper { + transition: opacity 200ms ease-in-out; +} + +/* Inline loading states for CV content during language transitions */ +.cv-page-content-wrapper.htmx-swapping { + opacity: 0.5; + transform: scale(0.99); + pointer-events: none; + filter: blur(1px); +} + +.cv-page-content-wrapper.htmx-settling { + opacity: 1; + transform: scale(1); + pointer-events: auto; + filter: blur(0); +} + +/* Respect reduced motion preference */ +@media (prefers-reduced-motion: reduce) { + .cv-page-content-wrapper.htmx-swapping { + transform: none; + filter: none; + opacity: 0.7; + } +} + +/* Focus Styles for Accessibility */ +button:focus, +a:focus { + outline: 2px solid var(--accent-blue); + outline-offset: 2px; +} + +/* Loading indicator animation */ +@keyframes spin { + to { transform: rotate(360deg); } +} + +/* Error Toast */ +.error-toast { + position: fixed; + bottom: 2rem; + right: 2rem; + background: #fee2e2; + color: #dc2626; + padding: 1rem 1.5rem; + border-radius: 8px; + border-left: 4px solid #dc2626; + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + display: none; /* Hidden by default */ + align-items: center; + gap: 1rem; + max-width: 400px; + z-index: 1000; + font-size: 0.95rem; +} + +/* Show toast with full animation cycle: slide in -> stay -> fade out */ +.error-toast.show { + display: flex; + animation: toastLifecycle 5.5s ease-out forwards; +} + +/* Full lifecycle animation: slide in (0-0.3s), stay (0.3-5s), fade out (5-5.5s) */ +@keyframes toastLifecycle { + 0% { + transform: translateX(120%); + opacity: 0; + } + 5.5% { /* 0.3s / 5.5s = 5.5% */ + transform: translateX(0); + opacity: 1; + } + 90.9% { /* 5s / 5.5s = 90.9% - stay visible */ + transform: translateX(0); + opacity: 1; + } + 100% { /* Final 0.5s - fade out and slide right */ + transform: translateX(120%); + opacity: 0; + } +} + +.error-icon { + font-size: 1.25rem; + flex-shrink: 0; +} + +.error-toast button.error-close { + background: none; + border: none; + font-size: 1.5rem; + color: #dc2626; + cursor: pointer; + padding: 0; + width: 24px; + height: 24px; + display: flex; + align-items: center; + justify-content: center; + transition: opacity 0.2s; + flex-shrink: 0; + line-height: 1; +} + +.error-toast button.error-close:hover { + opacity: 0.7; +} + +.error-toast button.error-close:focus { + outline: 2px solid #dc2626; + outline-offset: 2px; +} + +/* Mobile responsive error toast */ +@media (max-width: 768px) { + .error-toast { + left: 1rem; + right: 1rem; + bottom: 1rem; + max-width: none; + } +} + +/* =============================================== + TWO-PAGE LAYOUT STYLES + =============================================== */ + +/* Page Container - Each CV page */ +.cv-page { + background: var(--paper-bg); + max-width: 1200px; + margin: 2rem auto; + box-shadow: var(--shadow-lg); + border: 1px solid var(--border-color); + transform: scale(0.95); + transform-origin: top center; + transition: transform 0.3s ease; +} + +/* Page Content Grid */ +.page-content { + display: grid; +} + +/* Page 1: Left sidebar + Main content */ +.page-1 .page-content { + grid-template-columns: 300px 1fr; +} + +/* Page 2: Main content + Right sidebar */ +.page-2 .page-content { + grid-template-columns: 1fr 300px; +} + +/* Sidebar positioning */ +.cv-sidebar-left { + grid-column: 1; + grid-row: 1; +} + +.cv-sidebar-right { + grid-column: 2; + grid-row: 1; + text-align: right; +} + +/* Main content positioning */ +.page-1 .cv-main { + grid-column: 2; + grid-row: 1; +} + +.page-2 .cv-main { + grid-column: 1; + grid-row: 1; +} + +/* =============================================== + FOOTER STYLES + =============================================== */ + +.cv-footer { + background: #303030; + color: #ccc; + padding: 20px 0; + margin: 0; + grid-column: 1 / -1; /* Span all columns */ +} + +.footer-content { + list-style: none; + text-align: center; + margin: 0; + padding: 0; +} + +.footer-content li { + display: inline-block; + margin: 0; +} + +.footer-content li > div { + display: inline-block; + margin: 0 20px; + text-align: left; +} + +.footer-label { + width: 200px; + font-size: 1.7em; +} + +.footer-value { + width: 450px; + font-size: 1em; +} + +.footer-value b { + font-weight: normal; + font-size: 1.7em; +} + +.footer-separator { + position: relative; + left: -4%; + font-size: 0.6em; +} + +.footer-separator i { + opacity: 0.3; +} + +.cv-footer a { + color: inherit; +} + +.cv-footer a:hover { + color: #0275d8; + text-decoration: none; + font-weight: bold; +} + +/* =============================================== + PRINT STYLES - Handled by print.css + =============================================== */ +/* All print styles consolidated in /static/css/print.css */ + +/* =============================================== + SECTION STYLES FOR PAGE 2 + =============================================== */ + +.language-item, +.reference-item, +.other-content { + margin-bottom: 0!important; + line-height: 1.4!important; + margin-left: 2rem!important; + font-size: 0.95rem!important; +} + +/* Award item with logo */ +.award-item { + display: flex; + gap: 1.2rem; + align-items: flex-start; + margin-bottom: 2.5rem; + padding-bottom: 2rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + page-break-inside: avoid; + transition: gap 0.3s ease-in-out; +} + +/* Keep border on all award items including last one */ + +/* ======================================== + HIDE ICONS, ICONS, AND BADGES MODE + ======================================== */ + +/* Adjust gap when icons are hidden */ +.cv-paper:not(.show-icons) .award-item { + gap: 0; +} + +/* Hide all icons when .show-icons is not present */ +.cv-paper:not(.show-icons) .company-logo, +.cv-paper:not(.show-icons) .award-logo, +.cv-paper:not(.show-icons) .project-icon, +.cv-paper:not(.show-icons) .course-icon { + display: none !important; +} + +/* Hide icons inside responsibilities (Drolosoft sub-clients, Third Party projects) */ +.cv-paper:not(.show-icons) .responsibilities li img, +.cv-paper:not(.show-icons) .responsibilities li iconify-icon.default-company-icon { + display: none !important; +} + +/* Adjust layout for responsibilities without icons */ +.cv-paper:not(.show-icons) .responsibilities li:has(img), +.cv-paper:not(.show-icons) .responsibilities li:has(iconify-icon) { + display: block !important; + grid-template-columns: none !important; + padding-left: 1.2rem !important; +} + +/* Restore bullet points for responsibilities without icons */ +.cv-paper:not(.show-icons) .responsibilities li:has(img):before, +.cv-paper:not(.show-icons) .responsibilities li:has(iconify-icon):before { + display: block !important; +} + +/* Hide all section icons */ +.cv-paper:not(.show-icons) .section-icon { + display: none !important; +} + +/* Hide all badges (Current, Expired, Maintained By) */ +.cv-paper:not(.show-icons) .current-badge, +.cv-paper:not(.show-icons) .expired-badge, +.cv-paper:not(.show-icons) .maintained-badge { + display: none !important; +} + +/* Adjust experience items layout when icons are hidden */ +.cv-paper:not(.show-icons) .experience-item { + display: block !important; +} + +/* Adjust project and course items layout when icons are hidden */ +.cv-paper:not(.show-icons) .project-item, +.cv-paper:not(.show-icons) .course-item, +.cv-paper:not(.show-icons) .award-item { + display: block !important; + gap: 0 !important; +} + +.award-logo { + flex-shrink: 0; + display: block; +} + +.award-logo img { + width: 80px; + height: 80px; + object-fit: contain; + border-radius: 4px; + border: 1px solid #ddd; + background: white; + padding: 10px; +} + +.default-award-icon { + width: 80px; + height: 80px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + border: 1px solid #ddd; + background: #f5f5f5; + color: #999; + padding: 10px; +} + +.award-content { + flex: 1; +} + +.award-item strong, +.course-item strong, +.language-item strong { + font-weight: 600; + color: var(--text-dark); +} + +/* Add checkmarks before language items */ +.language-item::before { + content: "✓"; + color: var(--text-dark); + font-weight: normal; + font-size: 0.85em; + margin-right: 0.4em; +} + +.award-item small, +.course-item small { + color: #666; + font-size: 0.875em; +} + +.award-desc, +.course-desc { + margin-top: 0.5em; + color: var(--text-gray); + font-size: 0.95rem; +} + +.reference-item { + margin-bottom: 0.4em; + line-height: 1.4; +} + +/* Add checkmarks before reference items */ +.reference-item::before { + content: "✓"; + color: var(--accent-blue); + font-weight: normal; + font-size: 0.85em; + margin-right: 0.4em; +} + +.reference-item a { + font-weight: 500; +} + +.ref-type { + color: #999; + margin-left: 0.5em; + font-size: 0.875em; +} + +/* Add checkmark before other content */ +.other-content::before { + content: "✓"; + color: var(--text-dark); + font-weight: normal; + font-size: 0.85em; + margin-right: 0.4em; +} + +/* =============================================== + MOBILE RESPONSIVE - TWO-PAGE LAYOUT + =============================================== */ + +@media (max-width: 900px) { + .cv-page { + margin: 0.5rem; + transform: scale(1); + border: none; + box-shadow: none; + } + + /* Stack layout on mobile using flexbox for proper flow */ + .page-1 .page-content, + .page-2 .page-content { + display: flex !important; + flex-direction: column; + gap: 0; + } + + .cv-sidebar-left, + .cv-sidebar-right { + width: 100% !important; + position: static !important; + grid-column: unset; + grid-row: unset; + padding: 0 !important; + } + + /* ========== Sidebar Accordion on Mobile ========== */ + .sidebar-accordion-header { + display: flex !important; + align-items: center; + gap: 0.5rem; + padding: 0.75rem 1rem; + background: var(--sidebar-gray); + cursor: pointer; + user-select: none; + border-bottom: 2px solid rgba(0, 0, 0, 0.1); + transition: background-color 0.2s ease; +text-align: center; + } + + .sidebar-accordion-header:hover { + background: #c5c5c5; + } + + .sidebar-accordion-header:active { + background: #b8b8b8; + } + + .sidebar-accordion-header iconify-icon { + flex-shrink: 0; + } + + .sidebar-accordion-header span { + font-weight: 700; + font-size: 1.3rem; + flex: 1; + } + + .sidebar-accordion-header .chevron { + transition: transform 0.3s ease; + } + + .sidebar-accordion-header.active .chevron { + transform: rotate(180deg); + } + + .sidebar-accordion-content { + max-height: 0; + overflow: hidden; + transition: max-height 0.3s ease-out; + padding: 0 1rem; + } + + .sidebar-accordion-content.active { + max-height: 5000px; + transition: max-height 0.5s ease-in; + padding: 1rem 1rem 0.5rem 1rem; + } + + /* Reduce font sizes inside accordion content */ + .sidebar-accordion-content .sidebar-title { + font-size: 1rem; + } + + .sidebar-accordion-content .sidebar-content, + .sidebar-accordion-content .skill-item { + font-size: 0.8rem; + } + + .page-1 .cv-main, + .page-2 .cv-main { + width: 100% !important; + position: static !important; + grid-column: unset; + grid-row: unset; + padding: 2rem 1.5rem !important; + } + + /* Adjust title badges header for mobile */ + .cv-title-badges-header { + padding: 0.75rem 1rem !important; + font-size: 0.85rem; + } + + .badge { + font-size: 0.75rem !important; + padding: 0.25rem 0.5rem !important; + } + + /* Hide header on page 2 for mobile to merge pages */ + .page-2 .cv-title-badges-header { + display: none; + } + + /* Adjust footer for mobile */ + .cv-footer { + padding: 1.5rem 1rem; + } + + .footer-content li { + display: block !important; + margin-bottom: 1.5rem; + } + + .footer-content li > div { + display: block; + margin: 0; + text-align: center; + width: 100%; + } + + .footer-label { + font-size: 0.9rem; + margin-top: 1rem; + color: #777; + } + + .footer-separator { + display: none; + } + + .footer-value { + font-size: 1.2rem; + margin-bottom: 0; + padding: 0; + } + + .footer-value b { + font-size: 1.3rem; + } + + .site-title { + justify-content: space-between; + width: 100%; + } + + /* Ensure proper stacking order */ + .cv-sidebar-left { + order: 1; + } + + .cv-title-badges-header { + order: 2; + } + + .cv-main { + order: 3; + } + + .cv-sidebar-right { + order: 4; + } + + .cv-footer { + order: 5; + } +} + +/* =============================================== + TABLET RESPONSIVE + =============================================== */ + +@media (max-width: 768px) { + /* Further reduce padding on smaller screens */ + .cv-page { + margin: 0.25rem; + } + + .cv-sidebar-left, + .cv-sidebar-right { + width: 100% !important; + padding: 1.5rem 1rem; + } + + /* Force left alignment for all sidebar content on mobile */ + .cv-sidebar-left .sidebar-content, + .cv-sidebar-left .skill-item { + text-align: left !important; + } + /* Force right alignment for all sidebar content on mobile */ + .cv-sidebar-right .sidebar-content, + .cv-sidebar-right .skill-item { + text-align: right !important; + } + .page-1 .cv-main, + .page-2 .cv-main { + width: 100% !important; + padding: 1.5rem 1rem !important; + } + + .cv-title-badges-header { + padding: 0.5rem 0.75rem !important; + font-size: 0.8rem; + } + + .badge { + font-size: 0.7rem !important; + padding: 0.2rem 0.4rem !important; + } + + /* Footer refinements */ + .cv-footer { + padding: 1rem 0.75rem; + } + + .footer-label { + font-size: 1.1rem; + margin-top: 0.75rem; + } + + .footer-value { + font-size: 0.85rem; + } + + .footer-value b { + font-size: 0.95rem; + } + + /* Sidebar title sizing */ + .sidebar-title { + font-size: 1.1rem; + } + + .sidebar-content { + font-size: 0.85rem; + } + + /* Section titles */ + .section-title { + font-size: 1.1rem; + margin-bottom: 1rem; + } +} + +/* Company link styling */ +.company-link { + color: var(--accent-blue); + font-weight: 500; + text-decoration: none; +} + +.company-link:hover { + text-decoration: underline; + color: #0052a3; +} + +/* =============================================== + HAMBURGER MENU & NAVIGATION + =============================================== */ + +/* Hamburger button */ +.hamburger-btn { + background: transparent; + border: none; + color: #fff; + cursor: pointer; + padding: 0.5rem; + display: flex; + align-items: center; + justify-content: center; + transition: background-color 0.2s ease; + border-radius: 4px; + margin: 0 0.5rem; + position: relative; /* For CSS-only hover trigger */ +} + + +.hamburger-btn:hover { + background-color: rgba(255, 255, 255, 0.1); +} + +.hamburger-btn:active { + background-color: rgba(255, 255, 255, 0.2); +} + +/* Navigation Menu */ +.navigation-menu { + position: fixed; + top: 50px; /* Height of action bar */ + left: 0; + width: 280px; + max-height: 0; + background: #ffffff; + box-shadow: 2px 0 10px rgba(0, 0, 0, 0.15); + transition: max-height 0.5s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease; + overflow-y: auto; + z-index: 1000; /* Above fixed buttons (z-index: 999) */ + pointer-events: none; /* Disable pointer events when hidden */ + opacity: 0; +} + +/* Pure CSS Menu Activation - Show menu when hovering hamburger OR menu */ +/* Show when hovering the hamburger button (adjacent in DOM after site-title-left) */ +.hamburger-btn:hover ~ .navigation-menu, +.hamburger-btn:focus ~ .navigation-menu, +/* Show when hovering the menu itself */ +.navigation-menu:hover, +/* Legacy class for backward compatibility */ +.navigation-menu.menu-hover, +.navigation-menu.menu-open { + max-height: calc(100vh - 60px); /* Viewport height minus header + some spacing */ + pointer-events: auto; /* Enable pointer events when visible */ + opacity: 1; +} + +.menu-content { + padding: 1rem 0; +} + +.menu-item { + display: flex; + align-items: center; + gap: 1rem; + padding: 0.875rem 1.5rem; + color: var(--text-dark); + text-decoration: none; + transition: background-color 0.2s ease, color 0.2s ease; + font-size: 0.95rem; + font-weight: 500; + border-left: 3px solid transparent; +} + +.menu-item:hover { + background-color: rgba(0, 102, 204, 0.08); + color: var(--accent-blue); + border-left-color: var(--accent-blue); + text-decoration: none; +} + +.menu-item iconify-icon { + color: var(--text-gray); + flex-shrink: 0; + transition: color 0.2s ease; +} + +.menu-item:hover iconify-icon { + color: var(--accent-blue); +} + +/* Menu item action controls (Expand All, Collapse All) */ +/* Removed centered text styling - action items now behave like regular menu items */ + +/* Remove extra padding - all menu items should align consistently */ + +/* Submenu styles - hover triggered, opens to the right */ +.menu-item-submenu { + position: relative; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + padding: 0 0 1rem 0; +} + +.menu-item.has-submenu { + justify-content: space-between; + position: relative; +} + +.submenu-arrow { + transition: transform 0.2s ease; + margin-left: auto; +} + +/* Rotate arrow slightly on hover */ +.menu-item-submenu:hover .submenu-arrow { + transform: translateX(3px); +} + +.submenu-content { + position: fixed; /* Changed from absolute to fixed to break out of parent overflow */ + left: 232px; /* Slight overlap with menu to eliminate any gap */ + background: #ffffff; + box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.15); + border-radius: 8px; + min-width: 250px; + max-width: 300px; + opacity: 0; + visibility: hidden; + transform: translateX(-3px); + transition: all 0.3s ease; + z-index: 1000; /* Higher z-index to appear above everything */ + padding: 0.5rem 0; + max-height: calc(100vh - 100px); /* Ensure it fits viewport */ + overflow-y: auto; /* Scroll if content is too long */ +} + +/* Show submenu when hovering the submenu container OR the submenu itself */ +.menu-item-submenu:hover .submenu-content, +.submenu-content:hover { + opacity: 1; + visibility: visible; + transform: translateX(0); +} + +/* Legacy class for JS compatibility */ +.menu-item-submenu.submenu-open .submenu-arrow { + transform: translateX(3px); +} + +.menu-item-submenu.submenu-open .submenu-content { + opacity: 1; + visibility: visible; + transform: translateX(0); +} + +.submenu-content .menu-item { + padding: 0.875rem 1.5rem; + font-size: 0.9rem; + border-left: 3px solid transparent; + border-radius: 0; +} + +.submenu-content .menu-item:first-child { + border-top-left-radius: 8px; + border-top-right-radius: 8px; +} + +.submenu-content .menu-item:last-child { + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; +} + +/* ========== Menu Sections with Separators ========== */ +/* Quick Actions section - always visible */ +.menu-section-wrapper { + padding: 0.5rem 1.5rem 1rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} + +/* Remove border from last visible section */ +.menu-content > *:last-child, +.menu-content > div:last-child { + border-bottom: none !important; +} + +/* ========== Menu Controls & Actions (Always Visible) ========== */ +/* Always visible in hamburger menu at all screen sizes */ +.menu-controls-section, +.menu-actions-section { + display: block; + padding: 0.5rem 1.5rem 1rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} + +.menu-item-header { + display: flex; + align-items: center; + gap: 1rem; + padding: 0.875rem 0 0.875rem 0; + color: var(--text-dark); + font-size: 0.85rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.5px; + cursor: default; +} + +/* Disable hover effect for headers */ +.menu-item-header:hover { + background-color: transparent !important; + color: var(--text-dark) !important; + border-left-color: transparent !important; +} + +.menu-item-header iconify-icon { + color: var(--text-gray); + flex-shrink: 0; +} + +.menu-item-header:hover iconify-icon { + color: var(--text-gray) !important; +} + +.menu-item-header span { + flex: 1; +} + +.menu-control-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.75rem 0; +} + +.menu-control-label { + display: flex; + align-items: center; + gap: 0.75rem; + color: var(--text-dark); + font-size: 0.9rem; + font-weight: 500; +} + +.menu-control-label iconify-icon { + color: var(--text-gray); +} + +.menu-action-btn { + display: flex; + align-items: center; + justify-content: center; + gap: 1rem; + padding: 0.875rem 1rem; + margin: 0.25rem 0; + background: rgba(0, 0, 0, 0.03); + border: none; + border-radius: 8px; + color: var(--text-dark); + text-decoration: none; + font-size: 0.9rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; + width: 100%; +} + +.menu-action-btn:hover { + background: rgba(0, 102, 204, 0.08); + color: var(--accent-blue); + text-decoration: none; +} + +.menu-action-btn iconify-icon { + color: var(--text-gray); + flex-shrink: 0; + transition: color 0.2s ease; +} + +.menu-action-btn:hover iconify-icon { + color: var(--accent-blue); +} + +/* PDF button in menu - White bg with red icon on hover */ +.menu-pdf-btn:hover, +.menu-pdf-btn.pdf-hover-sync { + background: white !important; + color: #e74c3c !important; +} + +.menu-pdf-btn:hover iconify-icon, +.menu-pdf-btn.pdf-hover-sync iconify-icon { + color: #e74c3c !important; +} + +/* Print button in menu - White bg with green icon on hover */ +.menu-print-btn:hover, +.menu-print-btn.print-hover-sync { + background: white !important; + color: #27ae60 !important; +} + +.menu-print-btn:hover iconify-icon, +.menu-print-btn.print-hover-sync iconify-icon { + color: #27ae60 !important; +} + +/* Section icons in titles */ +.section-icon { + vertical-align: middle; + margin-right: 0.5rem; + color: #7d7d7d; +} + +/* Add invisible separator (blank space) below section titles */ +#experience .section-title, +#awards .section-title, +#courses .section-title, +#projects .section-title { + margin-bottom: 40px !important; +} + +/* Smooth scrolling */ +html { + scroll-behavior: smooth; +} + +/* Add scroll padding to account for fixed header */ +html { + scroll-padding-top: 70px; /* Action bar height + some spacing */ +} + +/* Mobile responsive */ +@media (max-width: 768px) { + .navigation-menu { + width: 240px; + } + + .menu-item { + padding: 0.75rem 1rem; + font-size: 0.9rem; + } + + .site-title { + justify-content: space-between; + width: 100%; + } +} + +/* Hide menu overlay on print */ +@media print { + .navigation-menu { + display: none !important; + } + + .hamburger-btn { + display: none !important; + } +} + +/* ======================================== + Scroll Direction - Hide/Show Header + ======================================== */ + +/* Add smooth transition to header elements */ +.action-bar, +.navigation-menu { + transition: transform 0.3s ease-in-out; +} + +/* Hide header when scrolling down */ +.action-bar.header-hidden { + transform: translateY(-100%); +} + +.navigation-menu.header-hidden { + transform: translateY(-100%); +} + +/* ======================================== + Back to Top Button + ======================================== */ + +.back-to-top { + position: fixed; + bottom: 2rem; + right: 2rem; + width: 50px; + height: 50px; + background: var(--black-bar); + color: white; + border: none; + border-radius: 50%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + z-index: 99; + transition: all 0.3s ease; + opacity: 0.2; +} + +.back-to-top:hover { + opacity: 1; + transform: translateY(-3px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); + background: #27ae60; +} + +.back-to-top.at-bottom { + opacity: 1; + background: #27ae60; +} + +.back-to-top:active { + transform: translateY(-1px); + box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3); +} + +/* Mobile adjustments */ +@media (max-width: 768px) { + .back-to-top { + bottom: 1.5rem; + right: 1.5rem; + width: 45px; + height: 45px; + } +} + +/* ======================================== + Info Button (Bottom Left) + ======================================== */ + +.info-button { + position: fixed; + bottom: 2rem; + left: 2rem; + width: 50px; + height: 50px; + background: var(--black-bar); + color: white; + border: none; + border-radius: 50%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + z-index: 99; + transition: all 0.3s ease; + opacity: 0.6; /* Increased from 0.2 for better discoverability */ +} + +.info-button:hover { + opacity: 1; + transform: translateY(-3px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); + background: #27ae60; +} + +.info-button.at-bottom { + opacity: 1; + background: #27ae60; +} + +.info-button:active { + transform: translateY(-1px); + box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3); +} + +/* Mobile adjustments - Flexbox button layout at bottom center */ +@media (max-width: 900px) { + /* Hide only zoom control on mobile */ + .zoom-toggle-btn, + .zoom-control { + display: none !important; + } + + /* Reset fixed positioning for FLEXBOX buttons on mobile (exclude back-to-top) */ + .download-btn, + .print-friendly-btn, + .shortcuts-btn, + .info-button { + position: fixed !important; + bottom: 1.5rem !important; + left: auto !important; + right: auto !important; + width: 50px !important; + height: 50px !important; + opacity: 0.7 !important; + transform: none !important; + } + + /* Keep back-to-top button at bottom-right (same as desktop) */ + .back-to-top { + position: fixed !important; + bottom: 1.5rem !important; + right: 1.5rem !important; + width: 50px !important; + height: 50px !important; + } + + /* Flexbox container behavior - buttons arrange themselves */ + /* Buttons will be positioned using JavaScript or individual positioning */ + /* For now, use fixed spacing from center */ + + /* 5 buttons: Download, Print, Shortcuts, Theme, Info */ + /* Spacing: 10px gap between buttons, centered horizontally */ + /* Total width: 5 * 50px + 4 * 10px = 290px */ + /* Start position: 50% - 145px */ + + .download-btn { + left: calc(50% - 145px) !important; /* First button */ + } + + .print-friendly-btn { + left: calc(50% - 85px) !important; /* Second button */ + } + + .shortcuts-btn { + left: calc(50% - 25px) !important; /* Third button */ + } + + /* Theme switcher button - fourth position (defined in color-theme.css) */ + /* left: calc(50% + 35px) !important; */ + + .info-button { + left: calc(50% + 95px) !important; /* Fifth button (last) */ + } + + /* Hover effects - only Y transform + enhanced shadow */ + .download-btn:hover, + .download-btn.pdf-hover-sync, + .print-friendly-btn:hover, + .print-friendly-btn.print-hover-sync, + .shortcuts-btn:hover, + .info-button:hover, + .back-to-top:hover { + transform: translateY(-3px) !important; + opacity: 1 !important; + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4) !important; + } + + /* Keep at-bottom state without transform */ + .info-button.at-bottom, + .shortcuts-btn.at-bottom { + opacity: 1 !important; + transform: none !important; + } +} + +/* Very narrow mobile - Move back-to-top UP on RIGHT side to avoid overlap */ +@media (max-width: 483px) { + .back-to-top { + /* Stay on RIGHT side, just move UP higher */ + right: 1.5rem !important; + bottom: 5.5rem !important; /* Higher position to clear bottom button row */ + } +} + +/* ======================================== + Info Modal - Modern Glassmorphism Design + ======================================== */ + +/* Native element - force centering */ +.info-modal { + border: none; + border-radius: 24px; + padding: 0; + max-width: 420px; + width: calc(100% - 2rem); + background: transparent; + /* Force centering - override any browser defaults */ + position: fixed; + inset: 0; + margin: auto; + /* Constrain height so margin:auto can center vertically */ + max-height: fit-content; +} + +/* Native ::backdrop pseudo-element replaces manual backdrop div */ +.info-modal::backdrop { + background: rgba(0, 0, 0, 0.7); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); +} + +/* Dialog opening animation - native dialog uses [open] attribute */ +.info-modal[open] { + animation: modalFadeIn 0.3s ease; +} + +@keyframes modalFadeIn { + from { + opacity: 0; + transform: scale(0.9) translateY(20px); + } + to { + opacity: 1; + transform: scale(1) translateY(0); + } +} + +.info-modal-content { + background: linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.9) 100%); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + border-radius: 24px; + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3), 0 0 100px rgba(39, 174, 96, 0.1); + width: 100%; + padding: 2.5rem; + position: relative; + border: 1px solid rgba(255, 255, 255, 0.8); +} + +.info-modal-close { + position: absolute; + top: 1rem; + right: 1rem; + background: rgba(0, 0, 0, 0.05); + border: none; + width: 40px; + height: 40px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + color: #333; + transition: all 0.2s ease; + z-index: 10; +} + +.info-modal-close:hover { + background: rgba(0, 0, 0, 0.1); + transform: rotate(90deg); +} + +.info-modal-header { + text-align: center; + margin-bottom: 2rem; +} + +.info-modal-header h2 { + font-size: 1.5rem; + font-weight: 600; + color: #333; + margin: 0 0 1.5rem 0; +} + +.info-modal-cv-title { + font-size: 1.5rem; + font-weight: 700; + color: #f39c12; /* Orange subtitle */ + margin-bottom: 0; + letter-spacing: 0.05em; + display: flex; + align-items: center; + gap: 0.5rem; + justify-content: center; +} + +#info-modal .info-modal-cv-title { + color: #27ae60; +} + +.info-modal-photo { + width: 40px; + height: 53px; + object-fit: cover; + border-radius: 4px; + border: none; + box-shadow: none; +} + +.photo-bracket-wrapper { + position: relative; + display: inline-flex; + align-items: center; + padding: 0 22px; +} + +.photo-bracket-wrapper::before { + content: '{'; + position: absolute; + left: 2px; + font-size: 2rem; + font-weight: 700; + color: #27ae60; + line-height: 1; + top: 8px; +} + +.photo-bracket-wrapper::after { + content: '}'; + position: absolute; + right: 2px; + font-size: 2rem; + font-weight: 700; + color: #27ae60; + line-height: 1; + top: 8px; +} + +.info-modal-body { + color: #333; +} + +.info-modal-description { + font-size: 1rem; + line-height: 1.6; + margin-bottom: 2rem; + color: #444; +} + +.info-modal-description strong { + color: #27ae60; + font-weight: 600; +} + +.info-modal-tech { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 1rem; + margin-bottom: 2rem; +} + +.info-tech-item { + display: flex; + align-items: center; + justify-content: center; + gap: 0.75rem; + padding: 0.75rem; + background: rgba(39, 174, 96, 0.05); + border-radius: 12px; + border: 1px solid rgba(39, 174, 96, 0.1); + transition: all 0.3s ease; +} + +.info-tech-item:hover { + background: rgba(39, 174, 96, 0.1); + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(39, 174, 96, 0.2); +} + +.info-tech-item iconify-icon { + color: #27ae60; + flex-shrink: 0; +} + +.info-tech-item span { + font-size: 0.9rem; + font-weight: 500; + color: #333; +} + +.info-modal-github { + display: flex; + align-items: center; + justify-content: center; + gap: 0.75rem; + padding: 1rem 1.5rem; + background: linear-gradient(135deg, #27ae60 0%, #229954 100%); + color: white; + text-decoration: none; + border-radius: 12px; + font-weight: 600; + font-size: 1rem; + transition: all 0.3s ease; + box-shadow: 0 4px 15px rgba(39, 174, 96, 0.3); +} + +.info-modal-github:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(39, 174, 96, 0.4); + background: linear-gradient(135deg, #229954 0%, #27ae60 100%); +} + +.info-modal-github:active { + transform: translateY(0); + box-shadow: 0 4px 15px rgba(39, 174, 96, 0.3); +} + +.info-modal-github-subtext { + text-align: center; + font-size: 0.9rem; + color: #666; + margin-top: 1.5rem; + margin-bottom: 1rem; + font-style: italic; +} + +/* Mobile responsive */ +@media (max-width: 768px) { + .info-modal-content { + padding: 2rem 1.5rem; + max-width: calc(100% - 2rem); + } + + .info-modal-header h2 { + font-size: 1.5rem; + } + + .info-modal-tech { + grid-template-columns: 1fr; + } + + .info-modal-description { + font-size: 0.95rem; + } +} + +/* ======================================== + Desktop: Ensure Sidebar Content Visible (>1280px) + ======================================== */ + +/* ======================================== + Responsive: Medium Screens (901px - 1023px) + ======================================== */ + +@media (min-width: 901px) and (max-width: 1023px) { + + /* ========== Global Font Size Reduction ========== */ + html { + font-size: 14px; /* Reduced from default 16px */ + } + + .cv-name { + font-size: 1.8em; /* Reduced from 2.2em */ + } + + .sidebar-title { + font-size: 0.95rem; + } + + .sidebar-content { + font-size: 0.9rem; + } + + /* ========== Selector Labels - Hide, Show on Hover ========== */ + .selector-label { + max-width: 0; + overflow: hidden; + opacity: 0; + transition: all 0.3s ease; + white-space: nowrap; + } + + .selector-group:hover .selector-label { + max-width: 200px; + opacity: 1; + margin-right: 0.75rem; + } + + /* ========== Language Selector - Collapse to EN/ES ========== */ + .language-selector .selector-btn { + position: relative; + padding: 0.4rem 1rem; /* Keep padding consistent */ + min-width: 50px; + font-size: 0; /* Hide actual text */ + overflow: visible; + transition: font-size 0.3s ease; /* Slower animation */ + display: inline-flex; + justify-content: center; + align-items: center; + } + + /* Show only short version (EN/ES) */ + .language-selector .selector-btn::before { + content: attr(data-short); + font-size: 1rem; /* Restore font size for pseudo-element */ + opacity: 1; + transition: opacity 0.3s ease; /* Slower animation */ + display: block; + width: 100%; + text-align: center; + } + + /* On hover of INDIVIDUAL button only, show full text */ + .language-selector .selector-btn:hover { + font-size: 1rem; /* Restore font size to show full text */ + min-width: auto; + } + + .language-selector .selector-btn:hover::before { + content: ''; /* Hide short version */ + opacity: 0; + } + + /* ========== Action Buttons - Icon Only, Expand on Hover ========== */ + .action-btn { + position: relative; + width: 45px; + overflow: hidden; + transition: width 0.3s ease, padding 0.3s ease; + white-space: nowrap; + text-indent: 0; + } + + /* Hide button text, keep icon */ + .action-btn iconify-icon { + flex-shrink: 0; + } + + .action-btn { + font-size: 0; + padding: 0 0.65rem; + justify-content: center; + } + + /* On hover, show text */ + .action-btn:hover { + width: auto; + font-size: 0.95rem; + padding: 0.65rem 1.5rem; + gap: 0.5rem; + } + + /* ========== Sidebar Content - Hide Text, Show on Hover ========== */ + .sidebar-content { + max-height: 0 !important; + overflow: hidden !important; + opacity: 0 !important; + } + + /* Show sidebar content on hover */ + .skill-category:hover .sidebar-content, + .cv-sidebar-section:hover .sidebar-content { + max-height: 1000px !important; + opacity: 1 !important; + margin-top: 10px !important; + } +} + +/* ======================================== + Responsive: Medium Screens (1024px - 1280px) + ======================================== */ + +@media (min-width: 1024px) and (max-width: 1280px) { + + /* ========== Global Font Size Reduction ========== */ + html { + font-size: 14px; /* Reduced from default 16px */ + } + + .cv-name { + font-size: 1.8em; /* Reduced from 2.2em */ + } + + .sidebar-title { + font-size: 0.95rem; + } + + .sidebar-content { + font-size: 0.9rem; + } + + /* ========== Selector Labels - Hide, Show on Hover ========== */ + .selector-label { + max-width: 0; + overflow: hidden; + opacity: 0; + transition: all 0.3s ease; + white-space: nowrap; + } + + .selector-group:hover .selector-label { + max-width: 200px; + opacity: 1; + margin-right: 0.75rem; + } + + /* ========== Language Selector - Collapse to EN/ES ========== */ + .language-selector .selector-btn { + position: relative; + padding: 0.4rem 1rem; /* Keep padding consistent */ + min-width: 50px; + font-size: 0; /* Hide actual text */ + overflow: visible; + transition: font-size 0.3s ease; /* Slower animation */ + display: inline-flex; + justify-content: center; + align-items: center; + } + + /* Show only short version (EN/ES) */ + .language-selector .selector-btn::before { + content: attr(data-short); + font-size: 1rem; /* Restore font size for pseudo-element */ + opacity: 1; + transition: opacity 0.3s ease; /* Slower animation */ + display: block; + width: 100%; + text-align: center; + } + + /* On hover of INDIVIDUAL button only, show full text */ + .language-selector .selector-btn:hover { + font-size: 1rem; /* Restore font size to show full text */ + min-width: auto; + } + + .language-selector .selector-btn:hover::before { + content: ''; /* Hide short version */ + opacity: 0; + } + + /* ========== Action Buttons - Icon Only, Expand on Hover ========== */ + .action-btn { + position: relative; + width: 45px; + overflow: hidden; + transition: width 0.3s ease, padding 0.3s ease; + white-space: nowrap; + text-indent: 0; + } + + /* Hide button text, keep icon */ + .action-btn iconify-icon { + flex-shrink: 0; + } + + .action-btn { + font-size: 0; + padding: 0 0.65rem; + justify-content: center; + } + + /* On hover, show text */ + .action-btn:hover { + width: auto; + font-size: 0.95rem; + padding: 0.65rem 1.5rem; + gap: 0.5rem; + } + + /* ========== Sidebar Content - Hide Text, Show on Hover ========== */ + .sidebar-content { + max-height: 0 !important; + overflow: hidden !important; + opacity: 0 !important; + } + + /* Show sidebar content on hover */ + .skill-category:hover .sidebar-content, + .cv-sidebar-section:hover .sidebar-content { + max-height: 1000px !important; + opacity: 1 !important; + margin-top: 10px !important; + } +} + +/* ======================================== + Responsive: Small Screens (up to 540px) + ======================================== */ + +/* ======================================== + Responsive: Tablet Screens - Center Photo (up to 768px) + ======================================== */ + +@media (max-width: 768px) { + /* ======================================== + TYPOGRAPHY - Subtle font size reductions + ======================================== */ + .cv-name { + text-align: center; + font-size: 1.6rem; + } + + .years-experience { + text-align: center; + font-size: 1.1em; + } + + .section-title { + font-size: 1.2em; + } + + .sidebar-title { + font-size: 1.2em; + } + + .experience-period, + .experience-separator, + .experience-location, + .experience-duration { + font-size: 0.95rem; + } + + .position { + font-size: 0.95rem; + } + + .short-desc, + .responsibilities li { + font-size: 0.85rem; + } + + /* ======================================== + TEXT ALIGNMENT FIXES - Selective alignment + ======================================== */ + /* Keep justified for intro and skills */ + .intro-text, + .summary-text { + text-align: justify; + font-size: 0.85rem; + line-height: 1.5; + } + + .intro-text { + margin-top: 0; + width: 100%; + } + + /* Left-align for course/project descriptions */ + .course-desc, + .project-desc { + text-align: left !important; + font-size: 0.85rem !important; + line-height: 1.5; + } + + /* ======================================== + HEADER LAYOUT - Centered photo + ======================================== */ + .cv-header-content { + flex-direction: column; + align-items: center; + gap: 1rem; + } + + .cv-header-left { + width: 100%; + position: static; + padding-right: 0; + } + + .cv-photo { + position: static; + width: auto; + height: auto; + max-width: 250px; + margin: 1.5rem auto; + text-align: center; + right: auto; + top: auto; + } + + .cv-photo img { + width: 100%; + height: auto; + max-height: none; + } + + /* ======================================== + UNIFIED LOGO/ICON SIZING - Consistent 60px + ======================================== */ + .company-logo, + .course-icon, + .project-icon, + .award-logo { + width: 60px !important; + height: 60px !important; + flex-shrink: 0; + } + + .company-logo img, + .course-icon img, + .project-icon img, + .award-logo img { + width: 60px !important; + height: 60px !important; + object-fit: contain; + } + + .default-company-icon, + .default-course-icon, + .default-project-icon, + .default-award-icon { + width: 60px !important; + height: 60px !important; + } + + /* ======================================== + CONSISTENT ITEM LAYOUT - Uniform spacing + ======================================== */ + .experience-item, + .course-item, + .project-item, + .award-item { + display: flex; + flex-direction: row; + gap: 1rem !important; + align-items: flex-start; + margin-bottom: 2rem !important; + padding-bottom: 1.5rem !important; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + } + + .experience-item { + margin-bottom: 1.8rem !important; + } + + .experience-content, + .course-content, + .project-content, + .award-content { + flex: 1; + min-width: 0; + } + + /* ======================================== + FONT SIZE CONSISTENCY - Titles and descriptions + ======================================== */ + .course-title, + .project-title, + .award-item strong { + font-size: 0.95rem !important; + line-height: 1.4; + } + + .course-item small, + .project-item small, + .award-item small { + font-size: 0.8rem !important; + } + + .course-desc, + .project-desc, + .award-desc { + font-size: 0.85rem !important; + line-height: 1.5; + } + + /* ======================================== + RESPONSIBILITIES MOBILE OPTIMIZATION + ======================================== */ + .responsibilities li:has(img), + .responsibilities li:has(iconify-icon) { + grid-template-columns: 60px 1fr !important; + gap: 0.75rem !important; + margin-bottom: 0.75rem !important; + } + + .responsibilities li img, + .responsibilities li iconify-icon.default-company-icon { + width: 60px !important; + height: 60px !important; + } + + /* ======================================== + SIDEBAR ITEMS MOBILE OPTIMIZATION + ======================================== */ + .language-item, + .reference-item, + .other-content { + margin-bottom: 0 !important; + line-height: 1.4 !important; + margin-left: 1rem !important; + font-size: 0.85rem !important; + } +} + +/* ======================================== + Responsive: All Mobile Screens (up to 540px) + ======================================== */ + +@media (max-width: 540px) { + /* Simplify action bar grid for mobile: single column */ + .action-bar-content { + grid-template-columns: 1fr; + gap: 0; + padding: 0; + } + + /* Hide center controls on mobile (moved to hamburger menu) */ + .view-controls-center { + display: none; + } + + /* Hide action buttons on small screens (available in hamburger menu) */ + .action-buttons-right { + display: none; + } + + /* Site title uses flexbox with percentage widths */ + .site-title { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + padding: 0 0.5rem; + gap: 0.5rem; + } + + /* Left group (hamburger + title) takes ~50-60% */ + .site-title-left { + display: flex; + align-items: center; + gap: 0.5rem; + flex: 1 1 1; + min-width: 0; + } + + /* Title link is flexible within left group */ + .site-title-link { + flex: 1 1 auto; + min-width: 0; + overflow: hidden; + } + + .site-title-text { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + /* Language selector takes ~30-35% */ + .language-selector { + display: flex; + flex: 0 0 35%; + margin-left: auto; + padding-left: 0; + margin-right: 0; + justify-content: flex-end; + gap: 0.25rem; + } + + /* Hide year from title in mobile view */ + .site-title-year { + display: none; + } + + /* Hide desktop logo, show mobile icon in title */ + .site-logo-link { + display: none; + } + + .site-icon-mobile { + display: inline-flex; + } + + /* ========== Language Selector - Show Short Names Only ========== */ + .language-selector .selector-btn { + position: relative; + padding: 0.4rem 0.75rem; + min-width: 40px; + font-size: 0; /* Hide actual text */ + overflow: visible; + transition: font-size 0.3s ease; + display: inline-flex; + justify-content: center; + align-items: center; + } + + /* Show only short version (EN/ES) */ + .language-selector .selector-btn::before { + content: attr(data-short); + font-size: 0.95rem; + opacity: 1; + transition: opacity 0.3s ease; + display: block; + width: 100%; + text-align: center; + } + + /* Keep short names on hover (no expansion) */ + .language-selector .selector-btn:hover { + font-size: 0; + min-width: 40px; + } + + .language-selector .selector-btn:hover::before { + content: attr(data-short); + opacity: 1; + } +} + +/* ========================================================================== + ZOOM CONTROL - Fixed Bottom Center + ========================================================================== */ + +.zoom-control { + position: fixed; + bottom: 100px; /* Default position, can be dragged */ + left: 50%; + transform: translateX(-50%); + z-index: 900; + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.65rem 1.25rem; + background: rgba(128, 128, 128, 0.7); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + border-radius: 50px; + box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2); + transition: all 0.3s ease; + opacity: 0.7; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; + cursor: move; /* Indicate draggability */ + user-select: none; /* Prevent text selection while dragging */ +} + +/* Zoom control highlight when hovering zoom toggle button */ +.zoom-control.zoom-highlight { + opacity: 1; + box-shadow: 0px 0px 10px 4px rgb(1 113 188 / 80%); + background: rgb(91 91 91); +} + +/* Hidden state for zoom control and show button */ +.zoom-hidden { + display: none !important; +} + +/* Close button for zoom control */ +.zoom-close-btn { + position: absolute; + top: -8px; + right: -8px; + width: 24px; + height: 24px; + background: rgba(128, 128, 128, 0.6); /* Subtle grey */ + border: 2px solid rgba(255, 255, 255, 0.3); + border-radius: 50%; + color: rgba(255, 255, 255, 0.8); /* Light grey icon */ + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + padding: 0; + transition: all 0.2s ease; + z-index: 1; + opacity: 0.7; /* Subtle by default */ +} + +.zoom-close-btn:hover { + background: rgba(220, 53, 69, 0.9); /* Red on hover */ + color: white; /* White icon on hover */ + opacity: 1; /* Fully visible on hover */ + transform: scale(1.1); + box-shadow: 0 2px 8px rgba(220, 53, 69, 0.4); +} + +.zoom-control:hover { + opacity: 1; + background: rgb(91 91 91); + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); +} + +/* Zoom Values (Labels) */ +.zoom-value { + color: rgba(255, 255, 255, 1); /* 100% white */ + font-size: 0.95rem; /* Bigger */ + font-weight: 500; /* Medium weight */ + min-width: 30px; + text-align: center; +} + +.zoom-value-current { + color: rgba(255, 255, 255, 1); /* 100% white */ + font-weight: 600; + font-size: 1.05rem; /* Bigger */ + min-width: 35px; +} + +/* Range Slider Styling */ +.zoom-slider { + -webkit-appearance: none; + appearance: none; + width: 180px; + height: 5px; + border-radius: 3px; + background: rgba(200, 200, 200, 0.5); + outline: none; + cursor: pointer; + transition: all 0.3s ease; +} + +/* Solid blue color on hover - no gradient */ +.zoom-control:hover .zoom-slider, +.zoom-slider:hover { + background: rgba(145, 190, 236, 1); /* solid blue */ +} + +.zoom-slider:focus { + outline: 2px solid rgba(255, 255, 255, 0.6); + outline-offset: 2px; +} + +/* Webkit Slider Thumb */ +.zoom-slider::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 18px; + height: 18px; + border-radius: 50%; + background: white; + border: 2px solid rgba(180, 180, 180, 0.8); + cursor: pointer; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); + transition: all 0.2s ease; +} + +.zoom-slider::-webkit-slider-thumb:hover { + transform: scale(1.1); + border-color: rgba(200, 200, 200, 1); + box-shadow: 0 3px 8px rgba(0, 0, 0, 0.4); +} + +.zoom-slider::-webkit-slider-thumb:active { + transform: scale(1.05); +} + +/* Firefox Slider Thumb */ +.zoom-slider::-moz-range-thumb { + width: 18px; + height: 18px; + border-radius: 50%; + background: white; + border: 2px solid rgba(180, 180, 180, 0.8); + cursor: pointer; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); + transition: all 0.2s ease; +} + +.zoom-slider::-moz-range-thumb:hover { + transform: scale(1.1); + border-color: rgba(200, 200, 200, 1); + box-shadow: 0 3px 8px rgba(0, 0, 0, 0.4); +} + +.zoom-slider::-moz-range-thumb:active { + transform: scale(1.05); +} + +/* Firefox Range Track */ +.zoom-slider::-moz-range-track { + height: 5px; + border-radius: 3px; + background: rgba(200, 200, 200, 0.5); + transition: all 0.3s ease; +} + +/* Firefox Range Track - Solid blue on hover */ +.zoom-control:hover .zoom-slider::-moz-range-track, +.zoom-slider:hover::-moz-range-track { + background: #3b82f6; /* solid blue */ +} + +/* Reset Button - Circular with dynamic value inside */ +.zoom-reset-btn { + display: flex; + align-items: center; + justify-content: center; + min-width: 44px; + min-height: 44px; + padding: 0.5rem; + background: rgba(200, 200, 200, 0.2); + border: 2px solid rgba(220, 220, 220, 0.3); + border-radius: 50%; + color: rgba(255, 255, 255, 0.8); + font-size: 0.85rem; + font-weight: 700; + cursor: pointer; + transition: all 0.3s ease; + flex-shrink: 0; + margin: 0 -5px 0 10px; +} + +.zoom-reset-btn #zoom-value-current { + color: inherit; + font-size: inherit; + font-weight: inherit; + min-width: auto; +} + +.zoom-reset-btn:hover { + background: rgba(220, 220, 220, 0.4); + border-color: rgba(240, 240, 240, 0.6); + color: white; +} + +/* Green hover only when zoom is not at default (100) */ +.zoom-reset-btn.zoom-not-default:hover { + background: #74aacd; + border-color: #74aacd; + color: white; +} + +.zoom-reset-btn:active { + transform: scale(0.95); +} + +.zoom-reset-btn:focus { + outline: 2px solid rgba(255, 255, 255, 0.6); + outline-offset: 2px; +} + +/* Mobile Responsive - Horizontal button layout defined below (around line 2867) */ +/* Old mobile styles removed - now using horizontal layout with all three buttons */ + +/* Very Small Screens - Ultra Compact */ +@media (max-width: 480px) { + .zoom-control { + bottom: 40px; + padding: 0.35rem 0.7rem; + gap: 0.35rem; + } + + .zoom-slider { + width: 100px; + } + + /* Hide min/max labels on very small screens */ + .zoom-value-min, + .zoom-value-max { + display: none; + } +} + +/* ============================================================================= + HTMX CSS TRANSITIONS + ============================================================================= */ + +/* Inline loading transition styles moved to main section above (~line 1677) */ +/* Prevent layout shift during content fade */ +.cv-page-content-wrapper { + position: relative; +} + +/* ============================================================================= + KEYBOARD SHORTCUTS BUTTON & MODAL + ============================================================================= */ + +/* Shortcuts Button (Fixed Left) - Mirrors info-button on opposite side */ +/* Zoom Toggle Button (above shortcuts button) */ +.zoom-toggle-btn { + position: fixed; + bottom: 10rem; /* Above shortcuts button */ + left: 2rem; + width: 50px; + height: 50px; + background: var(--black-bar); + color: white; /* Match other buttons when inactive */ + border: none; + border-radius: 50%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + transition: all 0.3s ease; + z-index: 999; + opacity: 0.6; /* Match shortcuts button opacity */ +} + +.zoom-toggle-btn:hover { + opacity: 1; + transform: translateY(-3px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); + background: #3498db; /* Blue hover */ +} + +.zoom-toggle-btn.at-bottom { + opacity: 1; + background: #3498db; /* Blue - matches hover */ +} + +/* No special styling for active state - button looks same whether zoom is on or off */ + +.shortcuts-btn { + position: fixed; + bottom: 6rem; /* Above back-to-top button (2rem + 50px + gap) */ + left: 2rem; /* LEFT SIDE instead of right */ + width: 50px; + height: 50px; + background: var(--black-bar); + color: white; + border: none; + border-radius: 50%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + z-index: 99; + transition: all 0.3s ease; + opacity: 0.6; /* Increased from 0.2 for better discoverability */ +} + +.shortcuts-btn:hover { + opacity: 1; + transform: translateY(-3px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); + background: #f39c12; /* Orange hover */ +} + +.shortcuts-btn.at-bottom { + opacity: 1; + background: #f39c12; /* Orange when at bottom */ +} + +.shortcuts-btn:active { + transform: translateY(-1px); +} + +/* Print-Friendly Button (second from top) */ +.print-friendly-btn { + position: fixed; + bottom: 18rem; /* Below download button (22rem) */ + left: 2rem; + width: 50px; + height: 50px; + background: var(--black-bar); /* Dark background by default */ + color: white; /* White icon by default */ + border: none; + border-radius: 50%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + transition: all 0.3s ease; + z-index: 999; + opacity: 0.6; +} + +.print-friendly-btn iconify-icon { + color: white; /* White icon by default */ +} + +.print-friendly-btn:hover, +.print-friendly-btn.print-hover-sync { + opacity: 1; + transform: translateY(-3px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); + background: white !important; /* White background on hover */ + color: #27ae60; /* Green icon on hover */ +} + +.print-friendly-btn:hover iconify-icon, +.print-friendly-btn.print-hover-sync iconify-icon { + color: #27ae60; /* Green icon on hover */ +} + +.print-friendly-btn.at-bottom { + opacity: 1; + background: white !important; /* White background - matches hover */ + color: #27ae60; /* Green - matches hover */ +} + +.print-friendly-btn.at-bottom iconify-icon { + color: #27ae60; /* Green icon when at bottom */ +} + +/* Download Button (TOP POSITION) */ +.download-btn { + position: fixed; + bottom: 22rem; /* Top button position */ + left: 2rem; + width: 50px; + height: 50px; + background: var(--black-bar); + color: white; + border: none; + border-radius: 50%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + transition: all 0.3s ease; + z-index: 999; + opacity: 0.6; +} + +.download-btn { + background: var(--black-bar); /* Gray by default like other buttons */ + opacity: 0.6; /* Match other buttons */ +} + +.download-btn:hover, +.download-btn.pdf-hover-sync { + opacity: 1; + transform: translateY(-3px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); + background: #cd6060 !important; /* PDF red on hover */ +} + +.download-btn iconify-icon { + filter: brightness(0) invert(1); /* Always white */ + transition: filter 0.3s ease; +} + +.download-btn:hover iconify-icon { + filter: brightness(0) invert(1); /* Keep white on hover */ +} + +.download-btn.at-bottom { + opacity: 1; + background: #cd6060 !important; /* PDF red - matches hover */ +} + +/* Mobile adjustments */ +@media (max-width: 768px) { + .shortcuts-btn { + bottom: 5.5rem; /* Above back-to-top button (1.5rem + 45px + gap) */ + left: 1.5rem; /* LEFT SIDE on mobile too */ + width: 45px; + height: 45px; + } +} + +/* Shortcuts Modal - Very wide for 3-column grid, less tall */ +#shortcuts-modal { + max-width: 900px; /* Much wider - was 750px */ + max-height: 80vh; /* Limit height */ +} + +/* Keyboard icon with green curly brackets (matching info modal style) */ +.keyboard-icon-wrapper { + position: relative; + display: inline-flex; + align-items: center; + padding: 0 22px; +} + +.keyboard-icon-wrapper::before { + content: '{'; + position: absolute; + left: 2px; + font-size: 2rem; + font-weight: 700; + color: #575757ff; /* Dark brackets - matching info modal */ + line-height: 1; + top: -3px; +} + +.keyboard-icon-wrapper::after { + content: '}'; + position: absolute; + right: 2px; + font-size: 2rem; + font-weight: 700; + color: #575757ff; /* Dark brackets - matching info modal */ + line-height: 1; + top: -3px; +} + +.keyboard-icon-wrapper iconify-icon { + color: #f39c12; + position: relative; + top: 1px; +} + +/* Add margin-bottom to subtitle */ +#shortcuts-modal .info-modal-cv-title { + margin-bottom: 0.5rem; +} + +#shortcuts-modal .info-modal-body { + display: grid; + grid-template-columns: 1fr 1fr; /* 2 columns for 5 sections (3+2) */ + gap: 1.2rem 1.5rem; /* row gap, column gap */ + margin-top: 1.5rem; /* Increased spacing since no description */ +} + +/* Shortcuts Modal Content - Extends info-modal styles */ +.shortcuts-section { + margin-top: 0; /* Grid handles spacing */ + background: #f8f9fa; + border: 1px solid #e1e4e8; + border-radius: 8px; + padding: 1rem; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); +} + +.shortcuts-section:first-of-type { + margin-top: 0; +} + +.shortcuts-section-title { + font-size: 1.05rem; + font-weight: 600; + color: #827a6e; /* Brownish-gray for section header text */ + margin-bottom: 0.75rem; + display: flex; + align-items: center; + gap: 0.5rem; + padding-bottom: 0.5rem; + border-bottom: 2px solid rgba(130, 122, 110, 0.2); /* Matching border */ +} + +.shortcuts-section-title iconify-icon { + color: #f39c12; /* ORANGE icons for section headers */ +} + +.shortcuts-list { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.shortcut-item { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + padding: 0.5rem 0; +} + +.shortcut-keys { + display: flex; + align-items: center; + gap: 0.4rem; + flex-wrap: wrap; +} + +.shortcut-keys kbd { + font-family: 'Monaco', 'Courier New', monospace; + font-size: 0.75rem; + font-weight: 600; + background: rgba(52, 152, 219, 0.08); /* Light blue background */ + border: 1px solid rgba(52, 152, 219, 0.35); /* Blue border */ + border-radius: 6px; + padding: 0.3rem 0.6rem; + box-shadow: 0 2px 4px rgba(52, 152, 219, 0.12), inset 0 -1px 0 rgba(52, 152, 219, 0.25); + white-space: nowrap; + text-align: center; + color: #3498db; /* Blue text */ + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.2rem; + transition: all 0.2s ease; + min-width: 2rem; +} + +/* Iconify icons inside kbd elements */ +.shortcut-keys kbd iconify-icon { + color: inherit; + vertical-align: middle; + display: inline-flex; +} + +.shortcut-item:hover .shortcut-keys kbd { + background: rgba(52, 152, 219, 0.15); + border-color: rgba(52, 152, 219, 0.5); + box-shadow: 0 2px 6px rgba(52, 152, 219, 0.25); +} + +.shortcut-desc { + flex: 1; + font-size: 0.95rem; + color: var(--text-gray); + line-height: 1.4; +} + +/* Mobile responsive */ +@media (max-width: 768px) { + #shortcuts-modal { + max-width: calc(100% - 2rem); + } + + #shortcuts-modal .info-modal-body { + grid-template-columns: 1fr; /* Single column on mobile */ + gap: 1.5rem; + } +} + +/* Tablet - 2 columns */ +@media (min-width: 769px) and (max-width: 1024px) { + #shortcuts-modal { + max-width: 700px; + } + + #shortcuts-modal .info-modal-body { + grid-template-columns: 1fr 1fr; /* 2 columns on tablet */ + gap: 1.2rem 1.5rem; + } + + .shortcuts-section-title { + font-size: 1rem; + } + + .shortcut-item { + flex-direction: column; + align-items: flex-start; + gap: 0.35rem; + } + + .shortcut-keys kbd { + font-size: 0.7rem; + padding: 0.2rem 0.4rem; + } + + .shortcut-desc { + font-size: 0.9rem; + } +} + +/* ======================================================================== + PDF DOWNLOAD MODAL STYLES + ======================================================================== */ + +/* PDF Modal Specific Overrides */ +.pdf-download-modal { + max-width: 900px; + width: calc(100% - 2rem); +} + +/* Modal Subtitle */ +.pdf-modal-subtitle { + font-size: 0.95rem; + color: var(--text-gray); + margin-top: 0.5rem; + font-weight: 400; +} + +/* PDF Options Grid */ +.pdf-options-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 24px; + margin: 2rem 0 1.5rem 0; +} + +/* PDF Option Card */ +.pdf-option-card { + border: 2px solid transparent; + border-radius: 12px; + padding: 16px; + cursor: pointer; + transition: all 250ms ease; + position: relative; + background: #ffffff; + display: flex; + flex-direction: column; + gap: 12px; +} + +.pdf-option-card:hover { + border-color: #e0e0e0; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + transform: translateY(-2px); +} + +.pdf-option-card:focus { + outline: 2px solid #4caf50; + outline-offset: 2px; +} + +/* Selected State */ +.pdf-option-card.selected { + border-color: #4caf50; + box-shadow: 0 6px 16px rgba(76, 175, 80, 0.2); + background: #f9fff9; +} + +/* PDF Thumbnail Container */ +.pdf-thumbnail { + background: #ffffff; + border: 1px solid #e0e0e0; + border-radius: 8px; + padding: 16px; + height: 280px; + display: flex; + flex-direction: column; + gap: 12px; + position: relative; + overflow: hidden; +} + +/* Skeleton Blocks inside Thumbnails */ +.pdf-thumbnail .skeleton-block { + background: linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 50%, #f0f0f0 75%); + background-size: 200% 100%; + animation: skeleton-shimmer 1.8s ease-in-out infinite; + border-radius: 4px; +} + +/* Custom Placeholder (for Custom CV card) */ +.custom-placeholder { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100%; + color: #999; + text-align: center; +} + +.custom-placeholder iconify-icon { + margin-bottom: 12px; + opacity: 0.5; +} + +.custom-placeholder p { + font-size: 0.9rem; + font-weight: 500; + color: #666; + margin: 0; +} + +/* Thumbnail Badge (Page Count / Coming Soon) */ +.thumbnail-badge { + position: absolute; + top: 8px; + right: 8px; + background: rgba(0, 0, 0, 0.75); + color: white; + font-size: 0.7rem; + font-weight: 600; + padding: 4px 8px; + border-radius: 4px; + letter-spacing: 0.5px; + text-transform: uppercase; +} + +/* PDF Option Info */ +.pdf-option-info { + text-align: center; +} + +.pdf-option-info h3 { + font-size: 1.1rem; + font-weight: 600; + color: var(--text-dark); + margin: 0 0 4px 0; +} + +.pdf-option-info p { + font-size: 0.875rem; + color: var(--text-gray); + margin: 0; + line-height: 1.4; +} + +/* PDF Option Badge (Checkmark) */ +.pdf-option-badge { + position: absolute; + top: 8px; + left: 8px; + opacity: 0; + transform: scale(0.8); + transition: all 250ms ease; + color: #4caf50; +} + +.pdf-option-card.selected .pdf-option-badge { + opacity: 1; + transform: scale(1); +} + +/* PDF Modal Footer */ +.pdf-modal-footer { + display: flex; + justify-content: center; + padding-top: 1rem; + border-top: 1px solid #e0e0e0; + margin-top: 0.5rem; +} + +/* PDF Download Button */ +.pdf-download-btn { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 12px 32px; + font-size: 1rem; + font-weight: 600; + border: none; + border-radius: 8px; + cursor: pointer; + transition: all 250ms ease; + font-family: inherit; +} + +.pdf-download-btn iconify-icon { + flex-shrink: 0; +} + +/* Disabled State */ +.pdf-download-btn:disabled { + background: #e0e0e0; + color: #999999; + cursor: not-allowed; + opacity: 0.6; +} + +/* Enabled State */ +.pdf-download-btn:not(:disabled) { + background: #4caf50; + color: white; +} + +.pdf-download-btn:not(:disabled):hover { + background: #45a049; + box-shadow: 0 4px 12px rgba(76, 175, 80, 0.3); + transform: translateY(-1px); +} + +.pdf-download-btn:not(:disabled):active { + transform: translateY(0); +} + +/* Screen Reader Only */ +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; +} + +/* ======================================================================== + RESPONSIVE DESIGN - PDF MODAL + ======================================================================== */ + +/* Tablet: Two columns */ +@media (min-width: 480px) and (max-width: 767px) { + .pdf-options-grid { + grid-template-columns: repeat(2, 1fr); + gap: 16px; + } + + /* Custom card spans full width */ + .pdf-option-card[data-cv-format="custom"] { + grid-column: 1 / -1; + } + + .pdf-thumbnail { + height: 220px; + } +} + +/* Mobile: Single column */ +@media (max-width: 479px) { + .pdf-download-modal { + max-width: calc(100% - 1rem); + } + + .pdf-options-grid { + display: flex; + flex-direction: column; + gap: 16px; + } + + .pdf-thumbnail { + height: 200px; + } + + .pdf-option-info h3 { + font-size: 1rem; + } + + .pdf-option-info p { + font-size: 0.8rem; + } + + .pdf-download-btn { + padding: 10px 24px; + font-size: 0.9rem; + } +} + +/* ======================================================================== + ACCESSIBILITY - REDUCED MOTION + ======================================================================== */ + +@media (prefers-reduced-motion: reduce) { + .pdf-thumbnail .skeleton-block { + animation: none; + background: #e8e8e8; + } + + .pdf-option-card { + transition: none; + } + + .pdf-option-badge { + transition: none; + } + + .pdf-download-btn { + transition: none; + } +} + +/* ======================================================================== + PRINT STYLES - PDF MODAL + ======================================================================== */ + +@media print { + .pdf-download-modal { + display: none !important; + } +} diff --git a/static/css/main.new.css b/static/css/main.new.css new file mode 100644 index 0000000..2e1c228 --- /dev/null +++ b/static/css/main.new.css @@ -0,0 +1,36 @@ +/* ============================================================================ + MAIN.CSS - Entry Point (New Modular Structure) + ============================================================================ */ + +/* 01 - Foundation */ +@import './01-foundation/_reset.css'; +@import './01-foundation/_variables.css'; +@import './01-foundation/_typography.css'; +@import './01-foundation/_themes.css'; + +/* 02 - Layout */ +@import './02-layout/_container.css'; +@import './02-layout/_page.css'; +@import './02-layout/_grid.css'; +@import './02-layout/_paper.css'; + +/* 03 - Components */ +@import './03-components/_action-bar.css'; +@import './03-components/_sidebar.css'; +@import './03-components/_cv-header.css'; +@import './03-components/_cv-section.css'; +@import './03-components/_experience.css'; +@import './03-components/_projects.css'; +@import './03-components/_courses.css'; +@import './03-components/_education.css'; +@import './03-components/_languages.css'; + +/* 04 - Interactive (includes hamburger, buttons, modals, zoom - TO BE SPLIT LATER) */ +@import './04-interactive/_toggles.css'; +@import './04-interactive/_remaining.css'; + +/* 06 - Effects */ +@import './06-effects/_skeleton.css'; + +/* 08 - Contexts */ +@import './08-contexts/_print.css'; diff --git a/static/hyperscript/toggles._hs b/static/hyperscript/toggles._hs index c09cba0..fb73519 100644 --- a/static/hyperscript/toggles._hs +++ b/static/hyperscript/toggles._hs @@ -55,17 +55,17 @@ end -- ============================================================================== def toggleTheme(isClean) - set body to document.body + set container to the first .cv-container set actionBarToggle to #themeToggle set menuToggle to #themeToggleMenu if isClean is true - add .theme-clean to body + add .theme-clean to container call localStorage.setItem('cv-theme', 'clean') if actionBarToggle exists then set actionBarToggle's checked to true end if menuToggle exists then set menuToggle's checked to true end else - remove .theme-clean from body + remove .theme-clean from container call localStorage.setItem('cv-theme', 'default') if actionBarToggle exists then set actionBarToggle's checked to false end if menuToggle exists then set menuToggle's checked to false end diff --git a/templates/index.html b/templates/index.html index f6759ce..e44b82d 100644 --- a/templates/index.html +++ b/templates/index.html @@ -71,12 +71,8 @@ - + - - - - diff --git a/templates/partials/modals/pdf-modal.html b/templates/partials/modals/pdf-modal.html index 4930abf..9a93508 100644 --- a/templates/partials/modals/pdf-modal.html +++ b/templates/partials/modals/pdf-modal.html @@ -15,6 +15,7 @@
+

{{if eq .Lang "es"}}Descargar PDF{{else}}Download PDF{{end}}

{{if eq .Lang "es"}}Elige tu formato preferido{{else}}Choose your preferred format{{end}} @@ -156,12 +157,12 @@

- +