From 02788196e86d6ffaf3b8e48bac3a5da1793b31d9 Mon Sep 17 00:00:00 2001
From: Jenny
Date: Sat, 20 Jun 2026 05:35:21 +0800
Subject: [PATCH 2/2] fix: use container queries for mission card illustration
placement
---
skills/context/progress-tracker.md | 4 +-
src/app/globals.css | 50 +++++++++++++++----
.../sections/mission/mission-cards-client.tsx | 50 +++++++++----------
3 files changed, 67 insertions(+), 37 deletions(-)
diff --git a/skills/context/progress-tracker.md b/skills/context/progress-tracker.md
index a82e732..d4a73e9 100644
--- a/skills/context/progress-tracker.md
+++ b/skills/context/progress-tracker.md
@@ -22,7 +22,7 @@ All seven homepage sections are built, wired, and animated (scroll-driven entran
### Sections
- **Hero** -- full-bleed with isolated `HeroWebglBackground` layer, responsive typography, inner `.site-container`. Interactive WebGL globe (R3F/Three.js) in `src/components/webgl/globe/` (surface, hubs, arcs, atmosphere, starfield, shaders, layout, colors modules); baked static WebP/PNG fallback for mobile (`<1024px`), no-WebGL, and reduced motion via `hero-globe-static.ts` + `GlobeCanvasErrorBoundary`. Hero copy uses `.hero-*` component classes in `globals.css`; CTAs use `HashLink`.
-- **Mission** -- desktop accordion cards with scroll pin-stack, mobile snap carousel with pagination dots, per-card illustrations, reduced-motion support. Card height capped via `min(px, dvh)` for viewport fit. Illustration placements use dvh-based responsive sizing.
+- **Mission** -- desktop accordion cards with scroll pin-stack, mobile snap carousel with pagination dots, per-card illustrations, reduced-motion support. Card height capped via `min(px, dvh)` for viewport fit. Expanded card content and illustrations use card-container-aware scaling, with illustrations centered in the available space between the title and body for short desktop viewports.
- **History** -- timeline section.
- **Team** -- team member cards. Member names link to X profile (tappable on mobile/tablet).
- **Monad** -- GSAP hover/dialog animations, `MonadCardsClient` with Radix dialog (desktop) + Sheet (mobile), `TooltipProvider` in layout.
@@ -90,4 +90,4 @@ All seven homepage sections are built, wired, and animated (scroll-driven entran
## Latest Handoff
-- Team content proofreading 1: updated Jeff Paul's bio to the edupreneur/founder copy and changed the second metric from "Revenue-positive for 2 years" to "Over $5m in Grants Raised". Touched `src/lib/content/team.ts`. Verification: `bun run typecheck` passes. Open: animation overlap in Mission card remains deferred. Next: continue content QA fixes.
+- Mission graph placement tuning: moved expanded-card illustrations into the Mission card content grid so each graph centers in the remaining space between the wrapped title and body instead of relying on fixed vertical offsets. Added equal vertical inset and max sizing for the illustration row to preserve breathing room at short desktop heights such as 1440x670. Touched `src/components/sections/mission/mission-cards-client.tsx` and `src/app/globals.css`. Verification: `bun run typecheck`, `bun run lint` (passes with existing warnings in `site-footer.tsx` and `monad-topic-enter.ts`), `bun run build`, browser geometry check at 1440x670 showing equal title/graph and graph/body gaps. Open: existing unrelated lint warnings remain. Next: continue Mission card-by-card visual tuning if requested.
diff --git a/src/app/globals.css b/src/app/globals.css
index 99f7ab6..84e69c6 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -510,32 +510,64 @@
.mission-card-shell {
@apply relative overflow-hidden rounded-2xl border border-border-default bg-background text-left;
+ container: mission-card / size;
}
.mission-card-illustration {
- @apply pointer-events-none absolute inset-x-0 flex justify-center;
+ @apply pointer-events-none flex h-full min-h-0 items-center justify-center overflow-visible;
+ padding-block: 0.75rem;
+ padding-block: clamp(0.75rem, 2cqh, 1rem);
+ }
+
+ .mission-card-illustration > * {
+ max-width: 100%;
+ max-height: 100%;
}
.mission-card-content {
- @apply relative z-10 grid h-full grid-rows-[auto_1fr_auto] p-5 md:p-6 xl:p-7;
+ @apply relative z-10 grid h-full grid-rows-[auto_minmax(0,1fr)_auto] p-5 md:p-6 xl:p-7;
}
.mission-card-title {
@apply font-mona leading-none text-text-primary max-md:text-[2.25rem] max-md:font-semibold md:text-section-heading md:font-medium xl:font-semibold;
}
+ .mission-card-title-spaced {
+ @apply mt-4 md:mt-5;
+ }
+
+ .mission-card-body {
+ @apply font-mona text-body-sm font-light text-text-secondary;
+ }
+
+ @media (width >= 48rem) {
+ .mission-card-body {
+ font-size: var(--text-body);
+ line-height: var(--text-body-line-height);
+ }
+ }
+
@media (width >= 80rem) {
+ .mission-card-content {
+ padding: 1.75rem;
+ padding: clamp(1.25rem, min(5cqw, 4.4cqh), 1.75rem);
+ }
+
.mission-card-title {
- font-size: clamp(3rem, 5.5dvh, 3.75rem);
+ font-size: 3.75rem;
+ font-size: clamp(2.5rem, min(10.8cqw, 8.4cqh), 3.75rem);
}
- }
- .mission-card-title-spaced {
- @apply mt-4 md:mt-5 xl:mt-7;
- }
+ .mission-card-title-spaced {
+ margin-top: 1.75rem;
+ margin-top: clamp(1rem, 3.4cqh, 1.75rem);
+ }
- .mission-card-body {
- @apply font-mona text-body-sm font-light text-text-secondary md:text-body xl:text-body-lg;
+ .mission-card-body {
+ font-size: var(--text-body-lg);
+ font-size: clamp(1rem, min(3.6cqw, 3.2cqh), 1.25rem);
+ line-height: 1.3;
+ }
}
.mission-desktop-card-trigger {
diff --git a/src/components/sections/mission/mission-cards-client.tsx b/src/components/sections/mission/mission-cards-client.tsx
index 94acac8..8d8b703 100644
--- a/src/components/sections/mission/mission-cards-client.tsx
+++ b/src/components/sections/mission/mission-cards-client.tsx
@@ -29,7 +29,6 @@ import {
import type { MissionCard, MissionCardId } from "@/lib/content/mission";
type MissionIllustrationPlacement = {
- topClass: string;
sizeClass: string;
};
@@ -44,26 +43,27 @@ type MissionDesktopStackProps = MissionCardsProps & {
const MISSION_COLLAPSED_EYEBROW_CLASS =
"mission-eyebrow mission-collapsed-card-eyebrow";
+const MISSION_ILLUSTRATION_SIZE_LG =
+ "xl:size-[clamp(15rem,min(74cqw,48cqh),28rem)]";
+
+const MISSION_ILLUSTRATION_SIZE_MD =
+ "xl:size-[clamp(13rem,min(64cqw,42cqh),24rem)]";
+
const MISSION_ILLUSTRATION_PLACEMENTS = {
pulse: {
- topClass: "top-[12.5rem] md:top-[14.5rem] xl:top-[60%] xl:-translate-y-1/2",
- sizeClass: "size-[13.5rem] md:size-[22rem] xl:size-[clamp(18rem,42dvh,28rem)]",
+ sizeClass: `size-[13.5rem] md:size-[22rem] ${MISSION_ILLUSTRATION_SIZE_LG}`,
},
disciplines: {
- topClass: "top-[12rem] md:top-[14rem] xl:top-[calc(50%+3rem)] xl:-translate-y-1/2",
- sizeClass: "size-[13rem] md:size-[22rem] xl:size-[clamp(18rem,42dvh,28rem)]",
+ sizeClass: `size-[13rem] md:size-[22rem] ${MISSION_ILLUSTRATION_SIZE_LG}`,
},
collections: {
- topClass: "top-[13.5rem] md:top-[14.5rem] xl:top-[calc(50%+3rem)] xl:-translate-y-1/2",
- sizeClass: "size-[11.5rem] md:size-[20rem] xl:size-[clamp(16rem,36dvh,24rem)]",
+ sizeClass: `size-[11.5rem] md:size-[20rem] ${MISSION_ILLUSTRATION_SIZE_MD}`,
},
ideas: {
- topClass: "top-[12.8rem] md:top-[14.5rem] xl:top-[calc(50%+3rem)] xl:-translate-y-1/2",
- sizeClass: "size-[14rem] md:size-[22rem] xl:size-[clamp(18rem,42dvh,28rem)]",
+ sizeClass: `size-[14rem] md:size-[22rem] ${MISSION_ILLUSTRATION_SIZE_LG}`,
},
culture: {
- topClass: "top-[14.5rem] md:top-[15.5rem] xl:top-[60%] xl:-translate-y-1/2",
- sizeClass: "size-[11.5rem] md:size-[18rem] xl:size-[clamp(16rem,36dvh,24rem)]",
+ sizeClass: `size-[11.5rem] md:size-[18rem] ${MISSION_ILLUSTRATION_SIZE_MD}`,
},
} satisfies Record {card.eyebrow} {card.body}