Mimi Plumb Design System
Overview
The Mimi Plumb portfolio is a study in radical minimalism—a design that recedes completely to let black-and-white photography command every pixel of attention. The canvas is unapologetically white ({colors.canvas}), the ink system a controlled spectrum of grays that never exceeds medium-dark ({colors.ink} at #666666). There is no brand color in the traditional sense; the entire chromatic vocabulary is achromatic, trusting contrast, scale, and typographic weight to create hierarchy rather than hue.
The typeface—Gotham Narrow—appears in exactly three weights that form the system's structural spine: an elegant thin (weight 100) for section labels and secondary headings, a light regular (weight 400) for body copy and navigation items, and a book weight (weight 700) reserved exclusively for the artist's name as the site's singular display moment. This tri-weight discipline means the designer never reaches for boldness; emphasis comes from size differential alone, with the {typography.display-lg} name at 27.2px towering over {typography.body-md} at 16px.
Shape language is nearly absent by intention. The only rounded element visible is the dark mode toggle button at {rounded.percentage} (12.5% radius), a solitary softening gesture in an otherwise rectilinear environment. Photography bleeds edge-to-edge within its container with zero border radius on the primary gallery image, treating each frame as an installation view rather than a card component.
The layout follows a split-pane gallery model: a fixed or sticky left rail carrying navigation ({component.top-nav-sidebar}) and a expansive right field dominated by the current photograph ({component.gallery-image-container}). Below the hero image sits a narrow thumbnail preview strip ({component.thumbnail-preview}) and the project title caption. This architecture mirrors the physical experience of walking through a exhibition wall label on the left, photograph on the right.
Key Characteristics:
- Pure achromatic palette—no hue beyond grayscale, letting photography provide all color
- Single typeface (Gotham Narrow) in three weights (100/400/700) with no italic or alternate cuts
{typography.display-lg}at 27.2px / weight 700 is the only display-scale type; everything else is 17.6px or smaller{colors.ink}(#666666) serves dual duty as both primary brand color and body text color- Zero drop shadows—the only depth comes from photographic content itself
- Spacing anchored at
{spacing.xs}(4px) micro-increments up to{spacing.container-wide}(1058px) max content width {component.dark-mode-toggle}is the sole interactive widget, using{rounded.percentage}radius- Transitions are deliberately slow (up to 1.5s for opacity/filter changes) to match contemplative viewing pace
Colors
Brand & Accent
- Primary (
{colors.primary}— #666666): The site's sole brand-adjacent color, serving double duty as the dominant text color and implicit link/interactive color. Appears on all text elements, navigation items, and the artist name. - On Primary (
{colors.on-primary}— #ffffff): White text for rendering atop any surface using the primary color as background (theoretically; in practice this site never inverts to primary backgrounds).
Surface
- Canvas (
{colors.canvas}— #ffffff): The universal background—sidebar, main gallery area, footer, every container. This is a non-negotiable white. - Surface Overlay (
{colors.surface-overlay}— #d2d2d2): Semi-transparent gray at 75% opacity, used exclusively as the background for the thumbnail preview strip below the main image.
Text
- Ink (
{colors.ink}— #666666): The primary text color—medium-dark gray chosen for refined legibility without the aggression of near-black. Used for headlines, navigation, captions, and body text. - Body (
{colors.body}— #666666): Identical to ink in this system; retained as a semantic token for potential future divergence. - Muted (
{colors.muted}— #888888): Slightly lighter gray for de-emphasized elements like section labels ("PROJECTS", "INFORMATION"). - Muted Soft (
{colors.muted-soft}— #999999): Lightest text gray, used for the dark mode toggle icon and any truly tertiary information. - On Dark (
{colors.on-dark}— #ffffff): White text reserved for dark mode state when backgrounds invert to dark gray/black.
Hairlines & Borders
- Hairline (
{colors.hairline}— #e5e5e5): Very light gray for subtle dividers where needed (minimal use in current design). - Border Strong (
{colors.border-strong}— #cccccc): Medium-light gray for more visible borders if required.
Semantic
No explicit semantic colors (error/success/warning) detected in this portfolio context. A photography archive does not require form validation or status signaling within this view.
Typography
Font Family
The entire system runs on Gotham Narrow, a geometric sans-serif from Hoefler & Co. (originally Font Bureau). Three weights are loaded via @font-face declarations pointing to local .otf files: Thin (100), Light (400), and Book (700). The CSS fallback stack cascades through "Helvetica Neue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, then system fonts (-apple-system, BlinkMacSystemFont).
This is a proprietary typeface—Gotham Narrow is not available on Google Fonts or as a web font via standard CDNs. The site self-hosts the OpenType files, which is the correct approach for licensing compliance and render fidelity.
Gotham Narrow plays every role: the artist's name at {typography.display-lg} uses Book weight (700) to anchor the page visually; section headers like "PROJECTS" use Thin (100) via {typography.title-md} for ethereal labeling; all navigation links, body copy, and captions use Light (400) via {typography.body-md} and {typography.title-md-regular} for comfortable reading.
Hierarchy
| Token | Size | Weight | Line Height | Letter Spacing | Use |
|---|---|---|---|---|---|
| {typography.display-lg} | 27.2px | 700 | 1.675 | normal | Artist name / site title |
| {typography.title-md} | 17.6px | 100 | 1.675 | normal | Section labels ("PROJECTS", "INFORMATION") |
| {typography.title-md-regular} | 17.6px | 400 | 1.675 | normal | Navigation items, project titles, info links |
| {typography.body-md} | 16px | 400 | 1.4 | normal | Image captions, body text |
| {typography.body-sm} | 14px | 400 | 1.5 | normal | Smaller UI text (potential use) |
| {typography.caption} | 13.33px | 400 | 1.4 | normal | Toggle button, meta text |
Principles
The typography system's defining discipline is weight scarcity. Only three weights exist (100, 400, 700), and each has a clearly bounded role. The thin weight (100) is exclusively for structural labels—it would be illegible at small sizes or long reading lengths, so it's constrained to short, uppercase-adjacent headers. The book weight (700) appears exactly once per page view: the "Mimi Plumb" name in the sidebar. Everything else lives at 400.
Size creates hierarchy where weight refuses to. The 27.2px name commands attention not because it's bold (though it is), but because it's 70% larger than the 16px body text and 55% larger than the 17.6px navigation items. Line heights are generously loose (1.675–1.675 for display and titles, 1.4 for body) reflecting the editorial/gallery pacing—this is not a dashboard to scan, but an archive to contemplate.
Letter-spacing remains normal throughout; there is no tracking adjustment even at display scale. The typeface's native proportions are trusted entirely.
Note on Font Substitutes
Gotham Narrow is proprietary. For open-source reimplementation, the closest Google Fonts equivalent is Manrope (variable weight, similar geometric skeleton with multiple weights spanning thin to bold). A secondary option is Inter for the 400/700 range, though Inter lacks a convincing 100-weight equivalent. For the thin label role, IBM Plex Sans ExtraLight (200) can approximate the ethereal quality of Gotham Narrow Thin.
Define CSS variables mapping to your substitute:
--font-family: 'Manrope', 'Helvetica Neue', Helvetica, sans-serif;
--font-weight-thin: 200; /* maps to Gotham Narrow 100 */
--font-weight-light: 400; /* maps to Gotham Narrow 400 */
--font-weight-book: 700; /* maps to Gotham Narrow 700 */
Layout
Spacing System
-
Base unit: 4px (
{spacing.xs}). -
Tokens:
{spacing.xxs}(2px) — micro-adjustments{spacing.xs}(4px) — tight internal padding, gaps between related elements{spacing.sm}(8px) — small separation between list items{spacing.md}(16px) — standard padding inside containers, sidebar item padding{spacing.lg}(24px) — gallery container padding, major section spacing{spacing.xl}(32px) — larger gaps between distinct zones{spacing.section}(48px) — section-to-section vertical rhythm{spacing.container-narrow}(705px) — narrower content constraint{spacing.container-medium}(793px) — mid-width constraint for certain layouts{spacing.container-wide}(1058px) — maximum content width for the overall page wrapper
-
Section padding (vertical):
{spacing.lg}(24px) — used around the main gallery image area. -
Card internal padding: Not applicable; this design uses no cards. The gallery image has zero internal padding.
-
Gutters: The sidebar-to-gallery gutter appears to be approximately
{spacing.xl}(32px) based on the grid gap inferred from container widths.
Grid & Container
The page uses a multi-zone grid layout (inferred from CSS class names grid-top-left, grid-middle-left, grid-middle-right, grid-bottom-left, grid-bottom-right):
- Max content width:
{spacing.container-wide}(1058px) for the overall page wrapper. - Density choice: Gallery/exhibition density—generous whitespace, single-column image display, no grid-of-cards marketplace pattern.
- Grid behavior at desktop:
- Left column (sidebar): fixed width, contains
{component.top-nav-sidebar}with artist name and navigation - Right column (main): fluid remainder, contains
{component.main-gallery}with full-bleed image - Bottom zone: spans width, contains
{component.thumbnail-preview}strip and{component.footer-area}
- Left column (sidebar): fixed width, contains
- Hero/column split: Approximately 25% sidebar, 75% gallery at desktop viewport widths.
Whitespace Philosophy
Whitespace is the primary design material here. The system refuses to fill space—margins breathe, the sidebar is comfortably sparse, and the photograph floats in an ocean of {colors.canvas} white. This is editorial-airy density: each project title gets its own line, each section label has room above it, the image caption sits well clear of the photograph edge. The design trusts silence.
Header Architecture
+------------------------------------------+
| Mimi Plumb [gallery area] | <- max-width: 1058px
| |
| PROJECTS |
| Reservoir, 2021-25 |
| Landfall, 1984-1990 |
| The White Sky, 1972-78 |
| ... |
| |
| INFORMATION |
| About |
| Contact |
+------------------------------------------+
[sidebar ~25%] [gallery ~75%]
Hero Section
The "hero" is the photograph itself—a full-bleed black-and-white image occupying the right-hand column:
+------------------------------------------+
| [sidebar] | |
| | +----------------------+ |
| | | | |
| | | PHOTOGRAPH | |
| | | (full bleed) | |
| | | | |
| | +----------------------+ |
| | Reservoir, 2021-25 |
| | +------------------+ |
| | | thumb | overlay | |
| | +------------------+ |
+------------------------------------------+
Thumbnail Preview Strip
Below the main image and caption, a horizontal strip shows the current thumbnail with a semi-transparent {colors.surface-overlay} background overlay, rounded at {rounded.percentage}. This serves as both position indicator and navigation hint.
Elevation & Depth
| Level | Treatment | Use |
|---|---|---|
| 0 (Flat) | No shadow, no border, {colors.canvas} background | Sidebar, main gallery area, footer |
| 1 (Overlay) | {colors.surface-overlay} at 75% opacity, no shadow | Thumbnail preview strip background |
| 2 (Interactive) | Background-color transition on hover/focus | Dark mode toggle button |
This is a fundamentally flat design system. There are no drop shadows anywhere—not on cards (there are no cards), not on modals (none observed), not on dropdowns. Depth is achieved solely through:
- Photographic content: The black-and-white images carry all visual weight and perceived depth through their tonal range.
- Opacity layering: The thumbnail strip's semi-transparent gray creates a subtle "glass" effect over the canvas.
- Typography scale: Size and weight differences create visual stratification without any z-axis tricks.
The philosophy is color-block over shadow, or more accurately, content over artifice. A photography portfolio gains nothing from fabricated depth when the photographs themselves contain infinite gradations of light and dark.
Decorative Depth
None. No gradient washes, no rainbow accents, no texture overlays. The only decoration is the photography itself.
Shapes
Border Radius Scale
| Token | Value | Use |
|---|---|---|
| {rounded.sm} | 2px | Micro-rounding for potential future subtle elements |
| {rounded.DEFAULT} | 4px | Standard slight rounding (available, minimally used) |
| {rounded.md} | 8px | Moderate rounding |
| {rounded.lg} | 12px | Softer rounding |
| {rounded.xl} | 16px | Large rounding |
| {rounded.pill} | 9999px | Full pill shape |
| {rounded.percentage} | 12.5% | Dark mode toggle button (only actual usage) |
In practice, almost every element in this design is sharp-cornered (0px radius). The {rounded.percentage} value on the dark mode toggle is the single exception—a small concession to touch-target friendliness on an otherwise uncompromisingly rectilinear canvas.
Photography Geometry
- Aspect ratio: Photographs appear to display at their native aspect ratios (varying by project—some square, some landscape). The container constrains width but preserves height proportionally.
- Corner rounding: Zero. Main gallery images are perfectly sharp rectangles.
- Treatment: Full-bleed within the right column container. No borders, no frames, no shadows. The image edge IS the design edge.
- Thumbnail geometry: The preview strip thumbnail uses
{rounded.percentage}(12.5%) radius, creating a subtle softening that distinguishes it from the "real" photograph above.
Components
No hover states documented. Hover behavior is unreliable to extract from a single screenshot. State variants live as separate entries in the
components:frontmatter (e.g.{component.button-primary-active},{component.text-input-focus}); add hover styling at implementation time per your stack's conventions.
Navigation & Structure
{component.top-nav-sidebar} — The left-rail navigation container housing the artist's name and all navigation links. Background {colors.canvas}, text {colors.ink}, typeset in {typography.display-lg} for the name (weight 700) and smaller sizes for navigation. Padding {spacing.md} internally. This is the structural anchor of the entire page—without it, the user has no orientation. It occupies roughly 25% of the {spacing.container-wide} layout.
{component.nav-section-label} — Section header text like "PROJECTS" and "INFORMATION" that groups navigation items. Background {colors.canvas}, text {colors.muted} (lighter gray for de-emphasis), typeset in {typography.body-sm} at weight 400 (visually lighter due to color, though the extracted CSS associates section labels with {typography.title-md} weight 100). Padding {spacing.sm} {spacing.md} {spacing.xs} provides breathing room above the label and tight spacing below before list items begin.
{component.nav-project-item} — Individual project links in the sidebar ("Reservoir, 2021-25", "Landfall, 1984-1990", etc.). Background {colors.canvas}, text {colors.ink}, typeset in {typography.title-md-regular} (17.6px / weight 400). Padding {spacing.xs} {spacing.md} keeps items compact but clickable. These are the primary navigation pathways—the user's journey through the archive flows through these links.
{component.nav-info-item} — Secondary navigation links under "INFORMATION" ("About", "Contact"). Identical styling to {component.nav-project-item} — same background, text color, typography, and padding. Structurally subordinate by position (below the project list), not by visual weight.
Gallery & Imagery
{component.main-gallery} — The right-column container holding the primary photograph. Background {colors.canvas}, text {colors.ink}, padding {spacing.lg} around the image. This is the viewport-dominating element—the reason the site exists. Its padding creates the "matting" effect around the photograph, separating it from the container edge without using an actual border or frame.
{component.gallery-image-container} — The <img> element or its immediate wrapper for the displayed photograph. Background {colors.canvas} (or transparent), no text, rounded {rounded.DEFAULT} (effectively sharp), padding 0. The image fills this container at natural aspect ratio, max-constrained by the available column width.
{component.image-caption} — Text beneath the photograph showing the current project title (e.g., "Reservoir, 2021-25"). Background {colors.canvas}, text {colors.ink}, typeset in {typography.body-md} (16px / weight 400). Padding {spacing.sm} 0 provides modest vertical separation from the image above. This caption is the only text in the gallery zone—it identifies without describing, respecting the viewer's direct relationship with the photograph.
{component.thumbnail-preview} — The horizontal strip below the caption showing a reduced version of the current image (or image sequence indicator). Background {colors.surface-overlay} (#d2d2d2 at 75% opacity), text {colors.ink}, rounded {rounded.percentage} (12.5%—the only notably rounded element), padding 0. This component serves as both "you are here" indicator and potential navigation handle for multi-image projects.
Interactive Elements
{component.dark-mode-toggle} — A checkbox-input-based toggle (likely styled via pseudo-elements or a label wrapper) positioned at bottom-right of the page. Background transparent, text {colors.muted-soft}, typeset in {typography.caption} (13.33px), size {spacing.xl} (32px square touch target), rounded {rounded.percentage} (12.5%). The transition background-color 0.2s suggests the button background changes color on interaction. This is the only explicitly interactive UI widget on the page—no buttons, no forms, no search bar, no social media icons. Just the mode switch.
Footer & Meta
{component.footer-area} — The bottom zone of the page, likely containing copyright, credits, or additional metadata. Background {colors.canvas}, text {colors.muted}, typeset in {typography.caption}. Padding {spacing.md}. In this design, the footer is visually minimal—possibly just the dark mode toggle resides here, or it may contain fine-print legal/attribution text.
Do's and Don'ts
Do
- Do use
{colors.ink}(#666666) for all text—never go darker than this unless implementing dark mode ({colors.on-dark}white on dark backgrounds). - Do reserve
{typography.display-lg}(27.2px / weight 700) exclusively for the artist name "Mimi Plumb"—it should appear exactly once per page view. - Do use
{typography.title-md}(17.6px / weight 100) for section labels like "PROJECTS" and "INFORMATION"—its extreme lightness signals structural non-interactivity. - Do let photographs bleed to their container edges with zero border radius—frames and mats are conceptual, not rendered.
- Do maintain
{spacing.lg}(24px) minimum padding around the main gallery image—the photograph needs "matting" whitespace to breathe. - Do keep the sidebar navigation in a fixed or sticky position while the gallery scrolls—orientation must persist.
- Do use the
{rounded.percentage}(12.5%) radius only for the dark mode toggle—everything else stays sharp. - Do allow 1–1.5 second transition durations for opacity and filter changes (as extracted:
opacity 1s, filter 0.2s)—this is contemplative, not transactional UI. - Do set
max-width: {spacing.container-wide}(1058px) on the outermost container—this content should not span ultra-wide displays. - Do self-host the Gotham Narrow
.otffiles via@font-facewithfont-display: block—web font loading must not cause FOUT/FOLT on a photography site.
Don't
- Don't introduce any color beyond the gray scale—this is an achromatic system by deliberate choice. No brand accent, no link blue, no CTA orange.
- Don't use font weight 700 (Book) for anything except the artist name—the weight hierarchy is sacred: 100 = labels, 400 = everything else, 700 = name only.
- Don't add drop shadows, gradients, or texture overlays to any component—depth comes from photography alone.
- Don't crowd the sidebar navigation items—they need
{spacing.xs}(4px) vertical padding minimum for comfortable click/tap targets. - Don't round the corners of the main gallery image—even
{rounded.sm}(2px) would violate the sharp-rectangle convention. - Don't replace the semi-transparent
{colors.surface-overlay}thumbnail background with solid color—the 75% opacity is intentional for visual layering. - Don't add hover states brighter than a subtle background-color shift—the
background-color 0.2stransition suggests minimal interaction feedback. - Don't expand the radius vocabulary beyond what's defined—this system barely uses rounding at all, and that's a feature, not an omission.
- Don't use letter-spacing adjustments—all typography uses
normal(0) letter-spacing; don't add artificial track for "designer" effect. - Don't implement a traditional header bar with logo-left/menu-center/actions-right—this site uses a sidebar-as-navigation model that's integral to its gallery identity.
Motion & Animation
Transition Tokens
--transition-all: all;
--transition-background: background-color 0.2s ease;
--transition-opacity-filter: opacity 1s ease, filter 0.2s ease, -webkit-filter 0.2s ease;
--transition-slow-fade: opacity 1.5s ease, filter 1.5s ease, -webkit-filter 1.5s ease;
--transition-quick-fade: opacity 0.2s ease;
--transition-micro: background-color 0.1s ease, transform 0.1s ease;
Keyframe Animations
No @keyframes blocks were detected in the extracted CSS. Animation behavior (if any) is likely driven by JavaScript-based class toggling (e.g., adding/removing a .active or .visible class that triggers CSS transitions).
Interaction Patterns
- Dark mode toggle: Background color transitions over 200ms (
background-color 0.2s) when activated—suggests a smooth inversion from light canvas to dark surface. - Image crossfade: When navigating between photographs in a multi-image project, opacity transitions run over 1000–1500ms (
opacity 1stoopacity 1.5s). This is unusually slow for web UI and reflects the contemplative, exhibition-like pacing—images dissolve rather than cut. - Filter transitions: Accompanying opacity changes,
filterand-webkit-filteranimate over 200ms—likely used for subtle brightness/contrast adjustments during image transitions. - Micro-interactions: The fastest transition (
background-color 0.1s, transform 0.1s) suggests near-instantaneous feedback for minor state changes, possibly the dark mode toggle's icon or a focus ring. - Gallery script presence: The extracted HTML includes inline JavaScript referencing a
Galleryclass withactive_photo_indexlogic—image navigation is custom-implemented, not a third-party carousel library.
The motion philosophy here is slow disclosure. Nothing snaps; everything dissolves. This matches the subject matter (fine-art documentary photography) and the audience behavior (lingering, studying, comparing).
Imagery Style
- Medium: Black-and-white photography (analog origin, digitally archived).
- Subject matter: Documentary and landscape work—reservoirs, landfalls, rural California, working-class American scenes. The visible "Reservoir, 2021-25" image shows a figure floating in water near a rock, suggesting environmental/portrait intersection.
- Tonal range: Full grayscale from near-white highlights to deep blacks—these are rich, detailed negatives/scans, not high-contrast graphic treatments.
- Color treatment: None. The site's achromatic design means photographs arrive as the sole source of chromatic information (which happens to be none).
- Role: Images dominate. The layout exists to present photographs at maximum scale within a readable frame. Text is purely navigational/identifying.
- Signature technique: Full-bleed presentation with zero border, zero shadow, zero radius—the photograph touches the whitespace directly. The "frame" is the browser window edge.
- Thumbnail treatment: Reduced-size version with semi-transparent gray overlay background and slight rounding ({rounded.percentage}), distinguishing it as "preview" not "primary."
Icon System
- Library: Custom SVG (detected as inline SVG or background-image SVG, not a known icon library).
- Specific icons observed: Moon/crescent icon on the dark mode toggle (bottom-right corner)—the sole icon in the entire interface.
- Treatment: Fill or stroke rendering in
{colors.muted-soft}(#999999), sized approximately 16–18px within the 32px toggle button. Aligned center within the toggle container. - Density: Extreme minimalism—one icon total. No search icons, no social icons, no arrow icons for navigation (text links serve that function).
- Dark mode implication: The crescent moon likely inverts to a sun icon when dark mode activates, though only the light-state icon is visible in the screenshot.
Recommended Frontend Stack
- Framework: Vanilla HTML/CSS/JS (or Astro for static generation)
- Styling: Vanilla CSS or CSS Modules (no Tailwind detected; custom properties recommended)
- Fonts: Self-hosted Gotham Narrow .otf files via @font-face (3 files: Thin, Light, Book)
- Animation: CSS transitions (extracted); JS class-toggling for gallery navigation
- Icons: Custom SVG (single moon/sun icon for dark mode toggle)
- Component lib: None (custom Gallery class observed in inline script)
- Build tool: Unknown (could be simple static hosting; no framework signatures detected)
Rationale: The extracted CSS shows no preprocessor variables, no utility classes, no framework fingerprints. The JavaScript is inline and includes a hand-rolled Gallery class. This is either a meticulously crafted vanilla implementation or a very lightweight static site generator output. For re-implementation, vanilla CSS with custom properties (for the token system defined in this doc) plus a minimal JS gallery controller would honor the original's intentional simplicity.
Responsive Behavior
Breakpoints
| Name | Width | Key Changes |
|---|---|---|
| Mobile | < 640px | Sidebar collapses to hamburger/off-canvas; gallery goes full-width; thumbnail stack becomes scrollable horizontal |
| Tablet | 640px – 1024px | Sidebar may compress or become a top-horizontal nav; image scales down; two-column layout persists but with narrower gutters |
| Desktop | 1024px – 1440px | Full sidebar + gallery split as shown in screenshot; optimal viewing experience |
| Wide | > 1440px | Content centers at {spacing.container-wide} (1058px) max-width with equal whitespace margins |
Note: Exact breakpoint values are inferred from the container width tokens (705px, 793px, 1058px) which suggest responsive stepping points. The actual @media queries were not extracted.
Touch Targets
{component.dark-mode-toggle}: 32px × 32px — below WCAG AAA's 44×44 recommendation. On mobile, this should expand to at least 44×44 for accessibility.{component.nav-project-item}: Full sidebar width × approximately 30–36px height (based on 17.6px font + padding) — adequate for touch if sidebar items span full width.{component.thumbnail-preview}: Height approximately 80–120px (estimated from proportions) — easily tappable as a navigation element.
Collapsing Strategy
- Navigation sidebar: At mobile widths, the left-column sidebar should collapse into a hamburger menu (off-canvas drawer or accordion) to preserve horizontal space for the photograph. The artist name might move to a top-bar or become the hamburger label.
- Gallery image: Always full-width of its container (minus
{spacing.lg}padding). At mobile, this means nearly full viewport width—correct behavior for a photo-first site. - Thumbnail strip: May convert from horizontal bar to a row of dot indicators or a horizontally-scrollable filmstrip at narrow widths.
- Typography scale:
{typography.display-lg}(27.2px) may reduce slightly on mobile (to ~24px) to prevent the artist name from dominating a small screen, though this should be tested against the original intent. - Spacing compression: Vertical spacing tokens (
{spacing.lg},{spacing.xl}) may halve on mobile to fit more content vertically without excessive scrolling.
Image Behavior
- Hero/main photograph: Scales down proportionally, maintaining aspect ratio. Never crops—always shows full frame. Max-width: 100% of container minus padding.
- Thumbnail preview: Scales down with container; may show less of the image (cropped center or scaled to fit) since it's an indicator, not the primary viewing experience.
- Loading strategy: Given the 1.5s fade transitions, images likely preload or lazy-load with a fade-in reveal (matching the
opacity 1.5stransition token).
Iteration Guide
- Build a static portfolio page using vanilla HTML/CSS/JS (or Astro for SSG convenience) that implements the sidebar + gallery split layout shown in the reference.
- Extract every color, font, radius, and spacing value from the YAML frontmatter via the
{section.token}paths. Define these as CSS custom properties on:rootso the entire stylesheet references variables, never hard-coded values. - Implement the
@font-facedeclarations for Gotham Narrow Thin (100), Light (400), and Book (700). If you lack the .otf files, substitute Manrope variable font via Google Fonts and map weights 200→100, 400→400, 700→700. - Build the sidebar navigation as a semantic
<nav>with{component.top-nav-sidebar}styling, containing{component.nav-section-label}headers and{component.nav-project-item}links. Make it sticky-positioned on desktop. - Implement the
Galleryclass (as hinted at in the extracted inline JS) to handle image switching with the slow crossfade transitions documented in Motion & Animation (opacity 1.5sfor image swaps). - Add the
{component.dark-mode-toggle}as a checkbox-input + label construct with the{rounded.percentage}radius andbackground-color 0.2stransition. Wire it to adata-themeattribute or class on<html>that inverts canvas/ink colors. - When adding new project pages, replicate the exact same layout structure—this is a template-driven portfolio where consistency reinforces the archival tone.
- Run accessibility audit: ensure the sidebar navigation has proper
aria-currentstates for the active project, images have meaningfulalttext, and the dark mode toggle hasaria-checkedbinding to its checked state. - Test the 1.5s image transition timing on real devices—if it feels sluggish on mobile, consider reducing to 800ms while keeping the 200ms background-color transition fast.
- Respect the no-color rule: if you're tempted to add a blue link underline or an orange hover state, resist. The grayscale discipline is the brand.
Font Setup for Substitution:
If Gotham Narrow is unavailable, add to your <head>:
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@200;400;700&display=swap" rel="stylesheet">
Then define:
:root {
--font-family: 'Manrope', 'Helvetica Neue', Helvetica, -apple-system, sans-serif;
--weight-thin: 200;
--weight-regular: 400;
--weight-bold: 700;
}
Known Gaps
- Hover state styling: Per the no-hover policy, all interactive hover/focus states (navigation item background shifts, link underlines, thumbnail hover effects) are undocumented and must be designed at implementation time.
- Dark mode full specification: The toggle exists and transitions are documented, but the complete dark-mode color inversion map (what
{colors.canvas}becomes, whether photographs get dimmed, how the sidebar behaves) was not extractable from the light-mode screenshot. - Multi-image gallery navigation: The
Galleryclass script suggests support for multiple images per project (prev/next/keyboard arrows), but the screenshot shows only a single image view. The complete carousel/pagination UI is unknown. - Loading states: No loading spinner, skeleton placeholder, or blur-up technique was visible. How the site handles photograph load latency (especially on slow connections) is undetermined.
- Project detail sub-pages: Each navigation item likely links to a dedicated project page with multiple images and possibly text. The structure of those interior pages (same layout? different? image grid vs. single-view?) is not captured here.
- "About" and "Contact" page designs: These navigation items presumably lead to text-heavy pages whose layouts may differ from the gallery template. Their typography, spacing, and component usage are unknown.
- Keyboard navigation: Whether the gallery supports arrow key navigation, whether the sidebar items are keyboard-focusable in a logical tab order, and what the focus ring style is (if any) are not detectable from static CSS.
- Print stylesheet: As a photography portfolio, print behavior (high-resolution image output, URL visibility, sidebar inclusion) may be important but is not reflected in the screen CSS.
- Footer content completeness: The footer area may contain copyright, credits, or additional links not fully visible or styled in the extracted DOM snapshot.
alltransition usage: One transition token is simplyallwith no duration/easing specified—which properties it applies to and how browsers interpret it (often deprecated in favor of explicit property lists) requires implementation judgment.