feat(site): add engaging interactions (typewriter, progress, skills, particles, testimonials)

Ultraworked with Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-02-11 20:34:03 -05:00
parent ec591a9f95
commit 31eb93e01b
3 changed files with 431 additions and 38 deletions

View File

@@ -219,16 +219,209 @@ footer {
.btn-primary {
background-color: var(--color-primary);
border-color: var(--color-primary);
color: white; /* Electric blue needs white text for contrast */
color: white;
font-weight: 700;
text-transform: uppercase;
font-size: 0.85rem;
letter-spacing: 0.05em;
padding: 0.6em 1.2em;
border-radius: 50px; /* Pill shape */
border-radius: 50px;
&:hover, &:focus, &:active {
background-color: color-mix(in srgb, var(--color-primary), black 10%) !important;
border-color: color-mix(in srgb, var(--color-primary), black 10%) !important;
}
}
/* ===== SCROLL PROGRESS BAR ===== */
.scroll-progress {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 4px;
background: linear-gradient(
to right,
var(--color-primary) 0%,
var(--color-primary) var(--scroll-progress, 0%),
transparent var(--scroll-progress, 0%)
);
z-index: 9999;
transition: none;
}
/* ===== PARTICLE CANVAS ===== */
#particles {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: -1;
opacity: 0.6;
}
/* ===== TYPEWRITER EFFECT ===== */
.typewriter {
opacity: 0;
transition: opacity 0.3s;
position: relative;
display: inline-block;
}
.typewriter::after {
content: '|';
position: absolute;
right: -8px;
animation: blink 0.7s infinite;
color: var(--color-secondary);
}
@keyframes blink {
0%, 50% { opacity: 1; }
51%, 100% { opacity: 0; }
}
/* ===== ANIMATED SKILL BARS ===== */
.skill-bars {
--bs-list-group-bg: transparent;
}
.skill-item {
display: flex;
flex-direction: column;
gap: 0.5rem;
padding: 1.25rem;
border-left: 4px solid transparent;
transition: border-color 0.3s, background-color 0.3s;
}
.skill-item:hover {
border-left-color: var(--color-secondary);
}
.skill-name {
font-weight: 600;
font-size: 1rem;
color: var(--text-body);
}
.skill-bar-track {
width: 100%;
height: 8px;
background: color-mix(in srgb, var(--color-coffee-medium), transparent 85%);
border-radius: 50px;
overflow: hidden;
position: relative;
}
.skill-bar-fill {
height: 100%;
width: 0;
background: linear-gradient(90deg, var(--color-primary), var(--color-secondary));
border-radius: 50px;
transition: width 1.5s cubic-bezier(0.65, 0, 0.35, 1);
position: relative;
overflow: hidden;
}
.skill-bar-fill::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(
90deg,
transparent,
rgba(255, 255, 255, 0.3),
transparent
);
animation: shimmer 2s infinite;
}
@keyframes shimmer {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
.skill-item.animate .skill-bar-fill {
width: var(--skill-level);
}
/* ===== INTERACTIVE TESTIMONIALS ===== */
.testimonial-card {
position: relative;
overflow: visible;
}
.testimonial-full {
display: none;
}
.testimonial-excerpt {
display: block;
}
.testimonial-card.expanded .testimonial-excerpt {
display: none;
}
.testimonial-card.expanded .testimonial-full {
display: block;
}
.testimonial-author {
font-weight: 600;
font-style: italic;
color: var(--color-coffee-medium);
margin-top: 1rem;
margin-bottom: 0;
}
.testimonial-toggle {
margin-top: 1rem;
background: var(--color-secondary);
color: var(--color-coffee-dark);
border: none;
padding: 0.5rem 1.5rem;
border-radius: 50px;
font-weight: 700;
font-size: 0.85rem;
cursor: pointer;
text-transform: uppercase;
letter-spacing: 0.05em;
transition: transform 0.2s, background-color 0.2s;
}
.testimonial-toggle:hover {
background: var(--color-primary);
color: white;
transform: translateY(-2px);
}
.testimonial-toggle:active {
transform: translateY(0);
}
/* ===== REDUCED MOTION SUPPORT ===== */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
.typewriter::after {
animation: none;
}
.skill-bar-fill::after {
animation: none;
}
}