diff --git a/src/components/layout/InterestHero.astro b/src/components/layout/InterestHero.astro
index fc8f301..c50a900 100644
--- a/src/components/layout/InterestHero.astro
+++ b/src/components/layout/InterestHero.astro
@@ -2,16 +2,14 @@
/**
* InterestHero.astro
* ---------------------------------------------------------------------------
- * Shared header for every interest sub-page, implementing the spec's
- * per-interest template (Header: title + tagline; Overview: narrative). Uses the
- * warm "interest" surface tone via InterestLayout.
+ * Shared header for every interest sub-page. Compact hero on the animated
+ * Milky Way field: a back-to-hub breadcrumb, a small icon mark, the title, and
+ * the italic tagline.
*
- * The decorative icon and the tagline (in mono, as a pull quote) give each page
- * a consistent rhythm while the page supplies its own title + overview copy.
- *
- * An optional `image` prop renders a wide celestial-framed banner behind / above
- * the heading so each interest page leads with a vibe-matched photo. A faint
- * starfield + alchemical accent reinforces the esoteric mood.
+ * Tuned for the dark starfield: text uses bright cream tones (not the dim
+ * --color-text-subtle/--color-text which vanish on the deep sky). The title is
+ * h2-sized (the page is a sub-page, not Home) so it doesn't dominate. An
+ * optional banner image sits above the heading.
*/
import Icon from '@components/Icon.astro';
import Reveal from '@components/motion/Reveal.astro';
@@ -46,20 +44,57 @@ const {
Carries the per-page morph name (one .vt-sky per page snapshot). -->
-
-
-
-
- {eyebrow}
-
-
+ {/* Two-column layout: text on the left, image on the right. Putting the image
+ BESIDE the text (instead of stacked above it) means the hero height is
+ driven by the text column and stays consistent across interest pages
+ regardless of image presence. On small screens it stacks (image below). */}
+
+
+ {/* --- Right: image column (only when an image is provided). A fixed
+ aspect keeps every interest hero the same height. --- */}
{image && (
-
+
)}
-
-
-
-
-
-
-
-
-
{title}
-
-
-
-
- {tagline}
-
-
diff --git a/src/components/professional/Certifications.astro b/src/components/professional/Certifications.astro
new file mode 100644
index 0000000..152c9a4
--- /dev/null
+++ b/src/components/professional/Certifications.astro
@@ -0,0 +1,77 @@
+---
+/**
+ * Certifications.astro
+ * ---------------------------------------------------------------------------
+ * Card grid for the Certifications section of the Professional page. Each entry
+ * is a cert with name, issuer, year, and optional status. Seeded with SAP/cloud
+ * placeholders (Greg to fill); swap the array below.
+ *
+ * Card aesthetic matches EducationHistory / ProjectCard.
+ */
+import Icon from "@components/Icon.astro";
+
+interface CertEntry {
+ icon: string;
+ name: string;
+ issuer: string;
+ year: string;
+ status?: "Active" | "Expired" | "In progress";
+}
+
+// Placeholder entries — replace with Greg's real certifications.
+const entries: CertEntry[] = [
+ /*{
+ icon: "microsoft-azure-devops",
+ name: "SAP BTP Certification",
+ issuer: "SAP",
+ year: "[Year]",
+ status: "Active",
+ },*/
+ {
+ icon: "cloud",
+ name: "Planet 9 Devlopment",
+ issuer: "Neptune",
+ year: "2019",
+ status: "Active",
+ },
+ /*{
+ icon: "robot",
+ name: "[AI / ML cert]",
+ issuer: "[Issuer]",
+ year: "[Year]",
+ },*/
+];
+---
+
+
+ {
+ entries.map((c) => (
+
+
+
+
+
+ {c.status && {c.status}}
+
+
+
+ {c.name}
+
+
+ {c.issuer}
+
+
+ {c.year}
+
+
+
+ ))
+ }
+
diff --git a/src/components/professional/EducationHistory.astro b/src/components/professional/EducationHistory.astro
new file mode 100644
index 0000000..3c4c488
--- /dev/null
+++ b/src/components/professional/EducationHistory.astro
@@ -0,0 +1,76 @@
+---
+/**
+ * EducationHistory.astro
+ * ---------------------------------------------------------------------------
+ * Card grid for the Education section of the Professional page. Each entry is a
+ * degree/diploma with institution, period, and optional detail. Data is seeded
+ * with placeholder rows (Greg to fill); swap the array below with real entries.
+ *
+ * Mirrors the Timeline/ProjectCard card aesthetic: raised surface, hairline
+ * border, gold accent for the credential, mono period label.
+ */
+import Icon from "@components/Icon.astro";
+
+interface EduEntry {
+ icon: string;
+ credential: string;
+ institution: string;
+ period: string;
+ detail?: string;
+}
+
+// Placeholder entries — replace with Greg's real education history.
+const entries: EduEntry[] = [
+ {
+ icon: "school",
+ credential: "B.S., Computer Science",
+ institution: "Drexel University",
+ period: "2014 – 2018",
+ detail:
+ "Foundational coursework in software engineering, algorithms, and systems. Focuses in AI and human-computer interaction.",
+ },
+];
+---
+
+
+ {
+ entries.map((e) => (
+
+
+
+
+
+
+
+ {e.credential}
+
+
+ {e.institution}
+
+
+ {e.period}
+
+
+
+ {e.detail && (
+
+ {e.detail}
+
+ )}
+
+ ))
+ }
+
diff --git a/src/components/professional/SectionNav.astro b/src/components/professional/SectionNav.astro
index b735bcc..aa91501 100644
--- a/src/components/professional/SectionNav.astro
+++ b/src/components/professional/SectionNav.astro
@@ -2,15 +2,23 @@
/**
* SectionNav.astro
* ---------------------------------------------------------------------------
- * Fixed LEFT-SIDE vertical rail for the Professional page. Shows the six
- * sections as a stacked icon+label list, highlights the section currently in
- * view, and lets the user click any item to smooth-scroll to it. A vertical
- * progress line beside the items fills as the user scrolls down the page.
+ * Fixed LEFT-SIDE vertical rail for the Professional page. Six sections as a
+ * stacked icon+label list; highlights the current section; click to smooth-
+ * scroll. A vertical progress line LEFT of the icons fills as you scroll.
*
- * Stylistically it mirrors the page's `.card` language (same raised surface,
- * border, radius) so it reads as a sibling of the content cards rather than a
- * separate chrome element. Icons + labels use bright tokens so they pop on the
- * dark surface. Hidden below `lg`.
+ * Three bugs previously fixed here:
+ * 1. Contrast: the rail used surface-relative tokens (--color-surface-raised /
+ * --color-cream) which collapsed to the same tone on light surfaces (the
+ * interest-surface cream made icons/text invisible). The rail now uses
+ * FIXED dark colors regardless of the page's surface tone.
+ * 2. Progress line clipping: the line sat at the icon column's horizontal
+ * center, running THROUGH the circles. It now sits in a dedicated left
+ * gutter, clear of the icons.
+ * 3. Last section (Contact) not activating: the IntersectionObserver band was
+ * too thin for the short final section to land in. The rootMargin is
+ * widened + click handlers set active immediately so feedback is instant.
+ *
+ * Hidden below `lg`.
*/
import Icon from "@components/Icon.astro";
const sections = [
@@ -28,70 +36,79 @@ const sections = [
class="pro-section-nav fixed left-4 top-1/2 z-40 hidden -translate-y-1/2 flex-col lg:flex"
data-pro-nav
>
- {/* Rail container — matches the .card aesthetic: raised surface, hairline
- border, 1rem radius. Bright icons + labels inside. */}
+ {/* Rail container. FIXED dark colors (not surface tokens) so it's always
+ legible regardless of the page's data-surface tone. Layout: a left gutter
+ for the progress line, then the icon+label list. */}
- {/* Vertical progress track behind the dots. */}
-
-
- {/* The fill bar — height set by JS as the user scrolls. */}
-
+ {/* --- Left gutter: the progress track + fill. Sits LEFT of the icons. --- */}
+
+ {/* Track (full height of the gutter). */}
+
+
+ {/* Fill — height set by JS. Anchored to the top of the track. */}
+