/** * Component-Level Skeleton Loaders for Language Transitions * ========================================================== * Each CV component has dual-state structure: * - .actual-content (real CV content) * - .skeleton-content (gray pulsing placeholders) * * Loading state controlled via .loading class on component wrapper */ /* ======================================================================== BASE SKELETON STYLES ======================================================================== */ .skeleton { background: linear-gradient( 90deg, #f0f0f0 0%, #e8e8e8 20%, #f0f0f0 40%, #f0f0f0 100% ); background-size: 200% 100%; animation: skeleton-shimmer 1.8s ease-in-out infinite; border-radius: 4px; will-change: background-position; } @keyframes skeleton-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } } /* ======================================================================== COMPONENT WRAPPER STATE TOGGLING ======================================================================== */ /* Default state: Show actual content, hide skeleton */ .component-wrapper { position: relative; } .component-wrapper .actual-content { opacity: 1; transition: opacity 250ms ease-out; } .component-wrapper .skeleton-content { position: absolute; top: 0; left: 0; right: 0; opacity: 0; pointer-events: none; transition: opacity 250ms ease-out; } /* Loading state: Hide actual content, show skeleton */ /* Triggered by manual .loading class OR when parent page container has .loading */ .component-wrapper.loading .actual-content, .loading .component-wrapper .actual-content { opacity: 0; pointer-events: none; } .component-wrapper.loading .skeleton-content, .loading .component-wrapper .skeleton-content { opacity: 1; pointer-events: all; } /* ======================================================================== SKELETON SHAPE DEFINITIONS ======================================================================== */ /* Header Section Skeleton */ /* Matches actual header layout with photo absolutely positioned on right */ .skeleton-header { position: relative; padding-right: 185px; /* Match .cv-header-left padding */ min-height: 200px; /* Ensure space for photo */ } .skeleton-header-text { position: relative; z-index: 1; } .skeleton-name { height: 40px; /* Larger to match h1 */ width: 75%; margin-bottom: 12px; } .skeleton-experience-years { height: 24px; /* Larger subtitle */ width: 55%; margin-bottom: 24px; } .skeleton-photo { width: 150px; /* Match actual photo */ height: 200px; /* Match actual photo */ border-radius: 0; /* No border-radius on actual photo */ border: 3px solid #e8e8e8; /* Match photo border style */ /* Absolute positioning to match actual layout */ position: absolute; top: 15px; right: 15px; flex-shrink: 0; } .skeleton-intro { height: 90px; /* Taller for 3-4 lines of text */ width: 100%; margin-top: 12px; } /* Section Title Skeleton */ .skeleton-section-title { display: flex; align-items: center; gap: 8px; margin-bottom: 16px; } .skeleton-icon { width: 24px; height: 24px; border-radius: 4px; flex-shrink: 0; } .skeleton-title-text { height: 24px; width: 40%; } /* Skill Item Skeleton (Sidebar) */ .skeleton-skill-category { margin-bottom: 20px; } .skeleton-skill-title { height: 20px; width: 60%; margin-bottom: 12px; } .skeleton-skill-items { display: flex; flex-direction: column; gap: 8px; } .skeleton-skill-item { height: 32px; width: 100%; } .skeleton-skill-item:nth-child(2) { width: 85%; } .skeleton-skill-item:nth-child(3) { width: 90%; } .skeleton-skill-item:nth-child(4) { width: 75%; } /* Experience Entry Skeleton */ .skeleton-experience-item { display: flex; gap: 16px; margin-bottom: 24px; } .skeleton-company-logo { width: 60px; height: 60px; border-radius: 8px; flex-shrink: 0; } .skeleton-experience-content { flex: 1; display: flex; flex-direction: column; gap: 8px; } /* NEW: Structural skeleton lines for experience */ .skeleton-position-line { height: 20px; width: 80%; } .skeleton-date-line { height: 14px; width: 50%; } .skeleton-description-line { height: 16px; width: 100%; margin-top: 4px; } .skeleton-responsibility-line { height: 14px; width: 100%; margin-left: 16px; /* Indent like list items */ } /* Legacy styles (keeping for backward compatibility) */ .skeleton-position { height: 20px; width: 80%; } .skeleton-company-info { height: 16px; width: 60%; } .skeleton-description { height: 40px; width: 100%; margin-top: 4px; } .skeleton-description.short { width: 85%; } /* Section Skeleton Base */ .skeleton-section { padding: 16px 0; } .skeleton-section-title { height: 28px; width: 35%; margin-bottom: 20px; } /* Education Item Skeleton */ .skeleton-education-item { height: 48px; width: 100%; margin-bottom: 12px; } .skeleton-education-item:last-child { margin-bottom: 0; } /* Skills Summary Skeleton */ .skeleton-summary-paragraph { height: 18px; width: 100%; margin-bottom: 10px; } .skeleton-summary-paragraph:last-child { margin-bottom: 0; } /* Award Item Skeleton */ .skeleton-award-item { display: flex; gap: 16px; margin-bottom: 24px; } .skeleton-award-logo { width: 60px; height: 60px; border-radius: 8px; flex-shrink: 0; } .skeleton-award-content { flex: 1; display: flex; flex-direction: column; gap: 8px; } /* NEW: Structural skeleton lines for awards */ .skeleton-award-title-line { height: 20px; width: 70%; } .skeleton-award-info-line { height: 14px; width: 50%; } /* Legacy styles (keeping for backward compatibility) */ .skeleton-award-title { height: 20px; width: 70%; } .skeleton-award-info { height: 16px; width: 50%; } .skeleton-award-description { height: 40px; width: 100%; margin-top: 4px; } /* Project Item Skeleton */ .skeleton-project-item { display: flex; gap: 16px; margin-bottom: 24px; } .skeleton-project-icon { width: 80px; height: 80px; border-radius: 8px; flex-shrink: 0; } .skeleton-project-content { flex: 1; display: flex; flex-direction: column; gap: 8px; } /* NEW: Structural skeleton lines for projects */ .skeleton-project-title-line { height: 20px; width: 75%; } .skeleton-tech-line { height: 14px; width: 85%; margin-top: 4px; } .skeleton-footer-line { height: 16px; width: 70%; margin-top: 16px; } /* Legacy styles (keeping for backward compatibility) */ .skeleton-project-title { height: 20px; width: 75%; } .skeleton-project-info { height: 16px; width: 55%; } .skeleton-project-description { height: 40px; width: 100%; margin-top: 4px; } .skeleton-project-description.short { width: 80%; } /* Course Item Skeleton */ .skeleton-course-item { display: flex; gap: 16px; margin-bottom: 20px; } .skeleton-course-icon { width: 80px; height: 80px; border-radius: 8px; flex-shrink: 0; } .skeleton-course-content { flex: 1; display: flex; flex-direction: column; gap: 8px; } /* NEW: Structural skeleton lines for courses */ .skeleton-course-title-line { height: 18px; width: 70%; } .skeleton-course-info-line { height: 14px; width: 60%; } /* Legacy styles (keeping for backward compatibility) */ .skeleton-course-title { height: 18px; width: 70%; } .skeleton-course-info { height: 16px; width: 60%; } /* Language Item Skeleton */ .skeleton-language-item { height: 20px; width: 100%; margin-bottom: 12px; } .skeleton-language-item:last-child { margin-bottom: 0; } /* Reference Item Skeleton */ .skeleton-reference-item { height: 22px; width: 100%; margin-bottom: 10px; } .skeleton-reference-item:last-child { margin-bottom: 0; } /* Other Section Skeleton */ .skeleton-other-item { height: 20px; width: 60%; } /* Sidebar Skeleton */ .skeleton-sidebar { padding: 16px 0; } .skeleton-sidebar-header { height: 28px; width: 80%; margin-bottom: 20px; } /* Skill Item Skeleton (Sidebar) - Already defined above but keeping for reference */ /* Footer Skeleton */ .skeleton-footer { display: flex; flex-direction: column; gap: 12px; padding: 16px 0; } .skeleton-footer-item { height: 20px; width: 100%; } .skeleton-footer-item:nth-child(2) { width: 90%; } .skeleton-footer-item:nth-child(3) { width: 85%; } .skeleton-footer-item:nth-child(4) { width: 80%; } .skeleton-footer-item:nth-child(5) { width: 75%; } /* Text Block Skeletons (Generic) */ .skeleton-text { height: 16px; margin-bottom: 8px; } .skeleton-text.short { width: 60%; } .skeleton-text.medium { width: 80%; } .skeleton-text.long { width: 95%; } /* ======================================================================== RESPONSIVE ADJUSTMENTS ======================================================================== */ @media (max-width: 768px) { .skeleton-header { flex-direction: column; align-items: center; } .skeleton-header-text { text-align: center; width: 100%; } .skeleton-name, .skeleton-experience-years { width: 80%; margin-left: auto; margin-right: auto; } .skeleton-photo { width: 100px; height: 100px; border-radius: 8px; } .skeleton-experience-item { flex-direction: column; gap: 12px; } .skeleton-company-logo { width: 50px; height: 50px; } } /* ======================================================================== ACCESSIBILITY - REDUCED MOTION ======================================================================== */ @media (prefers-reduced-motion: reduce) { .skeleton { animation: none; background: #e8e8e8; } .component-wrapper .actual-content, .component-wrapper .skeleton-content { transition: none; } } /* ======================================================================== PRINT STYLES ======================================================================== */ @media print { .skeleton-content { display: none !important; } .component-wrapper .actual-content { opacity: 1 !important; } } /* ======================================================================== PERFORMANCE OPTIMIZATIONS ======================================================================== */ /* Force GPU acceleration for skeleton elements */ .skeleton { transform: translateZ(0); backface-visibility: hidden; } /* Contain layout/paint/style to prevent reflow */ .component-wrapper { contain: layout style; } /* Optimize skeleton rendering */ .skeleton-content { contain: layout paint; }