# Progress Log

## Codebase Patterns
- Single self-contained HTML file. All CSS in a single `<style>` tag. All JS in a single `<script>` tag wrapped in an IIFE with 'use strict'.
- No frameworks, no build step. Only external dependency: Google Fonts via <link> tags.
- Boot sequence is shared: pure black #000 bg, Fira Code font, blinking green cursor (#00ff41, step-end animation), boot text typed line by line (~220ms apart), [OK] lines bright green bold, SYSTEM/USER/ROLE/LOCATION labels cyan #00e5ff, values bright green, other lines dim green #3a6b45.
- CV data source: Use the expanded CV_v4.md content. Key roles: Interim Head (May-Nov 2025), Deputy Head (Jul 2024-Present), High-Cost Drugs Pharmacist (May 2022-Jul 2024), Pharmacy Manager Tesco (Nov 2017-May 2022), Duty Pharmacy Manager Tesco (Aug 2016-Nov 2017).
- Use IntersectionObserver for scroll animations (not scroll event listeners).
- For smooth scroll on nav clicks: preventDefault, calculate offset, window.scrollTo with behavior:'smooth'.
- Output HTML file name convention: 4-vitals-monitor.html.
- ECG PQRST waveform shape: flat -> small P bump -> flat -> sharp Q dip -> tall R spike -> S dip -> flat -> gentle T wave -> flat.
- Use SVG paths with stroke-dasharray/stroke-dashoffset for line drawing animations.
- SVG circle skill gauges: circumference = 2*PI*r. stroke-dashoffset = circumference * (1 - level/100). rotate(-90deg) to start from top.
- Google Fonts: Plus Jakarta Sans, Inter Tight.
- Floating pill nav: NOT full width. max-width 600px, margin: 12px auto, border-radius 100px.
- ECG overlay: #ecg-overlay div at z-index 1001. SVG created dynamically with viewBox matching viewport dimensions.
- drawHeartbeat(svg, svgNS, vw, vh, cy, rHeight, color, duration, onComplete) — reusable PQRST waveform renderer. rHeight controls R peak amplitude. color and duration are per-beat customisable.
- finishECGPhase() handles cleanup: fades ECG lines, transitions boot bg to white, removes overlays, reveals CV. Task 3 will replace the call to this with expanded branching logic.
- requestAnimationFrame needed before setting CSS transitions on dynamically created SVG elements.
- SVG Z (closepath) draws back to the M (moveTo) point, NOT to the last subpath start. Don't use Z when tracing from an external origin to a rectangle — use explicit L commands instead.
- startBranching(svg, svgNS, vw, vh, cy, overlay, bootScreen) — creates branch paths from peak. finishECGPhase(overlay, bootScreen) — fades SVG, removes overlays from DOM, reveals CV content.
- Color interpolation for 3 beats: #00ff41 (green) → #00C9A7 (midpoint) → #00897B (teal). Match glow filter color to stroke color.
- Scroll reveal CSS specificity trap: compound selectors like `.cv-main section.visible .card` that set `transform` will override `.card:hover { transform }` because (0,3,0) > (0,2,0). Must add matching-specificity hover rules: `.cv-main section.visible .card:hover { transform: ... }`.
- initScrollReveal() is called from finishECGPhase() alongside initNavTracking() and initSkillGauges().

## Iteration Log

### Iteration 1 — Task 1: Build the boot screen foundation
- Created `4-vitals-monitor.html` with full boot screen implementation
- Boot sequence follows guardrail format exactly: CLINICAL TERMINAL v3.2.1, profile init, SYSTEM/USER/ROLE/LOCATION, modules, [OK] lines, READY
- Timing: 14 lines × 220ms = ~2860ms boot + 400ms pause + 800ms fade = ~4.06s total (within guardrail)
- Boot text fades to opacity:0, then boot screen is removed and CV content revealed
- Temporary: boot screen hides directly after fade (Task 2 will insert ECG phase between fade and reveal)
- CSS variables, all 3 Google Font families loaded, IIFE strict mode JS
- Learnings: setTimeout delay argument is evaluated at call-time, not in the closure callback, so using a cumulative var in forEach works correctly for staggered timing

### Iteration 2 — Task 2: Build the ECG flatline and first heartbeat
- Added ECG overlay phase between boot fade and CV reveal
- Flatline draws left-to-right (1000ms linear) using SVG stroke-dasharray/dashoffset
- First PQRST heartbeat (R peak 40px) draws over 600ms at viewport center
- drawHeartbeat() is a reusable function accepting: svg, svgNS, vw, vh, cy, rHeight, color, duration, onComplete callback — Task 3 calls this with different amplitudes
- finishECGPhase() is a temporary cleanup function that Task 3 will replace with expanded logic (2nd/3rd beats + branching)
- Timing: boot ~4s + ECG ~2.4s = ~6.4s total (within 8-9s guardrail)
- Learnings: SVG paths created via createElementNS need the SVG namespace 'http://www.w3.org/2000/svg'. requestAnimationFrame is needed before setting CSS transitions on dynamically created SVG elements to ensure the initial state is painted first.
- The ECG overlay z-index is 1001 (above boot screen at 1000) so the lines render on top of the black background

### Iteration 3 — Task 3: Build second and third heartbeats with overflow branching
- Replaced finishECGPhase() call after 1st beat with chained sequence: 1st→2nd→3rd→branching→reveal
- Second heartbeat: R peak 60px, stroke #00C9A7 (green-teal midpoint), bg lightens to #0A0A0A
- Third heartbeat: R peak 100px, stroke #00897B (full teal), bg lightens to #141414
- startBranching() creates 7 SVG branch paths from the 3rd R peak apex:
  - Branch 1: traces pill nav bar outline (rounded rect with Q curves for corners)
  - Branches 2-3: trace hero section left/right vertical edges
  - Branches 4-7: trace four vital sign card outlines (Q curve from peak to card top-left, then L lines around rectangle)
- Branches staggered by 50-150ms, 800ms draw with cubic-bezier easing
- Background transitions to white during branching (800ms ease-out)
- finishECGPhase() now accepts overlay/bootScreen params, removes elements from DOM (not just display:none)
- Glow filter on heartbeat paths dynamically matched to stroke color
- Total timing: ~8.5s (boot ~3.3s + flatline 1.05s + 3 beats ~2.55s + branching ~1.2s + fade 0.5s)
- Learnings: Don't use SVG Z (closepath) when tracing from an external origin to a rectangle — Z draws back to M point (the peak), not the rectangle's start corner. Instead, explicitly L back to the first rectangle corner.
- Learnings: When dynamically setting filter CSS on SVG elements, match the glow color to the stroke color for visual coherence.

### Iteration 4 — Task 4: Build final design skeleton with floating pill nav and typography
- Added floating pill nav bar: position: fixed; top: 16px; centered via left: 50% + translateX(-50%); max-width: 600px; border-radius: 999px; with subtle border and shadow
- Nav links use Inter Tight (--font-secondary) at 13px, muted color, with teal hover/active states
- Active nav link has a 4px teal dot below via ::after pseudo-element
- IntersectionObserver for active section tracking: threshold 0.3, rootMargin '-20% 0px -60% 0px'
- Smooth scroll: preventDefault on nav clicks, scrollTo with offset -70 and behavior: 'smooth'
- initNavTracking() called from finishECGPhase() after CV content is revealed (DOM must exist first)
- Main container: max-width 1000px, padding 0 32px, sections 80px vertical padding
- .section-heading utility class: 24px, 700 weight, heading color, margin-bottom 32px
- Responsive 768px: pill nav becomes full-width scrollable (overflow-x: auto, hidden scrollbar), main padding 20px
- Responsive 480px: nav links shrink to 11px/4px 8px padding, main padding 16px, section padding 48px
- All 6 sections added as skeleton: about, skills, experience, education, projects, contact + footer
- No new codebase pattern learnings — existing patterns from progress.txt covered all needs

### Iteration 5 — Task 5: Build hero section with vital sign cards
- Added centered hero section (#about) with min-height: 100vh, flexbox centering
- Content: h1 name (clamp 36-52px), muted job title, teal location pill, summary paragraph (max-width 560px)
- 4 vital sign metric cards in a flex row with gap 16px, teal border-top, hover elevation
- Card values use different font sizes: "10+" at 28px, "Python/SQL/BI" at 16px (.small), "Pop. Health" and "NHS N&W" at 18px (.medium)
- Responsive: 768px → 2x2 CSS grid, 480px → single column stacked + h1 reduced to 28px
- Vital cards have smooth hover transition: translateY(-2px) + shadow-md elevation
- No new codebase pattern learnings — straightforward implementation following established patterns

### Iteration 6 — Task 6: Build skills section with circular SVG progress gauges
- Skills HTML/CSS/JS was already substantially built in previous iterations (5 built the HTML structure)
- Polish additions: coral hover background for clinical skill items using `[data-color="coral"]:hover` selector
- Moved `text-align: center` from inline style to `.section-heading` class for cleanliness
- Confirmed responsive gauge sizing at 480px: CSS `width: 64px; height: 64px` overrides SVG presentation attributes since `viewBox` handles scaling
- 18 skills total: 8 Technical (teal), 6 Clinical (coral), 4 Strategic (teal) — all with correct percentages
- IntersectionObserver-based scroll animation with 100ms stagger is in place via `initSkillGauges()`
- Learnings: SVG `width`/`height` attributes are presentation attributes; CSS can override them when a `viewBox` is set

### Iteration 7 — Task 7: Build experience section with timeline and ECG decoration
- Added complete experience section with 5 roles in a vertical timeline layout
- Timeline has vertical line at 20% from left with dots (`.current` class fills dot with teal for active roles)
- Decorative ECG waveform SVG (200x30, PQRST shape) beside section heading at 30% opacity
- 5 timeline cards with role title, organisation (teal), date pill, and bullet points
- Cards have hover effect: scale(1.01), shadow-md elevation, teal left border appears
- Responsive 768px: timeline line and dots hidden, entries become full-width stacked
- Responsive 480px: reduced card padding (16px), smaller ECG decoration (120px via CSS width)
- All CV content verified accurate: correct titles, orgs, dates, key numbers (£14.6M, 14,000, £2.6M, 70%, 200+, £220M, £1M+, 3,000+)
- HTML tag balance verified: all section/div/ul/li/h3 tags matched correctly
- No new codebase pattern learnings — timeline pattern straightforward with existing conventions

### Iteration 8 — Task 8: Build education, projects, contact, and footer sections
- Added education section with 2-column grid: MPharm (Hons) UEA (2011-2015, 2:1) and Mary Seacole Leadership Programme (NHS Leadership Academy, 2018)
- Education cards use gradient top border via ::before pseudo-element (teal→coral) with overflow:hidden on card
- A-Levels line below cards: Mathematics (A*), Chemistry (B), Politics (C)
- Projects section with 2x2 grid: PharMetrics (with live link), Patient Pathway Analysis, Blueteq Generator, NMS Video
- Project cards use the gradient border hover trick: ::before with mask-composite exclude, opacity 0→1 on hover
- Contact section with 4-column grid using unicode icons: ☎ phone, ✉ email, ↗ LinkedIn, ○ location
- Footer with decorative ECG waveform SVG (120x20, PQRST shape) and attribution text
- Responsive 768px: projects grid → 1fr (single column), contact grid → 2x2
- Responsive 480px: education grid → 1fr, contact grid → 2x2
- All 13 content strings verified present, all HTML tags balanced (83 div pairs, 6 sections, 19 p, 9 a, 20 svg, etc.)
- CSS was already pre-built in previous iterations (education, projects, contact, footer classes all existed) — only HTML content needed to be filled in
- No new codebase pattern learnings — straightforward content population following established CSS patterns

### Iteration 9 — Task 9: Implement scroll animations and responsive design
- Added 3rd IntersectionObserver (`initScrollReveal()`) for section scroll-reveal animations
- All sections (except hero) start at `opacity: 0; transform: translateY(24px)` and animate to visible with `transition: opacity 0.6s ease, transform 0.6s ease`
- Hero section explicitly set to `opacity: 1; transform: none; transition: none` (always visible, above fold)
- Child elements (vital-card, skill-item, timeline-entry, education-card, project-card, contact-item) have staggered reveal: `opacity: 0; translateY(16px)` → visible state, with JS-assigned `transitionDelay` of `i * 60ms`
- Observer uses `threshold: 0.15` and `unobserve()` after reveal — animations only fire once
- Critical fix: hover transforms on cards need matching specificity to the `.cv-main section.visible .card` selectors, otherwise the `transform: translateY(0)` from the visible state overrides hover `transform: translateY(-2px)`. Added explicit hover rules at `.cv-main section.visible .education-card:hover` etc.
- Same specificity issue with `.cv-main .hero .vital-card` (0,3,0) overriding `.vital-card:hover` (0,2,0) — added `.cv-main .hero .vital-card:hover` at matching specificity
- Learnings: When using compound selectors for scroll-reveal states that set `transform`, ALWAYS add matching-specificity hover rules for any elements that also have hover transforms. The cascade means the higher-specificity non-hover rule will win over a lower-specificity hover rule.
- Responsive design was already largely complete from previous iterations (768px and 480px breakpoints). Task 9 primarily added the scroll animation layer on top.
