--- version: alpha name: wren-dalca-design description: "A pure black canvas with white ink and a single hot-pink accent (#ff2d78) used only on the cursor, focus states, and one button. Archivo carries bold display type at weight 700, Inter carries the sparse body copy. The system reads as a confident motion-design portfolio, minimal, cool, silent until the cursor moves." --- ## Brand Positioning Wren Dalca sells fifteen seconds of attention, not a case study. The people who hire a motion designer are scrolling through a hundred reels a week and deciding in the first second whether to keep watching. This site is built for that second: black space that makes the work the only thing in the room, a cursor that already feels like the work before a single frame plays, and reels that stay silent until someone actually points at them. Every decision below protects that bet. If a component explains itself with a paragraph instead of a look, it doesn't belong here. If a component would exist for wayfinding rather than for showing motion, it doesn't belong here either, that constraint is deliberate and is covered in full under Do's and Don'ts. colors: accent: "#ff2d78" ink: "#ffffff" ink-muted: "#8a8a8a" canvas: "#000000" ## Logo / Wordmark System The mark is two overlapping play-triangles, a white outline offset up and left, a solid pink triangle offset down and right on top of it. It is a play button caught mid-motion-blur, the same idea as the tagline: the reel is already moving before you click it. There is no wordmark in the lockup. Because the page carries no nav bar, the mark never has to sit next to a wordmark or a menu, it works alone as a small, static corner signature. ```svg ``` - **Placement**: fixed top-right corner, opposite the "back to gallery" utility link in the top-left. It is the only mark on the page and it never repeats. - **Minimum size**: not smaller than `18px` square. Below that the offset between the two triangles collapses and the "motion blur" reads as a smudge instead of two shapes. - **Clearspace**: empty margin equal to the mark's own rendered size on all sides, nothing else is ever placed closer, there is nothing else to place near it since there is no nav. - **Don't**: don't add a wordmark next to it, the mark stands alone. Don't animate it, a static mark is the calm anchor against a page where the cursor already carries all the motion. Don't recolor the outline triangle, it is always `--ink` on `--bg`. Don't use it as a favicon-style bullet or list marker. Don't make it a link, it is a signature, not navigation, clicking it should do nothing. ## Color System ### Roles | Role | Token | Value | Used for | |---|---|---|---| | Canvas | `--bg` | `#000000` | Page background, label color on any `--accent`-filled surface | | Ink | `--ink` | `#ffffff` | Headlines, body copy, secondary-button label, success confirmation text | | Ink muted | `--dim` | `#8a8a8a` | Back link, footer, form labels and helper text, the unavailable tile's caption | | Accent | `--accent` | `#ff2d78` | Cursor, the logo mark's front triangle, focus rings, hover/active states, the one primary button, form focus border, error border and message | There is deliberately no `--accent-alt`. The brand's own rule is "never a third color beyond black, white, and hot-pink," so error states reuse the same pink that focus and success-adjacent states use, rather than borrowing a second hue. The distinction between "this is focused" and "this is wrong" is carried by the message text next to the field, never by color alone, see Accessibility Baseline below. This is the same discipline as choosing not to invent a warning color, it is a constraint the brand keeps on purpose. ### Contrast (computed from the hex values above via WCAG relative luminance) | Pairing | Ratio | Passes | |---|---|---| | `--ink` (white) text on `--bg` (black) | 21:1 | AAA | | `--dim` (`#8a8a8a`) text on `--bg` | ~6.1:1 | AA (body text) | | `--accent` (pink) on `--bg`, used for the cursor, focus rings, links | ~5.9:1 | AA (normal text and large text) | | `--bg` (black) label on `--accent` fill, the primary button | ~5.9:1 | AA (same pair, same ratio, reversed roles) | | `--ink` (white) label on `--accent` fill | ~3.56:1 | Fails AA for normal text | The last row is the rule this table exists to enforce: the one filled-pink button on this page labels itself in `--bg`, never in `--ink`. White text on this specific pink undershoots AA at normal button-label sizes, black text on the same pink clears it comfortably. It is the intuitive choice (white-on-brand-color) that is actually wrong here, which is exactly why it is written down instead of assumed. typography: display: fontFamily: Archivo fontWeight: 700 body: fontFamily: Inter fontWeight: 400 ## Type Scale | Token | Size | Weight | Family | Line-height | Letter-spacing | Used for | |---|---|---|---|---|---|---| | `--text-display` | `clamp(2.5rem, 6vw, 4.5rem)` | 700 | Archivo | 1.05 | -0.01em | Hero H1 only | | `--text-h2` | `1.75rem` | 700 | Archivo | 1.15 | 0 | The single section heading, "Start a project" | | `--text-tile` | `1rem` | 700 | Archivo | 1.3 | 0 | Reel tile labels | | `--text-body` | `1.05rem` | 400 | Inter | 1.6 | 0 | Hero subhead, contact intro paragraph | | `--text-small` | `0.8rem` | 400 | Inter | 1.5 | 0.01em | Back link, footer, form labels, helper and error text, the unavailable tile's caption | | `--text-button` | `0.95rem` | 500 | Inter | 1 | 0 | Button labels | Rule for Archivo vs. Inter: Archivo is reserved for the hero headline, the one section heading, and every reel-tile label, the moments that are the work announcing itself. Inter carries everything meant to be read quickly and quietly: the subhead, the back link, form labels and helper text, button labels, footer copy. If a string is doing the showing off, it's Archivo. If a string is doing a quiet job (a label, a caption, an instruction), it's Inter. ## Spacing Scale Base unit `8px`, biased generous on the larger steps because "let silence do work" means the gaps carry as much weight as the type. Tokens in use: `--space-2: 0.5rem`, `--space-3: 1rem`, `--space-4: 1.5rem`, `--space-6: 2.5rem`, `--space-8: 4rem`, `--space-12: 6rem`. ## Shape Two radius tokens, used for two different reasons. `--radius: 4px` for the button and form-input corners, close enough to sharp that it reads as cinematic rather than soft-SaaS. `--radius-full: 999px`, reserved only for round, icon-only controls where a circle is the honest shape, the cursor dot and the lightbox close button. Reel tiles and the logo mark's clearspace are not rounded at all, `0px`. Nothing else on the page rounds. ## Iconography No icon library, and no hand-drawn glyphs either, not even the Unicode checkmark/cross pairing a dashboard might reach for. The only non-photographic marks on the page are the logo (a static signature, see above) and the custom cursor itself, which already functions as the page's one interactive "icon," expanding and labeling itself over a playable tile. Adding a play-button glyph on top of the video thumbnails, or status icons anywhere else, would be the exact kind of visual clutter the low type-to-image-ratio rule exists to prevent. If a future page genuinely needs iconography beyond the cursor, the fallback is plain text, the same choice made for the "reel under NDA" fallback state below, not an icon set. ## Signature Interaction A grid of thumbnails plays inline showreel loops on hover and cursor-proximity. The custom cursor snaps toward the nearest tile with a magnetic, eased motion (GSAP, `power2.out`, `0.15s` for position), then expands from a `16px` dot to a `56px` circle and prints the word "Watch" inside itself the moment it crosses into a playable tile, so the invitation to play is the cursor's own body, not a separate label pasted on the thumbnail. Only the tile under the cursor plays, every other tile stays silent, playback is earned one tile at a time, never all four (now five) at once. Clicking a playable tile opens the full reel in a lightbox with native video controls. The "reel under NDA" tile intentionally does none of this: hovering it does not expand the cursor and prints no "Watch" label, because there is genuinely nothing to watch, the absence of a cursor reaction is itself the signal, which is the same "let silence do work" principle applied to an interaction instead of to whitespace. ## Voice & Tone Confident, minimal, plays it cool. No exclamation points, no case-study framing, no "let's chat!" energy. In practice: - **Button label**: "Start a project", not "Let's create something amazing together" - **Hover-state micro-copy**: "Watch", printed inside the expanded cursor over a playable tile, not a tooltip, not "Click to view reel" - **Empty / unavailable moment**: "Reel under NDA. Available on request.", not a spinner, not "Oops, this video isn't ready yet!" - **Form success**: "Message sent. I'll reply within two business days.", not "Woohoo! You're all set!" ## Accessibility Baseline - **Custom cursor and `prefers-reduced-motion`**: under reduced motion the JS cursor never mounts its position tween, the `#cursor` element is hidden entirely (`display: none`), and `body` regains its native pointer (`cursor: auto`). The brand's "expensive-feeling cursor" is a motion effect first, so the honest reduced-motion fallback is the plain system cursor, not a cursor that still moves without the easing that makes it feel expensive. - **Autoplay-on-hover and `prefers-reduced-motion`**: under reduced motion, hovering a tile does not call `video.play()` and does not trigger the cursor's watch-label expansion, the tile stays on its static poster frame. Playback only ever starts from an explicit click or an Enter/Space press, which opens the lightbox with native, user-controlled video playback. Nothing auto-plays under reduced motion, full stop. - **Keyboard access**: every reel tile is a `tabindex="0"` element with an `Enter`/`Space` handler that opens the same lightbox a click would, and carries an `aria-label` naming the reel. The "reel under NDA" tile is not in the tab order, it has nothing to activate. - **Focus ring**: `2px solid var(--accent)`, `3px` offset, applied via `:focus-visible` to the back link, the logo mark's own focus state (it has none, it is not a link), every button, every reel tile, and every form field. Never removed without a visible replacement. - **Minimum tap target**: `44px` in the smallest dimension for the lightbox close button and both buttons, even though visually compact. - **Color is never the only signal**: a form error pairs the pink border with an explicit "Error:" prefixed message, never just a pink outline. The "reel under NDA" tile is dimmed *and* captioned in text, never conveyed by opacity alone. Form success is deliberately rendered in plain `--ink`, not `--accent`, so it never gets confused with the error state that shares the brand's one accent color. ## Components ### Logo mark Fixed corner signature, `22px`, see Logo / Wordmark System above. Not a link, not part of a lockup, appears exactly once. ### Buttons Two variants, one radius (`--radius: 4px`), one accent, used exactly once each on the whole page: - **Primary**: `--accent` fill, `--bg` label, the contact form's "Send message" submit, the only pink-filled surface on the page. - **Secondary**: transparent fill, `1px solid` translucent white border, `--ink` label, the hero's "Start a project" anchor jump to the contact section. Both variants define `:hover` (secondary: border brightens to full `--ink`, primary: `filter: brightness(1.08)`), `:active` (`transform: scale(0.97)`), `:disabled` (`opacity: .4`, `pointer-events: none`, used once the contact form has been successfully submitted), and `:focus-visible` (the shared accent outline). There is no ghost/tertiary variant, a two-button page doesn't need a third weight. ### Reel grid (the portfolio component) This is not a generic card grid, it's the product itself: five tiles in a two-column layout with `2px` gaps and no padding between them, so the black gutter reads as part of the composition rather than a spacing accident. Four tiles hold a real reel (poster, silent looping video on hover, label). The fifth demonstrates the fallback state, a reel that isn't available to watch, see below. States per playable tile: **idle** (poster only, label visible, cursor at rest), **hover/keyboard-focus** (video plays muted and loops, cursor expands and prints "Watch", a subtle parallax nudge tracks pointer position within the tile), **playing-in-lightbox** (full-size video with native controls, click-outside or Escape closes it). ### Fallback state: "reel under NDA" The one status state this brand actually needs, framed as something a working motion designer genuinely runs into (client confidentiality), not as a generic "loading" or "error" state. Poster image desaturated and darkened (`grayscale(1) brightness(.35)`), label in `--dim` instead of `--ink`, a second, smaller caption line underneath reading "Available on request." No spinner, no skeleton bars, no icon. The tile is not part of the tab order and the cursor does not react to it, silence is the signal that nothing is playable here. ### Cursor The page's one recurring interactive element. `16px` pink circle at rest, expands to `56px` and prints "Watch" over a playable tile, tracks the pointer with `power2.out` easing at `0.15s`. Fully replaced by the native system pointer under `prefers-reduced-motion: reduce`, see Accessibility Baseline. Implemented as a fixed 56px element scaled down at rest (`transform: scale()`, GSAP-tweened) rather than animating `width`/`height` directly, the visual size change is identical but stays on the compositor instead of triggering layout on every frame. ### Lightbox A full-viewport overlay (`rgba(0,0,0,.92)`) holding the selected reel at native video-player controls and its label. Close via the `44px` round (`--radius-full`) icon button, an outside click, or Escape. No entrance animation beyond an instant show, nothing to disable under reduced motion because there was never anything animating. ### Contact form The page's only form, and its only genuinely new UI surface: Name, Email, and a Message textarea, label above input in `--text-small`/`--dim`. Input and textarea: transparent background, `1px solid` translucent white border, `--radius`, `--ink` text, `--dim` placeholder text that is never used as a substitute for the label. On `:focus`, the border becomes `--accent` and the shared focus ring applies. Helper text sits below in `--text-small`/`--dim`. On error, the border and the message both switch to `--accent`, and the message is explicitly prefixed "Error:" so the signal never depends on the color alone (see Color System's note on sharing one accent between focus and error). On success, the border stays neutral and the message renders in plain `--ink`, the inputs and the submit button both go `:disabled`. ### Footer One quiet line of `--text-small`/`--dim` copy identifying the demo. No link list, that would be the wayfinding chrome this brand explicitly rejects. ## Do's and Don'ts ### Do - Let silence do work: generous black space around each reel tile. - Make the custom cursor feel expensive: smooth eased motion, no jitter, no lag. - Keep the type-to-image ratio low, this is a visual portfolio, not a case-study essay. - Reserve `--accent` for the cursor, focus rings, hover/active states, and the single primary button, never as decorative fill elsewhere. - Use `--bg` as the label color on the `--accent`-filled button, never `--ink`, white-on-pink fails contrast here. - Let the logo mark stay a small, static corner signature, it never grows into a lockup, a wordmark pairing, or a nav element. - Pair every color-coded form state with an explicit message, not color alone, since error and focus share one accent. ### Don't - Don't add a third color beyond black, white, and hot-pink. - Don't autoplay every reel simultaneously, playback is cursor-earned, one tile at a time. - Don't add a hamburger nav or multi-page structure, one scroll, no wayfinding chrome. - Don't add a second accent color for the error state, reuse `--accent` and carry the distinction in the message text instead. - Don't turn the "reel under NDA" tile into a skeleton loader or a spinner, a plain resolved sentence is this brand's voice for an unavailable state. - Don't let the custom cursor keep animating under `prefers-reduced-motion`, fall back to the native system pointer entirely. - Don't stack a second pink-filled button anywhere on the page, one conversion action total, everything else is the secondary anchor-jump style. ## Known Constraints - This system deliberately has no nav bar and no second page. The brand's own Don't rule ("no hamburger nav or multi-page structure, one scroll, no wayfinding chrome") overrides the multi-page pattern used by the other systems in this gallery, comprehensiveness here means a more resolved single scroll (a real contact form, a fallback tile state, documented button and cursor states), not more routes. - Error and focus share the same accent color by brand design (no second hue exists to borrow), the distinction is carried entirely by message text, this is a constraint the brand keeps on purpose, not a gap to fix later. - The five reel tiles use placeholder video paths and a shared poster image, not real footage, this remains a concept demo. The contact form validates client-side only, it isn't wired to a real inbox. - No responsive breakpoint table beyond a single-column mobile collapse of the grid and hero actions.