Contour · Design System v1.0.0 ← Back to drewbmeyer.com

Contour / Patterns

Patterns

Composed experiences with full interaction contracts — the pointer, keyboard and screen-reader behavior each one guarantees. These are the pieces that make the site feel like a place rather than a page.

Framed print#

The Photography wall's unit: a print in a cream mat and dark frame, hung with a deep shadow, with a museum plaque beneath. Hover lifts the frame off the wall; activation opens the lightbox.

Framed print — hover it
View markup
<button class="pg-frame" type="button"
        data-full="…-full.jpg" data-caption="Title — location">
  <span class="pg-frame__mat"><img src="….jpg" alt="…" loading="lazy" /></span>
  <span class="pg-frame__plaque">
    <span class="pg-frame__t">Title</span>
    <span class="pg-frame__m">Location · year</span>
  </span>
</button>
Anatomy. pg-frame (button) → pg-frame__mat (mat + frame border + shadow) → image, then pg-frame__plaque with title and meta. The page background is the "wall" token --pg-wall, themed for both modes.

Lab canvas#

An infinite pannable, zoomable board of project cards with an optional 3D depth mode — explore the real one. Cards come in two behaviors: link cards (<a>, open the project) and modal cards (<button>, open an on-page overlay).

Lab card — thumb and icon variants
View markup
<div class="lab-card">
  <a class="lab-card__inner" href="…" target="_blank" rel="noopener">  <!-- or <button> for modal cards -->
    <div class="lab-card__float">
      <div class="lab-card__thumb"><img src="…" alt="" /></div>
      <div class="lab-card__meta">
        <div class="lab-card__cat">Game</div>
        <div class="lab-card__title">Chicken Joe's Lunar Wipeout</div>
        <div class="lab-card__blurb">8-bit lunar chaos…</div>
        <span class="lab-card__open">Open</span>
      </div>
    </div>
  </a>
</div>

Interaction contract

InputBehavior
DragPans the world with inertia; a card tap only registers under 8px of total travel, so drags never misfire clicks
Wheel / pinchZooms about the pointer; on-screen / + / recenter buttons mirror it for keyboard and touch
TabCards are real links/buttons in DOM order — the whole board is keyboard-traversable without panning
3D toggleAdds perspective depth per card and cursor-driven parallax tilt; on by default, one button to flatten
Browser zoomNever blocked — the viewport meta stays zoomable; canvas gestures are scoped by touch-action on the board only

Case-study kit#

The parts every case study is assembled from. Each study re-themes the kit through its [data-case] scope (see case-study accents), so the same components wear five different brands.

Meta block

case-meta — the facts strip
Role
Principal UX Designer
Timeline
2024 – 2025
Platforms
iOS · Android · Web
Partners
Research · Product · Engineering
View markup
<dl class="case-meta">
  <div class="case-meta__item"><dt>Role</dt><dd>Principal UX Designer</dd></div>
  <div class="case-meta__item"><dt>Timeline</dt><dd>2024 – 2025</dd></div>
</dl>

Point card

case-point — a decision, in brief

Single secure access point

One caregiver identity to manage one or more care recipients — no shared passwords.

Invite, claim & revoke

Care recipients invite caregivers; access can be granted and pulled back at any time.

The rest of the kit

PartJobNotes
case-heroTitle, client mark, introPer-case display face via --case-display
case-impactBrand-tinted outcomes bandStats + pull quote on the case accent; text tuned to AA per palette
case-quoteStakeholder voicefigure + attribution, same contract as the recommendation card
case-screens / case-galleryProduct imageryBrand-tinted mats; every image bordered and captioned
case-phHonest placeholderLabeled "Asset placeholder" with an icon — never fake screenshots
case-nextForward momentumEvery study ends with a link to the next one

✓ Do

  • Lead with the quantified outcome in the impact band.
  • Theme via [data-case] tokens — never hand-color components.
  • Caption every artifact with what it shows and why it mattered.

✕ Don't

  • Don't ship a case accent that fails AA on small text in either theme.
  • Don't fake missing artifacts — use case-ph and say so.
  • Don't let a study dead-end; case-next is not optional.

Password gate#

Confidential case studies sit behind a server-side gate: a Netlify Edge Function intercepts /work/*, serves this branded card to unauthenticated visitors (HTTP 401 + noindex), and sets a hashed, HttpOnly cookie on the correct password — protected pages never reach the browser without it.

Gate card — static specimen

Protected work

This case study is private.

These projects contain confidential client work. Enter the password to view the case studies.

That password isn't right — try again.

View markup
<form class="passgate__form" method="POST" action="">
  <input class="passgate__input" type="password" name="password"
         placeholder="Password" aria-label="Password"
         autocomplete="current-password" autofocus />
  <button class="passgate__btn" type="submit">View work</button>
</form>
<p class="passgate__err" role="alert" id="gateErr">__GATE_ERROR__</p>
GuaranteeMechanism
Content never leaksEdge function gates at the CDN — unauthenticated requests receive the gate HTML, not the study
Errors are announcedServer-rendered message lands in a role="alert" element
Sessions persistSHA-256 token cookie, HttpOnly · Secure · SameSite=Lax, 30-day expiry
Search stays out401 status, x-robots-tag: noindex, and /work/ disallowed in robots.txt
© 2026 Drew B Meyer Contour v1.0.0 Built from css/style.css — the docs render the production system live