| name | dual-surface-frontend-design |
| description | Design or modify frontends that run on two visual registers - a calm light reading surface and an immersive dark stage - under one design language. Use for work on pages, components, overlays, immersive flows, motion choreography and its reduced-motion degradation, or cross-route visual continuity in such an app, and for extracting production rules from prototypes. Do not use for single-surface editorial styling (use editorial-manuscript-frontend-design), general design polish (use impeccable), WCAG auditing (use accessibility-compliance), or backend, business-logic, and state-machine work. |
Dual-Surface Frontend Design
One frontend design language, two surfaces: a light reading surface (calm, content-first: landing, input forms, longform documents, history) and a dark stage surface (immersive theater where chrome recedes and the app's central visual object leads). The surface switch is route-level; one surface's panel styling must never leak into the other. The alternation light -> dark -> light across the user journey is the drama of the product - making everything dark (or everything light) destroys it.
When this skill applies
- Creating or modifying user-facing pages, sections, overlays, or components in an app that follows (or should follow) this dual-surface language.
- Judging whether a visual proposal (prototype, review finding, redesign) fits the established language.
- Extracting design rules from HTML prototypes into production-quality implementation.
Do not use it for: business logic, API design, copywriting, or generic CSS questions unrelated to the app's visual language.
Design fact priority
When sources conflict, resolve in this order:
- The project's design spec document plus explicit product and accessibility boundaries.
- Current production code - the behavioral source of truth.
- Adopted HTML prototypes - the source of visual intent and composition rationale only.
- Historical task records and superseded prototypes - explain evolution, never override 1-3.
Core design invariants
Violating any of these is a design error, not a preference:
- Dual surface discipline. Light surface = warm, reflective, reading-first; dark stage = immersive, chrome recedes, the central object leads. Reading content never sits on dark-stage panels; stage chrome never sits on the light surface.
- Color division of labor. Give each accent a fixed semantic job: the warm accent (e.g. terracotta) carries decisive actions, completion, and editorial emphasis; the cool accent (e.g. indigo) carries progress, current position, and focus marks. Never both accents at equal intensity in one small component. Text-bearing controls and small colored text use darker
*-ink variants on the light surface for contrast (WCAG AA).
- Font tracks with fixed roles. Serif = narrative and meaning; sans = UI chrome; mono = labels, indices, kickers (uppercase, 0.1-0.2em tracking). Do not swap roles.
- Frame invariants for the central media object. (a) Keep one fixed aspect ratio for every standard frame of the app's central media object - it is the one global invariant. (b) Frames that animate mid-flight may use proportional geometry (radius and padding as percentages of width) so interpolation never breaks them - this is an explicit exception, not a rule to unify. (c) Presentation frames may use their own fixed metrics and are not required to match either. Do not collapse the layers onto one rule.
- Meaningful arrangements are semantic data, not grids. Hand-author relative coordinates (including deliberate rotations and overlaps) for each meaningful arrangement; fall back to a multi-row grid only for unknown data. The same semantic layout may be rendered in multiple places with intentionally different density - keep them in sync when the data changes.
- Composition by hierarchy, not containers. Hairlines, whitespace, typographic scale, and margin notes build hierarchy. Bounded cards appear only where content genuinely needs a boundary (input, saved state, disclosure, error, friction). Reject card grids, pill forests, glassmorphism, neon, and dashboard patterns.
- Motion is a deliberate production contract. Choreography timings and easings live in production code and are mirrored in the adopted prototype. Treat timings as frozen current production parameters: change them only as an intentional redesign, and update or extend tests accordingly.
- Reduced motion is dual-layer. A CSS blanket collapses durations, and JS switches behavior (instant scroll, skipped phases, shortened flights). Both layers must exist for any new animation.
- Gesture-gated actions are never the only path. A press-and-hold confirmation on a primary CTA is pointer-only; keyboard and assistive technology activate immediately.
- One authored surface transition. A single cinematic bridge (e.g. paper-burning to dark) may connect the light surface to the dark stage. It is continuity, not a reusable decoration, and must always degrade to direct navigation for reduced-motion, small screens, and capability failures.
Before editing
- Identify the surface (light or dark stage) and the route contract for the page you touch; read its current component and CSS first.
- Check the project's design spec for the relevant section; changes to confirmed colors, fonts, spacing, or the dual-surface language require explicit redesign authorization.
- For layout math, find every place the same semantic layout exists - it is intentionally expressed with different densities; do not "unify" them.
- For motion, find the existing timing constants and the reduced-motion path before adding or changing any animation.
- Read references/design-language.md for token semantics, color roles, typography, structure, motion, and accessibility rules. Read references/surface-patterns.md for the pattern archetypes (hub, input workspace, overlay, immersive stage, presentation view, longform document), each with composition, mobile degradation, and prototype scaffolding to avoid.
Behavior boundaries
This skill governs presentation only. While doing frontend design work:
- Preserve navigation paths, state transitions, data loading, friction dialogs, and persistence behavior exactly.
- Never copy prototype scaffolding into production: mock data, simulated pools, canned questions or interpretations, demo switchers,
alert() stubs, fake save/feedback states, route placeholders, screenshot-only controllers, or copies of app state machines.
- Do not fix accidental pixel values from prototypes into rules. Carry over only constraints, ratios, semantics, and responsive invariants that change future decisions.
- Product copy and business behavior changes require explicit user authorization beyond this skill.
Implement and verify
- Make the smallest component-local change that preserves behavior and DOM/visual source order.
- Verify against references/validation-matrix.md: desktop and mobile viewports, keyboard and focus, reduced motion, all meaningful arrangements, loading/empty/error/done states, horizontal overflow, and sticky/fixed occlusion.
- Run the project's targeted tests, typecheck, and lint/build for touched areas. If layout math has spec assertions, run them when touching it.
- Manually inspect the built surface; the goal is one edited composition, not assembled widgets.
Completion check
- The surface is correct (light vs dark stage) and consistent with neighboring routes.
- Color roles follow the accent division of labor;
*-ink variants used for text.
- Desktop asymmetry collapses into a single clean mobile reading column with intact DOM/focus order.
- Motion has both the full choreography and the reduced-motion path.
- All controls work with pointer and keyboard; touch targets are generous on the light surface.
- No prototype scaffolding leaked into production; product behavior is unchanged.