Files
cv-site/static/css/main.css
T
juanatsap f87a1a5c28 fix: implement complete hover synchronization for PDF/Print buttons
CRITICAL BUG FIX: Hover states now sync between action bar and hamburger menu

Changes:
1. Added mouseenter/mouseleave handlers to menu PDF button
   - templates/partials/navigation/hamburger-menu.html:178-181
   - Added .menu-pdf-btn class for targeting
   - Added hyperscript hover sync events

2. Updated syncPdfHover() function
   - static/js/cv-functions.js:71-82
   - Now selects both .pdf-btn and .menu-pdf-btn
   - Both buttons get .pdf-hover-sync class on hover

3. Updated syncPrintHover() function
   - static/js/cv-functions.js:88-99
   - Now selects both .print-btn and .menu-print-btn
   - Both buttons get .print-hover-sync class on hover

4. Added CSS for menu PDF button hover sync
   - static/css/main.css:2690-2700
   - .menu-pdf-btn.pdf-hover-sync styling (white bg, red icon)
   - Matches action bar PDF button hover state

5. Created comprehensive hover sync test
   - tests/mjs/8-hover-sync.test.mjs
   - Tests all 4 hover scenarios (bar→menu, menu→bar for both buttons)
   - Validates event handlers and CSS class application
   - Manual verification instructions included

Behavior now correct:
 Hovering action bar PDF button highlights menu PDF button
 Hovering action bar Print button highlights menu Print button
 Hovering menu PDF button highlights action bar PDF button
 Hovering menu Print button highlights action bar Print button

Fixes documented bug from PROJECT-MEMORY.md Section 3.
2025-11-17 14:35:32 +00:00

4368 lines
95 KiB
CSS

/* 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(--bg-gray);
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: rgb(41, 43, 44);
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(--black-bar);
color: white;
position: sticky;
top: 0;
z-index: 100;
box-shadow: 0 2px 5px rgba(0,0,0,0.3);
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;
font-weight: bold;
}
.icon-toggle input:not(:checked) + .icon-toggle-slider .icon-right {
color: #999;
opacity: 0.5;
}
.icon-toggle input:checked + .icon-toggle-slider .icon-left {
color: rgba(255,255,255,0.4);
opacity: 0.5;
}
.icon-toggle input:checked + .icon-toggle-slider .icon-right {
color: #333;
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: 2px 2px 9px rgba(0,0,0,0.5);
border: 1px solid #333;
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-white);
max-width: 1200px;
margin: 2rem auto;
box-shadow: 2px 2px 9px rgba(0,0,0,0.5);
border: 1px solid #333;
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 all buttons on mobile */
.download-btn,
.print-friendly-btn,
.shortcuts-btn,
.info-button,
.back-to-top {
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;
}
/* Flexbox container behavior - buttons arrange themselves */
/* Buttons will be positioned using JavaScript or individual positioning */
/* For now, use fixed spacing from center */
/* 4 buttons: Download, Print, Shortcuts, Info */
/* Spacing: 10px gap between buttons, centered horizontally */
/* Total width: 4 * 50px + 3 * 10px = 230px */
/* Start position: 50% - 115px */
.download-btn {
left: calc(50% - 115px) !important; /* First button: center - (230px/2) */
}
.print-friendly-btn {
left: calc(50% - 55px) !important; /* Second button: center - (230px/2) + 50px + 10px */
}
.shortcuts-btn {
left: calc(50% + 5px) !important; /* Third button: center - (230px/2) + 110px + 20px */
}
.info-button {
left: calc(50% + 65px) !important; /* Fourth button: center - (230px/2) + 170px + 30px */
}
/* Hover effects - only Y transform */
.download-btn:hover,
.download-btn.pdf-hover-sync,
.print-friendly-btn:hover,
.print-friendly-btn.print-hover-sync,
.shortcuts-btn:hover,
.info-button:hover {
transform: translateY(-3px) !important;
opacity: 1 !important;
}
/* Keep at-bottom state without transform */
.info-button.at-bottom,
.shortcuts-btn.at-bottom {
opacity: 1 !important;
transform: none !important;
}
}
/* ========================================
Info Modal - Modern Glassmorphism Design
======================================== */
/* Native <dialog> 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 */
}
/* 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 (above shortcuts) */
.print-friendly-btn {
position: fixed;
bottom: 14rem; /* Above zoom button */
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 */
}
/* Download Button (above print-friendly) */
.download-btn {
position: fixed;
bottom: 18rem; /* Above print-friendly button */
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 */
}
/* 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;
}
}