Content update and Professional details

This commit is contained in:
Greg Kilmer
2026-07-04 18:58:16 -04:00
parent 35d561525f
commit cf9eeb865e
6 changed files with 396 additions and 161 deletions
+58 -31
View File
@@ -14,14 +14,16 @@ import BaseLayout from "@layouts/BaseLayout.astro";
import Reveal from "@components/motion/Reveal.astro";
import Icon from "@components/Icon.astro";
import SectionHeader from "@components/layout/SectionHeader.astro";
import Placeholder from "@components/layout/Placeholder.astro";
import SectionNav from "@components/professional/SectionNav.astro";
import Timeline from "@components/professional/Timeline.astro";
import SkillGrid from "@components/professional/SkillGrid.astro";
import ProjectCard from "@components/professional/ProjectCard.astro";
import EducationHistory from "@components/professional/EducationHistory.astro";
import Certifications from "@components/professional/Certifications.astro";
import AlchemicalDivider from "@components/mystic/AlchemicalDivider.astro";
import Astrolabe from "@components/mystic/Astrolabe.astro";
import CircuitField from "@components/mystic/CircuitField.tsx";
import CelestialFrame from "@components/mystic/CelestialFrame.astro";
import { getCollection } from "astro:content";
const experience = (await getCollection("experience")).sort(
@@ -37,24 +39,43 @@ const projects = (await getCollection("projects")).sort(
title="Professional"
description="Software developer and team lead: cloud and mobile development, SAP Business Technology Platform, AI/ML, full-stack work. Resume and portfolio for Greg Kilmer."
>
<!-- Page header -->
<section class="relative overflow-hidden pt-28 sm:pt-32">
{
/* Circuit-board field. Now self-contained (nebula gradient + canvas inside
one root div), mirroring AnimatedBackground's structure so the morph from
a star hero is element-to-element equivalent — no separate gradient
flash. Shares view-transition-name "sky" via vt-sky. */
}
<CircuitField client:idle className="vt-sky opacity-100" />
{/* Slowly rotating astrolabe ornament behind the header. */}
<Astrolabe
class="pointer-events-none absolute z-0 -right-48 -top-24 h-[34rem] w-[34rem] animate-spin-slow"
style="color: var(--color-accent); opacity:.13;"
/>
<div
class="container-prose relative z-10 flex flex-col gap-10 lg:ml-56 lg:max-w-[calc(72rem+14rem)]"
>
<Reveal>
{/* Page header + overlapping headshot.
The headshot is anchored to the HERO SECTION (not container-prose) so its
straddle point is the true hero/next-section boundary. It's positioned on
the right, aligned with the content column's right edge via the same
container-prose centering math (a centered max-width column). translate-y-1/2
puts its center on the boundary: half in the hero, half over the next
section, in front of both (z-50). */}
<section class="relative overflow-visible pt-28 pb-28 sm:pt-32 sm:pb-36">
{/* Background layer — clipped to the hero so the circuit canvas/astrolabe
don't bleed into the content below. */}
<div class="pointer-events-none absolute inset-0 overflow-hidden">
<CircuitField client:idle className="vt-sky opacity-100" />
<Astrolabe
class="absolute z-0 -right-48 -top-24 h-[34rem] w-[34rem] animate-spin-slow"
style="color: var(--color-accent); opacity:.13;"
/>
</div>
{/* Headshot — anchored to the hero section's bottom edge (the true boundary
with the next section), aligned right with the content column. Wrapped in
a centered max-width box that mirrors container-prose so the headshot's
right edge lines up with the content's right edge. */}
<div class="pointer-events-none absolute inset-x-0 bottom-0 z-50 mx-auto max-w-[72rem] px-5 lg:ml-56 lg:max-w-[calc(72rem+14rem)] sm:px-8">
<div class="pointer-events-auto ml-auto w-44 translate-y-1/2 sm:w-52 md:w-60">
<CelestialFrame rounded="2xl" emphasis="strong">
<img
src="/images/about-portrait.jpg"
alt="Greg Kilmer headshot"
class="h-full w-full object-cover"
style="aspect-ratio: 4/5;"
/>
</CelestialFrame>
</div>
</div>
<div class="container-prose relative z-10 lg:ml-56 lg:max-w-[calc(72rem+14rem)]">
<Reveal class="max-w-2xl">
<SectionHeader
tone="hero"
kicker="Professional"
@@ -80,7 +101,7 @@ const projects = (await getCollection("projects")).sort(
It keeps container-prose's max-width but lets it sit beside the rail. */
}
<div
class="container-prose flex flex-col gap-20 py-16 sm:gap-24 sm:py-20 lg:ml-56 lg:max-w-[calc(72rem+14rem)]"
class="container-prose flex flex-col gap-20 pt-28 pb-16 sm:gap-24 sm:pt-40 sm:pb-20 lg:ml-56 lg:max-w-[calc(72rem+14rem)]"
>
{/* ===== 1. Summary ===== */}
<section id="summary" class="scroll-mt-28 flex flex-col gap-6">
@@ -185,7 +206,7 @@ const projects = (await getCollection("projects")).sort(
</section>
{/* ===== 5. Education ===== */}
<section id="education" class="scroll-mt-28 flex flex-col gap-6">
<section id="education" class="scroll-mt-28 flex flex-col gap-8">
<Reveal>
<SectionHeader
kicker="05"
@@ -194,16 +215,22 @@ const projects = (await getCollection("projects")).sort(
subtitle="My foundation."
/>
</Reveal>
<div class="grid gap-4 sm:grid-cols-2">
<Placeholder
label="Education history"
hint="Add degrees, institutions, and dates."
/>
<Placeholder
label="Certifications"
hint="SAP, cloud, or other relevant certifications."
/>
</div>
<Reveal delay={60}>
<div class="flex flex-col gap-3">
<h3 class="font-mono text-xs uppercase tracking-[0.22em]" style="color: var(--color-accent);">
Education history
</h3>
<EducationHistory />
</div>
</Reveal>
<Reveal delay={120}>
<div class="flex flex-col gap-3">
<h3 class="font-mono text-xs uppercase tracking-[0.22em]" style="color: var(--color-accent);">
Certifications
</h3>
<Certifications />
</div>
</Reveal>
</section>
{/* ===== 6. Contact ===== */}