Files
cv-site/static/css/main.css
T
juanatsap e572af0771 feat: implement dynamic date calculation for projects
- Remove hardcoded startDate from La Porra project
- Add gitRepoUrl field to Project struct for dynamic date fetching
- Implement backend logic to fetch first commit date from git repositories
- Add processProjectDates function to calculate dates dynamically
- Update template to display computed dates and dynamic "Present/Presente"
- Add support for both static and git-based project start dates

When a project has a gitRepoUrl, the system automatically fetches the first
commit date from the repository. For current projects, it displays
"Present" (English) or "Presente" (Spanish) dynamically from the backend.

The La Porra project now uses git repository path for date calculation
instead of hardcoded JSON values.
2025-11-09 02:43:40 +00:00

2103 lines
41 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);
color: rgb(41, 43, 44);
line-height: 1.5;
font-size: 16px;
font-weight: 400;
}
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-icon {
color: #fff;
flex-shrink: 0;
display: inline-flex;
align-items: center;
justify-content: center;
height: 36px;
padding: 0 .5rem 0 1.5rem;
}
/* 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: rgba(255,255,255,0.1);
border-radius: 15px;
padding: 0 6px;
transition: all 0.3s ease;
}
.icon-toggle-slider::before {
content: '';
position: absolute;
width: 24px;
height: 24px;
left: 3px;
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(45px);
}
.icon-toggle input:checked + .icon-toggle-slider {
background: #27ae60;
}
.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: 8px;
}
.icon-toggle-slider .icon-right {
right: 7px;
}
.icon-toggle input:not(:checked) + .icon-toggle-slider .icon-left {
color: #333;
}
.icon-toggle input:not(:checked) + .icon-toggle-slider .icon-right {
color: rgba(255,255,255,0.3);
}
.icon-toggle input:checked + .icon-toggle-slider .icon-left {
color: rgba(255,255,255,0.3);
}
.icon-toggle input:checked + .icon-toggle-slider .icon-right {
color: #333;
}
.icon-toggle input:focus + .icon-toggle-slider {
box-shadow: 0 0 0 3px rgba(39, 174, 96, 0.2);
}
/* Language selector - matching action button style */
.language-selector {
display: inline-flex;
gap: 0;
padding: 0;
padding-left: 3rem; /* Add left space to prevent overlap with site title */
margin-right: 2rem; /* Add space to prevent overlap with Length toggle */
background: transparent;
border-radius: 0;
height: 100%;
align-items: stretch;
}
.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;
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;
}
.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;
}
.action-btn iconify-icon {
color: white;
}
.action-btn:hover {
background: #ddd;
color: #333;
text-decoration: none;
}
.action-btn:hover iconify-icon {
color: #27ae60;
}
/* Print Friendly button - transparent by default, green on hover */
.print-btn {
background: transparent;
}
.print-btn:hover {
background: #27ae60;
color: white;
}
.print-btn:hover iconify-icon {
color: white;
}
/* 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;
}
/* Loading Indicator */
.htmx-indicator {
display: none;
}
.htmx-indicator.htmx-request {
display: inline-block;
}
.loader {
border: 2px solid #f3f3f3;
border-top: 2px solid white;
border-radius: 50%;
width: 20px;
height: 20px;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 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 !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 */
}
/* 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: 2rem 1.5rem;
font-size: 0.9rem;
}
.sidebar-section {
margin-bottom: 2rem;
}
.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);
}
.sidebar-content {
font-family: 'Quicksand', sans-serif;
font-size: 0.95em;
font-weight: 400;
line-height: 1.5;
}
.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;
}
/* 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;
}
.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);
/* Colocación a manopla de la foto :) */
margin: 15px;
{{/* top: 25px; */}}
position: relative;
right: 5px;
}
.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;
}
.section-title {
font-family: 'Quicksand', sans-serif;
font-size: 1.3em;
font-weight: 500;
line-height: 1.2em;
margin: 20px 0 25px 0;
padding: 0;
color: rgb(51, 51, 51);
}
.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;
}
.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.9rem;
line-height: 1.6;
margin-top: 0.5rem;
}
.responsibilities {
list-style: none;
margin-top: 0.5rem;
padding-left: 0;
}
.responsibilities li {
padding-left: 1.2rem;
margin-bottom: 0.4rem;
position: relative;
font-size: 0.9rem;
color: var(--text-dark);
line-height: 1.5;
}
.responsibilities li:before {
content: "•";
position: absolute;
left: 0;
color: var(--text-gray);
}
/* Responsibilities with company logos (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.9rem;
line-height: 1.6;
color: var(--text-dark);
}
/* Languages */
.languages-list {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
}
.language-item {
font-size: 1.1rem!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;
}
.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.9rem;
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.95em;
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: 1.1rem!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;
}
/* 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;
}
.cv-photo {
width: 120px;
height: 150px;
}
.action-bar-content {
grid-template-columns: 1fr;
gap: 1rem;
padding: 1rem;
}
.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;
}
.intro-text {
font-size: 0.9em;
margin-top: 15px;
}
}
.no-print {}
/* Smooth Transitions for HTMX Swaps */
.cv-paper {
transition: opacity 200ms ease-in-out;
}
.cv-paper.htmx-swapping {
opacity: 0;
}
.cv-paper.htmx-settling {
opacity: 1;
}
/* 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: flex;
align-items: center;
gap: 1rem;
max-width: 400px;
z-index: 1000;
animation: slideIn 0.3s ease-out;
font-size: 0.95rem;
}
@keyframes slideIn {
from {
transform: translateX(120%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
.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 - TWO-PAGE LAYOUT
=============================================== */
@media print {
body {
background: white;
margin: 0;
padding: 0;
}
.action-bar {
display: none !important;
}
.cv-page {
box-shadow: none;
border: none;
margin: 0 auto;
transform: scale(1);
max-width: 100%;
page-break-after: always;
page-break-inside: avoid;
}
.cv-page.page-2 {
page-break-after: auto;
}
.page-content {
page-break-inside: avoid;
}
.cv-section {
page-break-inside: avoid;
}
/* Ensure footer only on page 2 */
.page-1 .cv-footer {
display: none !important;
}
.cv-footer {
page-break-inside: avoid;
background: #ddd !important;
color: #333 !important;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
a {
text-decoration: none;
font-weight: 800;
color: inherit;
}
/* Set up proper A4 page dimensions */
@page {
size: A4 portrait;
margin: 0.5in;
}
}
/* ===============================================
SECTION STYLES FOR PAGE 2
=============================================== */
.award-item,
.course-item,
.language-item,
.reference-item,
.other-content {
margin-bottom: 0!important;
line-height: 1.4!important;
margin-left: 2rem!important;
font-size: 1.1rem!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: 2px solid #ddd;
page-break-inside: avoid;
transition: gap 0.3s ease-in-out;
}
/* Keep border on all award items including last one */
/* ========================================
HIDE LOGOS, ICONS, AND BADGES MODE
======================================== */
/* Adjust gap when logos are hidden */
.cv-paper:not(.show-logos) .award-item {
gap: 0;
}
/* Hide all logos when .show-logos is not present */
.cv-paper:not(.show-logos) .company-logo,
.cv-paper:not(.show-logos) .award-logo,
.cv-paper:not(.show-logos) .project-icon,
.cv-paper:not(.show-logos) .course-icon {
display: none !important;
}
/* Hide logos inside responsibilities (Drolosoft sub-clients, Third Party projects) */
.cv-paper:not(.show-logos) .responsibilities li img,
.cv-paper:not(.show-logos) .responsibilities li iconify-icon.default-company-icon {
display: none !important;
}
/* Adjust layout for responsibilities without logos */
.cv-paper:not(.show-logos) .responsibilities li:has(img),
.cv-paper:not(.show-logos) .responsibilities li:has(iconify-icon) {
display: block !important;
grid-template-columns: none !important;
padding-left: 1.2rem !important;
}
/* Restore bullet points for responsibilities without logos */
.cv-paper:not(.show-logos) .responsibilities li:has(img):before,
.cv-paper:not(.show-logos) .responsibilities li:has(iconify-icon):before {
display: block !important;
}
/* Hide all section icons */
.cv-paper:not(.show-logos) .section-icon {
display: none !important;
}
/* Hide all badges (Current, Expired, Maintained By) */
.cv-paper:not(.show-logos) .current-badge,
.cv-paper:not(.show-logos) .expired-badge,
.cv-paper:not(.show-logos) .maintained-badge {
display: none !important;
}
/* Adjust experience items layout when logos are hidden */
.cv-paper:not(.show-logos) .experience-item {
display: block !important;
}
/* Adjust project and course items layout when icons are hidden */
.cv-paper:not(.show-logos) .project-item,
.cv-paper:not(.show-logos) .course-item,
.cv-paper:not(.show-logos) .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.95em;
}
.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: 1rem;
transform: scale(1);
}
/* Stack layout on mobile */
.page-1 .page-content,
.page-2 .page-content {
grid-template-columns: 1fr;
}
.cv-sidebar-left,
.cv-sidebar-right {
grid-column: 1;
}
.page-1 .cv-main,
.page-2 .cv-main {
grid-column: 1;
}
/* Hide header on page 2 for mobile to merge pages */
.page-2 .cv-title-badges-header {
display: none;
}
/* Adjust footer for mobile */
.footer-content li > div {
display: block;
margin: 0;
text-align: center;
width: 100%;
}
.footer-label {
font-size: 1em;
margin-top: 15px;
color: #777;
}
.footer-separator {
display: none;
}
.footer-value {
font-size: 1.5em;
margin-bottom: 0;
padding: 0;
}
}
/* ===============================================
TABLET RESPONSIVE
=============================================== */
@media (max-width: 768px) and (min-width: 577px) {
.page-content {
gap: 1rem;
}
.footer-label {
font-size: 1.2em;
}
.footer-value {
font-size: 1em;
}
}
/* 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;
}
.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: calc(100vh - 50px);
background: #ffffff;
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.15);
transform: translateX(-100%);
transition: transform 0.3s ease-in-out;
overflow-y: auto;
z-index: 99;
}
.navigation-menu.menu-open {
transform: translateX(0);
}
.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);
}
/* 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;
}
}
/* 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.9;
}
.back-to-top:hover {
opacity: 1;
transform: translateY(-3px);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
background: #3a3a3a;
}
.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;
}
}
/* ========================================
Desktop: Ensure Sidebar Content Visible (>1280px)
======================================== */
/* ========================================
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;
}
.experience-item h3,
.project-item h3 {
font-size: 1rem;
}
.experience-item p,
.project-item p,
.experience-item li,
.project-item li {
font-size: 0.85rem;
}
/* ========== 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;
}
}