Task 6: Build skills section with circular SVG progress gauges

- Skills HTML/CSS/JS already built in prior iterations; this commit
  polishes: coral hover background for clinical skills, moves
  text-align:center to .section-heading class (removes inline style),
  confirms responsive gauge sizing at 480px
- 18 SVG circular gauges across 3 categories (Technical/Clinical/Strategic)
- Scroll-triggered IntersectionObserver animates stroke-dashoffset
  staggered by 100ms per gauge
- Clinical skills use coral color; technical/strategic use teal

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-09 11:05:08 +00:00
parent 2f48f1f1d3
commit 4940beb923
+316 -2
View File
@@ -239,6 +239,7 @@
font-weight: 700;
color: var(--heading);
margin-bottom: 32px;
text-align: center;
}
/* =========================================
@@ -339,6 +340,81 @@
margin-top: 4px;
}
/* =========================================
SKILLS SECTION
========================================= */
.skills-category {
margin-bottom: 40px;
}
.skills-category:last-child {
margin-bottom: 0;
}
.skills-cat-label {
font-family: var(--font-secondary);
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--muted);
margin-bottom: 20px;
padding-left: 4px;
}
.skills-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 24px;
}
.skill-item {
display: flex;
flex-direction: column;
align-items: center;
padding: 16px;
border-radius: var(--radius);
transition: background 0.3s ease;
}
.skill-item:hover {
background: var(--teal-light);
}
.skill-item[data-color="coral"]:hover {
background: var(--coral-light);
}
.skill-gauge {
display: block;
}
.skill-progress {
stroke-dasharray: 213.628;
stroke-dashoffset: 213.628;
transition: stroke-dashoffset 1.2s ease-out;
}
.skill-name {
font-family: var(--font-primary);
font-size: 12px;
font-weight: 600;
color: var(--heading);
margin-top: 8px;
text-align: center;
line-height: 1.3;
}
.skill-cat {
font-family: var(--font-secondary);
font-size: 10px;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.04em;
margin-top: 2px;
}
/* =========================================
RESPONSIVE: 768px
========================================= */
@@ -365,6 +441,10 @@
display: grid;
grid-template-columns: repeat(2, 1fr);
}
.skills-grid {
grid-template-columns: repeat(3, 1fr);
}
}
/* =========================================
@@ -393,6 +473,20 @@
display: grid;
grid-template-columns: 1fr;
}
.skills-grid {
grid-template-columns: repeat(2, 1fr);
gap: 16px;
}
.skill-gauge {
width: 64px;
height: 64px;
}
.skill-item {
padding: 12px;
}
}
</style>
</head>
@@ -449,7 +543,187 @@
</section>
<section id="skills">
<!-- Task 6: Skills with circular SVG progress gauges -->
<h2 class="section-heading">Skills &amp; Expertise</h2>
<div class="skills-category">
<h3 class="skills-cat-label">Technical</h3>
<div class="skills-grid">
<div class="skill-item" data-level="90" data-color="teal">
<svg class="skill-gauge" width="80" height="80" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke="var(--border)" stroke-width="5"/>
<circle class="skill-progress" cx="40" cy="40" r="34" fill="none" stroke="var(--teal)" stroke-width="5" stroke-linecap="round" transform="rotate(-90, 40, 40)"/>
<text x="40" y="40" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="600" fill="var(--heading)" font-family="var(--font-secondary)">90%</text>
</svg>
<span class="skill-name">Python</span>
<span class="skill-cat">Technical</span>
</div>
<div class="skill-item" data-level="88" data-color="teal">
<svg class="skill-gauge" width="80" height="80" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke="var(--border)" stroke-width="5"/>
<circle class="skill-progress" cx="40" cy="40" r="34" fill="none" stroke="var(--teal)" stroke-width="5" stroke-linecap="round" transform="rotate(-90, 40, 40)"/>
<text x="40" y="40" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="600" fill="var(--heading)" font-family="var(--font-secondary)">88%</text>
</svg>
<span class="skill-name">SQL</span>
<span class="skill-cat">Technical</span>
</div>
<div class="skill-item" data-level="92" data-color="teal">
<svg class="skill-gauge" width="80" height="80" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke="var(--border)" stroke-width="5"/>
<circle class="skill-progress" cx="40" cy="40" r="34" fill="none" stroke="var(--teal)" stroke-width="5" stroke-linecap="round" transform="rotate(-90, 40, 40)"/>
<text x="40" y="40" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="600" fill="var(--heading)" font-family="var(--font-secondary)">92%</text>
</svg>
<span class="skill-name">Power BI</span>
<span class="skill-cat">Technical</span>
</div>
<div class="skill-item" data-level="70" data-color="teal">
<svg class="skill-gauge" width="80" height="80" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke="var(--border)" stroke-width="5"/>
<circle class="skill-progress" cx="40" cy="40" r="34" fill="none" stroke="var(--teal)" stroke-width="5" stroke-linecap="round" transform="rotate(-90, 40, 40)"/>
<text x="40" y="40" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="600" fill="var(--heading)" font-family="var(--font-secondary)">70%</text>
</svg>
<span class="skill-name">JS / TS</span>
<span class="skill-cat">Technical</span>
</div>
<div class="skill-item" data-level="95" data-color="teal">
<svg class="skill-gauge" width="80" height="80" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke="var(--border)" stroke-width="5"/>
<circle class="skill-progress" cx="40" cy="40" r="34" fill="none" stroke="var(--teal)" stroke-width="5" stroke-linecap="round" transform="rotate(-90, 40, 40)"/>
<text x="40" y="40" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="600" fill="var(--heading)" font-family="var(--font-secondary)">95%</text>
</svg>
<span class="skill-name">Data Analysis</span>
<span class="skill-cat">Technical</span>
</div>
<div class="skill-item" data-level="88" data-color="teal">
<svg class="skill-gauge" width="80" height="80" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke="var(--border)" stroke-width="5"/>
<circle class="skill-progress" cx="40" cy="40" r="34" fill="none" stroke="var(--teal)" stroke-width="5" stroke-linecap="round" transform="rotate(-90, 40, 40)"/>
<text x="40" y="40" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="600" fill="var(--heading)" font-family="var(--font-secondary)">88%</text>
</svg>
<span class="skill-name">Dashboard Dev</span>
<span class="skill-cat">Technical</span>
</div>
<div class="skill-item" data-level="82" data-color="teal">
<svg class="skill-gauge" width="80" height="80" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke="var(--border)" stroke-width="5"/>
<circle class="skill-progress" cx="40" cy="40" r="34" fill="none" stroke="var(--teal)" stroke-width="5" stroke-linecap="round" transform="rotate(-90, 40, 40)"/>
<text x="40" y="40" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="600" fill="var(--heading)" font-family="var(--font-secondary)">82%</text>
</svg>
<span class="skill-name">Algorithm Design</span>
<span class="skill-cat">Technical</span>
</div>
<div class="skill-item" data-level="80" data-color="teal">
<svg class="skill-gauge" width="80" height="80" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke="var(--border)" stroke-width="5"/>
<circle class="skill-progress" cx="40" cy="40" r="34" fill="none" stroke="var(--teal)" stroke-width="5" stroke-linecap="round" transform="rotate(-90, 40, 40)"/>
<text x="40" y="40" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="600" fill="var(--heading)" font-family="var(--font-secondary)">80%</text>
</svg>
<span class="skill-name">Data Pipelines</span>
<span class="skill-cat">Technical</span>
</div>
</div>
</div>
<div class="skills-category">
<h3 class="skills-cat-label">Clinical</h3>
<div class="skills-grid">
<div class="skill-item" data-level="95" data-color="coral">
<svg class="skill-gauge" width="80" height="80" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke="var(--border)" stroke-width="5"/>
<circle class="skill-progress" cx="40" cy="40" r="34" fill="none" stroke="var(--coral)" stroke-width="5" stroke-linecap="round" transform="rotate(-90, 40, 40)"/>
<text x="40" y="40" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="600" fill="var(--heading)" font-family="var(--font-secondary)">95%</text>
</svg>
<span class="skill-name">Medicines Optimisation</span>
<span class="skill-cat">Clinical</span>
</div>
<div class="skill-item" data-level="90" data-color="coral">
<svg class="skill-gauge" width="80" height="80" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke="var(--border)" stroke-width="5"/>
<circle class="skill-progress" cx="40" cy="40" r="34" fill="none" stroke="var(--coral)" stroke-width="5" stroke-linecap="round" transform="rotate(-90, 40, 40)"/>
<text x="40" y="40" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="600" fill="var(--heading)" font-family="var(--font-secondary)">90%</text>
</svg>
<span class="skill-name">Pop. Health Analytics</span>
<span class="skill-cat">Clinical</span>
</div>
<div class="skill-item" data-level="85" data-color="coral">
<svg class="skill-gauge" width="80" height="80" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke="var(--border)" stroke-width="5"/>
<circle class="skill-progress" cx="40" cy="40" r="34" fill="none" stroke="var(--coral)" stroke-width="5" stroke-linecap="round" transform="rotate(-90, 40, 40)"/>
<text x="40" y="40" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="600" fill="var(--heading)" font-family="var(--font-secondary)">85%</text>
</svg>
<span class="skill-name">NICE TA</span>
<span class="skill-cat">Clinical</span>
</div>
<div class="skill-item" data-level="80" data-color="coral">
<svg class="skill-gauge" width="80" height="80" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke="var(--border)" stroke-width="5"/>
<circle class="skill-progress" cx="40" cy="40" r="34" fill="none" stroke="var(--coral)" stroke-width="5" stroke-linecap="round" transform="rotate(-90, 40, 40)"/>
<text x="40" y="40" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="600" fill="var(--heading)" font-family="var(--font-secondary)">80%</text>
</svg>
<span class="skill-name">Health Economics</span>
<span class="skill-cat">Clinical</span>
</div>
<div class="skill-item" data-level="82" data-color="coral">
<svg class="skill-gauge" width="80" height="80" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke="var(--border)" stroke-width="5"/>
<circle class="skill-progress" cx="40" cy="40" r="34" fill="none" stroke="var(--coral)" stroke-width="5" stroke-linecap="round" transform="rotate(-90, 40, 40)"/>
<text x="40" y="40" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="600" fill="var(--heading)" font-family="var(--font-secondary)">82%</text>
</svg>
<span class="skill-name">Clinical Pathways</span>
<span class="skill-cat">Clinical</span>
</div>
<div class="skill-item" data-level="88" data-color="coral">
<svg class="skill-gauge" width="80" height="80" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke="var(--border)" stroke-width="5"/>
<circle class="skill-progress" cx="40" cy="40" r="34" fill="none" stroke="var(--coral)" stroke-width="5" stroke-linecap="round" transform="rotate(-90, 40, 40)"/>
<text x="40" y="40" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="600" fill="var(--heading)" font-family="var(--font-secondary)">88%</text>
</svg>
<span class="skill-name">CD Assurance</span>
<span class="skill-cat">Clinical</span>
</div>
</div>
</div>
<div class="skills-category">
<h3 class="skills-cat-label">Strategic</h3>
<div class="skills-grid">
<div class="skill-item" data-level="90" data-color="teal">
<svg class="skill-gauge" width="80" height="80" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke="var(--border)" stroke-width="5"/>
<circle class="skill-progress" cx="40" cy="40" r="34" fill="none" stroke="var(--teal)" stroke-width="5" stroke-linecap="round" transform="rotate(-90, 40, 40)"/>
<text x="40" y="40" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="600" fill="var(--heading)" font-family="var(--font-secondary)">90%</text>
</svg>
<span class="skill-name">Budget Mgmt</span>
<span class="skill-cat">Strategic</span>
</div>
<div class="skill-item" data-level="88" data-color="teal">
<svg class="skill-gauge" width="80" height="80" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke="var(--border)" stroke-width="5"/>
<circle class="skill-progress" cx="40" cy="40" r="34" fill="none" stroke="var(--teal)" stroke-width="5" stroke-linecap="round" transform="rotate(-90, 40, 40)"/>
<text x="40" y="40" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="600" fill="var(--heading)" font-family="var(--font-secondary)">88%</text>
</svg>
<span class="skill-name">Stakeholder Engagement</span>
<span class="skill-cat">Strategic</span>
</div>
<div class="skill-item" data-level="85" data-color="teal">
<svg class="skill-gauge" width="80" height="80" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke="var(--border)" stroke-width="5"/>
<circle class="skill-progress" cx="40" cy="40" r="34" fill="none" stroke="var(--teal)" stroke-width="5" stroke-linecap="round" transform="rotate(-90, 40, 40)"/>
<text x="40" y="40" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="600" fill="var(--heading)" font-family="var(--font-secondary)">85%</text>
</svg>
<span class="skill-name">Pharma Negotiation</span>
<span class="skill-cat">Strategic</span>
</div>
<div class="skill-item" data-level="82" data-color="teal">
<svg class="skill-gauge" width="80" height="80" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke="var(--border)" stroke-width="5"/>
<circle class="skill-progress" cx="40" cy="40" r="34" fill="none" stroke="var(--teal)" stroke-width="5" stroke-linecap="round" transform="rotate(-90, 40, 40)"/>
<text x="40" y="40" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="600" fill="var(--heading)" font-family="var(--font-secondary)">82%</text>
</svg>
<span class="skill-name">Team Development</span>
<span class="skill-cat">Strategic</span>
</div>
</div>
</div>
</section>
<section id="experience">
@@ -869,8 +1143,9 @@
var cvContent = document.getElementById('cv-content');
cvContent.classList.add('revealed');
// Initialize nav tracking and smooth scroll after reveal
// Initialize nav tracking, smooth scroll, and skill gauges after reveal
initNavTracking();
initSkillGauges();
}, 500);
}
@@ -920,6 +1195,45 @@
});
}
/* =========================================
SKILL GAUGES: Scroll-triggered animation
========================================= */
function initSkillGauges() {
var skillsSection = document.getElementById('skills');
if (!skillsSection) return;
var skillItems = skillsSection.querySelectorAll('.skill-item');
var circumference = 2 * Math.PI * 34; // ~213.628
var animated = false;
var gaugeObserver = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting && !animated) {
animated = true;
gaugeObserver.unobserve(entry.target);
skillItems.forEach(function(item, index) {
var level = parseInt(item.getAttribute('data-level'), 10);
var progressCircle = item.querySelector('.skill-progress');
if (!progressCircle) return;
var targetOffset = circumference * (1 - level / 100);
// Stagger each gauge by 100ms
setTimeout(function() {
progressCircle.style.strokeDashoffset = targetOffset;
}, index * 100);
});
}
});
}, {
threshold: 0.15
});
gaugeObserver.observe(skillsSection);
}
})();
</script>
</body>