--- version: alpha name: center-and-pull-design description: "A cool stoneware-grey canvas (#e9e6e0) with near-black warm-grey ink (#2a2724), a third light palette in the gallery but deliberately cooler and less warm-cream than the trade-shop and dumpling-house systems built earlier the same batch. Terracotta (#9c4a2f) is the clay-body accent, slate blue (#4d6076) is a real glaze color reserved for the second page. Zilla Slab carries every headline, Nunito Sans carries prose and controls. The homepage throws one pot through four real wheel stages, each stage adding a vessel silhouette on a continuously spinning wheel." --- ## Brand Positioning Center & Pull teaches wheel-thrown pottery, and it exists because most studio sites sell the fantasy of a finished glazed bowl and skip the actual skill, which is slow, repetitive, and mostly about one hand fighting the other for control. The bet here is to show the four real stages a beginner actually learns, in order, and to be honest that most first classes end at stage one. If a component doesn't correspond to a real stage, a real class, or the wheel itself, it doesn't belong here. colors: accent: "#9c4a2f" accent-alt: "#4d6076" ink: "#2a2724" ink-muted: "#6b665e" canvas: "#e9e6e0" ## Logo / Wordmark System The mark is a pot on a wheel in profile: a wheel-head ellipse at the base, a vessel silhouette rising from it drawn as a single open line, not a filled shape. It is not a spinning wheel viewed from above, a pair of hands, or a ceramic glaze splash. ```svg ``` - **Lockup**: mark, then a `0.55rem` gap, then "Center & Pull" in Zilla Slab 700, sentence case. Mark always left of the wordmark. - **Minimum size**: mark not smaller than `18px` tall, below that the vessel line and the wheel ellipse merge. - **Clearspace**: empty margin equal to the mark's own height on all four sides. - **Don't**: don't fill the vessel silhouette solid, it stays an open line, a profile sketch, not a finished object. Don't recolor the wheel-head ellipse, it's always the neutral border tones, never an accent. Don't add hands or fingers to the mark. ## Color System ### Roles | Role | Token | Value | Used for | |---|---|---|---| | Canvas | `--bg` | `#e9e6e0` | Page background, opened-vessel hole fill | | Surface | `--panel` | `#ffffff` | Nav, stage cards, table, form card | | Surface raised | `--raised` | `#f2efe9` | Row hover, cta band | | Border | `--border` | `#ddd7cc` | Card edges, table rules, dividers | | Border strong | `--border-strong` | `#c7bfaf` | Decorative-only edges, wheel-head fill | | Border UI | `--border-ui` | `#8a8175` | Every interactive boundary: secondary button, input, select, wheel-head outline | | Ink | `--ink` | `#2a2724` | Headlines, body copy, table cells | | Ink muted | `--dim` | `#6b665e` | Labels, meta lines, helper text | | Terracotta | `--accent` | `#9c4a2f` | Primary button, links, every vessel silhouette | | Slate glaze | `--accent-alt` | `#4d6076` | Second-page status, a real glaze option | Terracotta is the clay body's own color, every vessel on the wheel is drawn in it, and the primary button shares it because that's this studio's one working color. Slate blue is a genuine stoneware glaze color, not a decorative pair, it's held back for the second page's glaze and status use so it reads as a specific choice rather than a system accent doing double duty. ### Contrast (computed from the hex values above via WCAG relative luminance) | Pairing | Ratio | Passes | |---|---|---| | `--ink` on `--bg` (headlines, body copy) | 11.92:1 | AAA | | `--ink` on `--panel` (card copy, table cells) | 14.85:1 | AAA | | `--dim` on `--bg` (labels, helper text) | 4.57:1 | AA | | `--dim` on `--panel` | 5.70:1 | AA | | `--dim` on `--raised` | 4.96:1 | AA | | `--accent` on `--bg` (links, price text) | 4.91:1 | AA | | `--accent` on `--panel` | 6.12:1 | AA | | `--accent` on `--raised` | 5.33:1 | AA | | `--accent-alt` on `--bg` | 5.19:1 | AA | | `--accent-alt` on `--panel` | 6.46:1 | AA | | `--accent-alt` on `--raised` | 5.63:1 | AA | | light label (`#fff6f1`) on `--accent` fill (primary button) | 5.74:1 | AA | | `--border-ui` control edge on `--bg` (non-text, inputs) | 3.08:1 | AA (1.4.11) | | `--border-ui` control edge on `--panel` (non-text, secondary button) | 3.83:1 | AA (1.4.11) | Both accents were darkened from an initial pass, `#b5593a` and `#5c7188`, which measured only 3.78:1 and 4.04:1 on canvas, short of the small-text 4.5:1 minimum, before this system shipped, not after. `--border-strong` is kept for decorative-only uses, the wheel-head fill, never a control boundary, `--border-ui` exists specifically so a real control never inherits that weaker value. typography: display: fontFamily: Zilla Slab fontWeight: 600 body: fontFamily: Nunito Sans fontWeight: 400 ## Type Scale | Token | Size | Weight | Family | Line-height | Letter-spacing | Used for | |---|---|---|---|---|---|---| | `--text-display` | `clamp(2.1rem, 5vw, 3.5rem)` | 600 | Zilla Slab | 1.1 | 0 | Homepage H1 | | `--text-page-h1` | `clamp(1.9rem, 4vw, 2.6rem)` | 600 | Zilla Slab | 1.1 | 0 | Second-page H1 | | `--text-h2` | `1.5rem` | 600 | Zilla Slab | 1.15 | 0 | Section headings | | `--text-h3` | `1.05rem` | 600 | Zilla Slab | 1.2 | 0 | Stage and class names | | `--text-body` | `1rem` | 400 | Nunito Sans | 1.6 | 0 | Paragraph copy | | `--text-small` | `0.88rem` | 400 | Nunito Sans | 1.55 | 0 | Table cells, footer, meta lines | | `--text-label` | `0.78rem` | 700 | Nunito Sans | 1 | 0.05em, uppercase | Form labels, table headers, stage numbers | Zilla Slab's sturdy slab serifs read as thrown and fired rather than typeset, reserved for headlines only. Nunito Sans carries every sentence and every control at 400 for prose and 700 for labels. ## Spacing Scale Base unit `8px`. Tokens in use: `--space-2: .5rem`, `--space-3: 1rem`, `--space-4: 1.5rem`, `--space-6: 2rem`, `--space-8: 3rem`, `--space-12: 4rem`. ## Shape `--radius: 6px` on cards and panels, `--radius-sm: 4px` on buttons and inputs. Small and structural, reading as fired ceramic edges, not the soft rounding of the dumpling-house system or the zero-radius machined edge of the trade-shop systems built the same batch. ## Iconography No icon library. The only non-text graphics are the logo mark and the hero's own wheel-and-vessel illustration (hand-built SVG). The wheel's cross-mark spins continuously and independently of the scroll-driven stages, since a wheel really does spin regardless of what stage the pot is at, this is the one always-on motion in the system, everything else is one-shot. ## Motion Principles Scroll throws one pot through four real stages. Each stage is a separate vessel silhouette positioned at a fixed spot on the wheel, and scales from `0` to `1` with a slight overshoot as its own scroll segment completes, the same one-shot settle this gallery's other "N items arrive in sequence" systems use. The wheel-head's cross-mark spins on a plain CSS `@keyframes` loop the entire time, independent of scroll position, because that motion is honestly continuous rather than tied to a discrete event. The moment a stage's vessel lands, the card describing that stage reveals below. One-shot sequence: nothing about the vessel reveal loops, and every stage is written out in the card grid regardless of scroll or script state. Each vessel's scale animation targets an inner group, kept deliberately separate from an outer group carrying its static position, because setting a CSS `transform` directly on an element that also carries a static SVG `transform` attribute replaces the attribute value entirely rather than composing with it, collapsing every vessel to the same point. This was caught and fixed before the system shipped, verified by reading each vessel's rendered bounding box and confirming four distinct x-positions rather than one. The scroll trigger measures the page's real available scroll room below the stage at load, minus a `16px` safety margin, and caps the distance at that figure (never more than `520px`). A viewport tall enough to leave under `20px` of room, or a `prefers-reduced-motion` visitor, gets all four vessels already thrown and every card already visible, with no scroll listener attached at all, though the wheel's continuous spin still honors `prefers-reduced-motion` by stopping entirely. ## Voice & Tone Patient, technique-focused, honest about how slow the skill actually is. Center & Pull talks like an instructor who has watched a hundred first classes end the same way, not like a studio selling a finished-bowl fantasy. In practice: - **Primary button**: "Book a class", not "Unleash your creativity" - **Stage one copy**: "Most first classes end here, and that's fine.", not "You'll be a pro in no time!" - **Stage two copy**: "A thumb goes into the center, straight down, not at an angle.", not "Now the fun part begins" - **What's included**: named plainly on the classes page (wheel time, clay, one firing), not implied - **Status**: "Wheels open today, walk-ins fit between classes." The tell that a sentence is off-brand: it promises speed or mastery instead of naming the actual stage and how long it honestly takes. ## Accessibility Baseline - **Focus ring**: `2px solid var(--accent)` at `2px` offset via `:focus-visible` on every link, button, input, and select, never removed. - **Reduced motion**: honored on both the vessel reveal and the wheel's continuous spin, as described under Motion Principles. No scroll listener is attached at all when reduce is set, or when there's no real scroll room to attach one to meaningfully. - **The wheel and vessel graphic is `aria-hidden`.** It's a continuously changing illustration tied to scroll position and a looping spin. Nothing is communicated by it alone: every stage's name and description is in the card grid below in plain markup at all times. - **Tap targets**: `44px` minimum height on every button, nav link, and form control. - **Structure**: one `

` per page, headings in order, `nav` / `main` / `footer` landmarks, `aria-current="page"` on the active nav link. ## Components ### Navigation Single line, `64px`, `--panel` with a `--border` bottom hairline, sticky. Left: the mark plus wordmark lockup. Right: a "Classes" link and exactly one primary button. Below 480px the first nav link drops, the primary button stays. ### Buttons Two variants, `4px` radius, `44px` minimum height: - **Primary**: `--accent` fill, a warm off-white `#fff6f1` label, brightness lift on hover. Once per view, for the real action ("Book a class"). - **Secondary**: transparent, `1px solid --border-ui`, `--ink` label, edge and label both going `--accent` on hover. ### The wheel and vessel (signature) Documented in full under Motion Principles. Structurally: a static wheel-head ellipse with a continuously spinning cross-mark, and four vessel groups, each an outer static-position group wrapping an inner scale-animated group. ### Stage card A flat panel: `--panel` background, `1px solid --border`, `6px` radius. Leads with a stage number label, then the stage name, then a real one-sentence description of the technique. Present in the DOM at all times, decorated by the reveal, never gated by it. ### Class table (second page) `--raised` header row in `--text-label`, `--panel` body rows, one `--border` rule between rows, a `` naming the order. Below 700px the table restacks into one bordered block per class. ### Notice A `--panel` block with a `3px` `--accent-alt` top rule, carrying a kiln or firing-time note. Square, matching the rest of this batch's own resolution for the same accent-bordered notice pattern. ### Form Label above control in `--text-label`. Select and input share `--bg` fill, `1px solid --border-ui`, `4px` radius, `44px` height, `--raised` fill plus an accent border on focus. ### Footer Two-part row: an honest note that the studio is fictional, and a link list back to the other page and the gallery. No invented legal text. ## Do's and Don'ts ### Do - Draw every vessel stage in `--accent`, the same terracotta as the clay body itself. - Keep a vessel's static position and its animated scale on separate nested groups, never the same element. - State the real technique behind a stage, not a vague "you'll get the hang of it." - Let the wheel spin continuously and independently of the scroll-driven stages. - Measure real scroll room, minus a safety margin, before choosing a scroll-trigger distance. ### Don't - Don't use a stock photo of hands on wet clay or a spinning-wheel close-up. - Don't write "unleash your creativity", name the actual technique stage instead. - Don't use a cartoon pot mascot or clay-splatter decoration. - Don't replay the vessel-throwing sequence on every scroll pass, it throws once, like a real class. - Don't round anything into a pill, thrown ceramics read structural. ### Deliberate exception The classes page's `.notice` element carries a `3px` `--accent-alt` top rule on `border-radius: 0`, the same square-plate treatment every other system built this batch reached for its own accent-bordered notice. The static-HTML pass of the mechanical detector still reports `border-accent-on-rounded` on that `border-top` declaration, because its regex engine matches the property text alone and can't see the resolved `border-radius: 0`, the same documented false positive every one of this batch's notices produces. The element is square, confirmed by reading the resolved CSS rule directly. ## Known Constraints - Two routes exist (home, classes). There is no live schedule calendar and no authenticated state. "Book a class" produces a client-side confirmation only, this is a concept demo. - The wheel shows exactly four stages because that's what a real first class covers. A fifth stage (trimming, which happens after the piece dries, off the wheel entirely) is deliberately out of scope for this hero, it isn't a wheel-throwing stage. - Responsive behavior is two breakpoints (900px, 700px, 480px) plus fluid type. There is no tablet-specific layout beyond the table's restack point. ## Process Built through the impeccable-audited anti-slop workflow: never-list written before any HTML, page structure derived from the signature interaction (the wheel and the four vessel stages) rather than a template, the scroll-trigger distance computed from real measured scroll room with a safety margin from the outset, a static-position-versus-animated-transform composition bug caught and fixed before shipping by reading each vessel's actual rendered position, and the mechanical detector run clean.