--- version: alpha name: rindwork-design description: "A blue-grey cellar-stone canvas (#1a1e21) with warm cream ink (#f0ece1), evoking an aging cave rather than a generic dark theme. Butter gold (#d4a017) is the working accent, a real cheese-fat color, dusty wine (#bb8894) is reserved for the second page's pairing notes. Petrona carries every headline in a warm literary serif, Figtree carries prose and controls. The homepage ages four wheels of cheese on a shelf, one at a time, each wheel's rind changing color and gaining texture as it settles into place." --- ## Brand Positioning Rindwork sells aged cheese, and it exists because most cheesemonger sites sell a mood, a rustic wooden board, string lights, wine-pairing adjectives that could describe anything, instead of the one fact that actually matters: how long has this wheel been aging, and at what temperature. The bet here is to show four real points in a real aging schedule on one shelf, so a customer understands what "aged" costs in time before they ever read a flavor note. If a component doesn't correspond to a real stage, a real week count, or the shelf itself, it doesn't belong here. colors: accent: "#d4a017" accent-alt: "#bb8894" ink: "#f0ece1" ink-muted: "#a8a598" canvas: "#1a1e21" ## Logo / Wordmark System The mark is a wheel of cheese viewed from above, a plain circle with a dashed rind line just inside its edge, marking where the rind meets the paste. It is not a wedge, a mouse hole, or a dairy-farm silhouette. ```svg ``` - **Lockup**: mark, then a `0.55rem` gap, then "Rindwork" in Petrona 600, sentence case. Mark always left of the wordmark. - **Minimum size**: mark not smaller than `18px` wide, below that the dashed rind line reads as a solid ring. - **Clearspace**: empty margin equal to the mark's own width on all four sides. - **Don't**: don't fill the mark's rind line solid, the dashes are what make it read as a boundary rather than a second circle. Don't recolor the dashed line to anything but `--accent`. Don't tilt the mark to a three-quarter angle, it stays a flat top-down view. ## Color System ### Roles | Role | Token | Value | Used for | |---|---|---|---| | Canvas | `--bg` | `#1a1e21` | Page background | | Surface | `--panel` | `#232830` | Nav, stage cards, table, form card | | Surface raised | `--raised` | `#2a2f34` | Row hover, cta band, unaged wheel base | | Border | `--border` | `#2f353b` | Card edges, table rules, dividers | | Border strong | `--border-strong` | `#3f474e` | Decorative-only edges, rind texture dots | | Border UI | `--border-ui` | `#8c795c` | Every interactive boundary: secondary button, input, select, wheel and shelf outline | | Ink | `--ink` | `#f0ece1` | Headlines, body copy, table cells | | Ink muted | `--dim` | `#a8a598` | Labels, meta lines, helper text | | Butter | `--accent` | `#d4a017` | Primary button, links, mark's rind line | | Wine | `--accent-alt` | `#bb8894` | Second-page status, pairing notes | Butter gold is a real cheese-fat color, not a decorative yellow, it's what the mark's rind line is and what the primary button is filled with. Wine is held back for the second page specifically, a pairing note and a status color, so it reads as a deliberate second use rather than a system accent asked to do everything. The four rind colors on the shelf itself, pale cream through deep aged brown, are real illustrative material colors, not system tokens, the same exception every material-specific fill in this gallery already establishes. ### Contrast (computed from the hex values above via WCAG relative luminance) | Pairing | Ratio | Passes | |---|---|---| | `--ink` on `--bg` (headlines, body copy) | 14.21:1 | AAA | | `--ink` on `--panel` (card copy, table cells) | 12.55:1 | AAA | | `--dim` on `--bg` (labels, helper text) | 6.79:1 | AAA | | `--dim` on `--panel` | 6.00:1 | AA | | `--dim` on `--raised` | 5.47:1 | AA | | `--accent` on `--bg` (links, price text) | 7.06:1 | AAA | | `--accent` on `--panel` | 6.24:1 | AA | | `--accent` on `--raised` | 5.69:1 | AA | | `--accent-alt` on `--bg` (pairing notes, status) | 5.64:1 | AA | | `--accent-alt` on `--panel` | 4.98:1 | AA | | `--accent-alt` on `--raised` | 4.54:1 | AA | | dark label (`#1e1503`) on `--accent` fill (primary button) | 7.60:1 | AAA | | `--border-ui` control edge on `--bg` (non-text, inputs) | 4.00:1 | AA (1.4.11) | | `--border-ui` control edge on `--panel` (non-text, secondary button) | 3.53:1 | AA (1.4.11) | `--accent-alt` went through two rounds before shipping, an initial `#9c6f7f` measured only 3.99:1 to 3.52:1 across the surfaces it needed to work on, short of the small-text 4.5:1 minimum, lightened to `#bb8894` to clear it everywhere. `--border-strong` is kept for decorative-only uses, the rind texture dots, never a control boundary, `--border-ui` exists specifically so a real control never inherits that weaker value. typography: display: fontFamily: Petrona fontWeight: 600 body: fontFamily: Figtree fontWeight: 400 ## Type Scale | Token | Size | Weight | Family | Line-height | Letter-spacing | Used for | |---|---|---|---|---|---|---| | `--text-display` | `clamp(2.1rem, 5vw, 3.5rem)` | 600 | Petrona | 1.1 | 0 | Homepage H1 | | `--text-page-h1` | `clamp(1.9rem, 4vw, 2.6rem)` | 600 | Petrona | 1.1 | 0 | Second-page H1 | | `--text-h2` | `1.5rem` | 600 | Petrona | 1.15 | 0 | Section headings | | `--text-h3` | `1.05rem` | 600 | Petrona | 1.2 | 0 | Stage names | | `--text-body` | `1rem` | 400 | Figtree | 1.6 | 0 | Paragraph copy | | `--text-small` | `0.88rem` | 400 | Figtree | 1.55 | 0 | Table cells, footer, meta lines | | `--text-label` | `0.78rem` | 700 | Figtree | 1 | 0.05em, uppercase | Form labels, table headers | Petrona's warm literary serif reads as considered and slow, matching a process measured in weeks, reserved for headlines only. Figtree 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: 5px` on cards and panels, `--radius-sm: 3px` on buttons and inputs. Small and quiet, reading as a cellar shelf's own edges, not a decorative rounding choice. ## Iconography No icon library. The only non-text graphics are the logo mark and the hero's own shelf-and-wheels illustration (hand-built SVG). A wheel's age is stated in weeks in text, never implied by an icon alone. ## Motion Principles Scroll ages four wheels on the shelf, one at a time. Each wheel is a separate group at a fixed shelf position, scaling 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, applied here with a domain-specific detail: the rind ellipse's fill color and its height above the wheel's base both change per stage, so later wheels read as visibly more developed, not just present. Each vessel's scale animation targets a group nested inside a separate static-position group from the very first draft of this system, learned directly from a bug caught and fixed on Center & Pull earlier the same batch: a CSS `transform` set on an element that also carries a static SVG `transform` attribute replaces the attribute rather than composing with it. The moment a wheel lands, the card describing that stage reveals below. One-shot sequence: nothing loops, and every stage is written out in the card grid regardless of scroll or script state. 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 wheels already aged and every card already visible, with no scroll listener attached at all. ## Voice & Tone Precise about time and temperature, no wine-snob posturing. Rindwork talks like someone who actually checks the cave twice a day, not like a tasting menu. In practice: - **Primary button**: "Shop wheels", not "Discover our artisan selection" - **Stage description**: "Rind has real texture now. This is where flavor actually starts developing.", not "Notes of hazelnut and hay" - **Cave note**: "Cave holds steady at 55°F, checked twice a day.", stated as a fact, not a selling point - **Wine pairing (second page)**: names the actual wine style, not a mood - **Status**: "Ready to cut, week 12+." The tell that a sentence is off-brand: it reaches for a flavor adjective or a wine-culture reference instead of naming the real week count or temperature behind it. ## 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 the wheel-aging sequence, 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 shelf graphic is `aria-hidden`.** It's a continuously changing illustration tied to scroll position. Nothing is communicated by it alone: every stage's name, week count, 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 "Wheels" link and exactly one primary button. Below 480px the first nav link drops, the primary button stays. ### Buttons Two variants, `3px` radius, `44px` minimum height: - **Primary**: `--accent` fill, a near-black `#1e1503` label, brightness lift on hover. Once per view, for the real action ("Shop wheels"). - **Secondary**: transparent, `1px solid --border-ui`, `--ink` label, edge and label both going `--accent` on hover. ### The aging shelf (signature) Documented in full under Motion Principles. Structurally: a static shelf plank and four wheel groups, each an outer static-position group wrapping an inner scale-animated group whose rind ellipse changes fill and height per stage. ### Stage card A flat panel: `--panel` background, `1px solid --border`, `5px` radius. Leads with a round rind-color swatch, then the stage name and week count, then a real one-sentence description. Present in the DOM at all times, decorated by the reveal, never gated by it. ### Wheel table (second page) `--raised` header row in `--text-label`, `--panel` body rows, one `--border` rule between rows, a `` naming the order. ### Notice A `--panel` block with a `3px` `--accent-alt` top rule, carrying a storage or serving-temperature 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`, `3px` radius, `44px` height, `--raised` fill plus an accent border on focus. ### Footer Two-part row: an honest note that the shop is fictional, and a link list back to the other page and the gallery. No invented legal text. ## Do's and Don'ts ### Do - Change a wheel's rind color and height per stage, not just its presence. - State the real week count and temperature behind every stage. - Keep a wheel's static shelf position and its animated scale on separate nested groups, never the same element. - Measure real scroll room, minus a safety margin, before choosing a scroll-trigger distance. ### Don't - Don't use a stock photo of a cheese board or a wine-and-cheese pairing cliche. - Don't write wine-tasting adjectives, name the actual age and temperature instead. - Don't use a cartoon cheese-wedge mascot or a mouse-hole decoration. - Don't replay the aging sequence on every scroll pass, it ages once, like a real batch on the shelf. - Don't round anything into a pill, a wheel reads as a disc. ### Deliberate exception The wheels 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, wheels). There is no live inventory count and no authenticated state. "Shop wheels" produces a client-side confirmation only, this is a concept demo. - The shelf shows exactly four stages because that's the real schedule this cheese follows. A fifth stage doesn't exist for this particular wheel, other cheeses in the shop age longer, out of scope for this hero. - 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 shelf and the four aging wheels) rather than a template, the scroll-trigger distance computed from real measured scroll room with a safety margin from the outset, static-position-versus-animated-transform composition handled correctly from the first draft per the lesson from Center & Pull earlier the same batch, and the mechanical detector run clean.