--- version: alpha name: flashpop-design description: "A butter-yellow canvas (#fff4d6) with deep navy ink (#1b1a3a), a coral-red (#ff5d5d) and a sky-blue (#2e9bf0) as the two brand accents, both fills labeled in ink with a darker text-safe tier for links. Poppins carries every headline, Inter carries anything meant to be read quickly. The homepage's hero is one printing photo strip, four polaroid frames popping into place in sequence as you scroll, each in its own real backdrop color." --- ## Brand Positioning Flashpop rents photo booths and backdrops for parties and events, and it exists because most photo-booth sites either bury a genuinely fun, fast product under stock photos of strangers laughing at a party, or oversell "unforgettable memories" without ever showing the actual strip you walk away with. Flashpop's bet: show the strip itself actually printing, frame by frame, in real backdrop colors, and stay plain everywhere else, a real package, a real rental window, a real price. If a component performs "unforgettable" without being tied to a real backdrop, a real price, or the strip itself, it doesn't belong here. colors: accent: "#ff5d5d" accent-text: "#c5311f" accent-alt: "#2e9bf0" accent-alt-text: "#0f6bb0" ink: "#1b1a3a" ink-muted: "#524f74" canvas: "#fff4d6" ## Logo / Wordmark System The mark is a single lightning-bolt flash inside a rounded square, the exact shutter-flash shape a guest sees for a half-second before the strip starts printing, not a generic camera-body icon. ```svg ``` - **Lockup**: mark, then a `0.5rem` gap, then "Flashpop" in Poppins, mark always left of the wordmark. - **Minimum size**: mark not smaller than `18px`, below that the bolt's inner angles blur into a blob. - **Clearspace**: empty margin equal to the mark's own height on all four sides. - **Don't**: don't recolor the bolt, it's always `--accent-alt`, never `--accent` or a third color. Don't round the bolt's points, it's always sharp, angular, a real flash shape. Don't place the mark on a busy photo background, it's built for a flat `--ink` square only. ## Color System ### Roles | Role | Token | Value | Used for | |---|---|---|---| | Canvas | `--bg` | `#fff4d6` | Page background | | Surface | `--panel` | `#ffffff` | Nav, package cards, form fields | | Surface raised | `--raised` | `#fff9ea` | Hover state, input focus fill | | Border | `--border` | `#f5e2b8` | Card edges, dividers, input outlines | | Ink | `--ink` | `#1b1a3a` | Primary text, headlines | | Ink muted | `--dim` | `#524f74` | Secondary text, meta lines, placeholders | | Coral | `--accent` | `#ff5d5d` | Primary button fill (ink label), "available" status | | Coral text | `--accent-text` | `#c5311f` | Links, small accent text | | Sky blue | `--accent-alt` | `#2e9bf0` | Secondary button fill (ink label), the mark's bolt, "booked" status | | Sky blue text | `--accent-alt-text` | `#0f6bb0` | Secondary links, small accent text | **The photo strip's four frame colors are illustrative, not tokens**, the same exception every other system in this batch already establishes: real backdrop themes come in real colors, sunset orange, party pink, midnight blue, garden green, not a two-token gradient wearing a polaroid shape. `--accent` and `--accent-alt` never appear as frame fills in the hero, they're reserved for the interface. ### Contrast (computed from the hex values above via WCAG relative luminance) | Pairing | Ratio | Passes | |---|---|---| | `--ink` on `--bg` | 15.26:1 | AAA | | `--dim` on `--bg` | 7.02:1 | AAA | | `--accent-text` on `--bg` (links) | 5.0:1 | AA | | `--accent-alt-text` on `--bg` (links) | 5.11:1 | AA | | `--ink` label on `--accent` fill | 5.56:1 | AA | | `--ink` label on `--accent-alt` fill | 5.63:1 | AA | Both raw accents are too light to carry white text (white on `--accent` measures 3.01:1, white on `--accent-alt` measures 2.97:1, both below AA), so this is the fourth palette in this batch to land on the bright-fill/dark-text-tier answer, alongside Pearl & Pop, Sunsplit, and High Score. At this point it's a real convergence for light-canvas, bright-accent palettes specifically, this batch asked for exactly that combination repeatedly, not a copy-pasted assumption; every ratio above is computed fresh for these hex values. typography: display: fontFamily: Poppins fontWeight: 600 body: fontFamily: Inter fontWeight: 400 ## Type Scale | Token | Size | Weight | Family | Line-height | Letter-spacing | Used for | |---|---|---|---|---|---|---| | `--text-display` | `clamp(2.25rem, 5.5vw, 3.6rem)` | 700 | Poppins | 1.1 | 0 | Homepage H1 only | | `--text-h2` | `1.5rem` | 600 | Poppins | 1.2 | 0 | Section headings | | `--text-h3` | `1.1rem` | 600 | Poppins | 1.25 | 0 | Package names | | `--text-body` | `1rem` | 400 | Inter | 1.65 | 0 | Paragraph copy | | `--text-small` | `0.85rem` | 400 | Inter | 1.5 | 0 | Nav, footer, helper text, meta lines | | `--text-label` | `0.75rem` | 600 | Inter | 1 | 0.06em, uppercase | Kickers, badges, form labels | Poppins' round geometry photographs well as a wordmark on a printed strip mockup, reserved for the headline, section headings, and package names. Inter carries anything read as a sentence or clicked as a control, including every price and every rental window. ## Spacing Scale Base unit `8px`. Tokens in use: `--space-2: 0.5rem`, `--space-3: 1rem`, `--space-4: 1.5rem`, `--space-6: 2rem`, `--space-8: 3rem`, `--space-12: 4rem`. ## Shape `--radius: 16px` on cards, panels, and inputs. `--radius-pill: 999px` on buttons and badges. The photo strip's frames use a slightly smaller `10px` radius with a wider white polaroid border, the one deliberate exception to the two-shape scale, because a real polaroid frame reads as a frame specifically through that thick white margin, not through corner rounding alone. ## Iconography No icon library. The only non-text graphics are the logo mark and the hero's own photo strip (hand-built SVG). Rental windows and package details are plain text, not a camera or calendar icon next to unrelated words. ## Motion Principles Scroll prints one photo strip: four polaroid frames pop into place in sequence down the strip, each scaling from a point with a slight overshoot (the "flash pop") as it lands, in its own real backdrop color. The moment a frame lands, the rental package it represents slides in below. One-shot reveal, nothing loops, every package is written out in plain markup at all times regardless of scroll or script state. Scroll trigger uses a fixed pixel-distance range ("top top" / "+=…"), not a viewport-percentage range, after Sunsplit's pre-elapsed-trigger bug proved percentage triggers are unsafe for hero elements sitting close to the viewport top at load; verified at exactly `0` progress at scroll position `0`. `prefers-reduced-motion: reduce` renders the full strip already printed and every card already visible. ## Voice & Tone Upbeat, specific about what's included, no "unforgettable memories" fluff. In practice: - **Button label**: "See rental packages", not "Capture unforgettable memories!" - **Package description**: "3-hour rental, one backdrop, unlimited prints, a real attendant on-site the whole time.", not "The ULTIMATE party experience!" - **Rental note**: "Booked events get their backdrop confirmed 48 hours ahead, not the morning of.", not vague promises about "seamless" service - **Empty state**: "That weekend's fully booked, the next open date is in 11 days.", not "Sorry, unavailable!" ## Accessibility Baseline - Focus ring: `2px solid var(--accent-alt-text)`, `2px` offset, applied via `:focus-visible` on every interactive element. - Reduced motion: the strip-print sequence and every card reveal check `prefers-reduced-motion: reduce` and render the finished state immediately. - Minimum tap target: `44px` in the smallest dimension for every button and input. - Color is never the only signal: a package's badge pairs "Available" or "Booked" with the word, never color alone. - Every package the strip can reveal is also written out in plain markup at all times, see Motion Principles. ## Components ### Navigation Single-line bar, `64px` tall, `--panel` background with a `--border` bottom hairline, sticky to the top. Left: the mark + wordmark lockup. Right: a "Packages" link plus one primary button ("See rental packages"). ### Buttons Three variants, one radius (`--radius-pill`): - **Primary**: `--accent` fill, `--ink` label, used once per view for the real action. - **Secondary**: transparent fill, `1px solid --border`, `--ink` label. - **Ghost**: text-only, `--dim` label, `--ink` on hover. All variants define `:hover`, `:active` (`transform: scale(0.97)`), `:disabled` (`opacity: .45`), and `:focus-visible`. ### The photo strip (signature interaction) Documented in full under Motion Principles. Structurally: a static strip backing and four polaroid-style frames, each scroll-driven from `scale(0)`/`opacity: 0` to full size with a brief overshoot, in sequence, real backdrop colors. ### Package card A flat `.panel`: `--panel` background, `1px solid --border`, `--radius`, no shadow. Holds the package name (Poppins), a real inclusion list, the price, and an availability badge. Revealed by its frame landing above, present in the DOM at all times. ### Badge `--radius-pill`, `1px solid` the semantic color, semantic-color text on transparent fill: `--accent-text` for "Available," `--accent-alt-text` for "Booked." Never filled solid. ### Footer One row: company name/tagline on the left, real page links on the right (Packages, back to gallery). ## Do's and Don'ts ### Do - Let the strip's four frames be real backdrop-theme colors, not a two-token gradient wearing a polaroid shape. - Give the frame-pop a real overshoot, a frame landing softly isn't a flash pop. - Label any accent-filled surface in `--ink`, both accents are too light to carry white here. - Write every package the strip can reveal into plain markup at all times. - Say the real rental window and price, not a vague "book now" push. ### Don't - Don't use stock photos of party guests, a camera-flash GIF, or a "smile!" caption anywhere. - Don't perform "unforgettable memories" copy, name the actual package inclusions instead. - Don't replay the strip printing on every scroll pass, it plays once, like a real strip printing. - Don't invent a third accent for a package state, "available" and "booked" are the only two. ## Known Constraints - Two routes exist (homepage, packages). There is no checkout and no authenticated state, "See rental packages" and the booking form are not wired to anything real, this is a concept demo. - The strip holds exactly four frames because that's the current backdrop lineup. A fifth backdrop rotates one out, it doesn't add a fifth frame. - No responsive breakpoint table beyond a single-column mobile collapse of the strip stage and package cards. ## Process Built through the impeccable-audited anti-slop workflow: never-list written before any HTML, page structure derived from the signature interaction (one real strip, actually printing) rather than a template, mechanical detector run clean, and the scroll trigger's start/end bounds checked to verify `0` progress at scroll position `0` before this system was considered done, using a fixed-pixel-distance trigger from the outset given the pre-elapsed-trigger lesson from Sunsplit earlier in this batch.