G&M v8
Grain & Mortar's new v8 website redesign — built in parallel with the existing grainandmortar.com production site. When launched, this site replaces the live one (see the cutover checklist in the theme docs).
Project Info
| Job Number | Internal (G&M rebrand) |
| Phase | Active build — pre-launch |
| Billable | Not billable (internal) |
Client Contacts
Internal team — this is G&M's own site.
- Mike DeKay — Creative Director, mike@grainandmortar.com
- Eric Downs — Technical Director, eric@grainandmortar.com
- Bryan Findell — Contract Animator (icon animations), bryanfindell@gmail.com
Site Reference
| Local Path | /Users/edowns/Local Sites/gm-v8/app/public/wp-content/themes/gmV8 |
| Local URL | https://gm-v8.local |
| Production URL | https://staging.grainandmortar.com (team-facing preview; becomes grainandmortar.com at cutover) |
| GitHub | https://github.com/grainandmortar/gmV8 |
| SSH (Flywheel) | gandmweb+g-m-v8@ssh.getflywheel.com |
| Flywheel Dashboard | https://app.getflywheel.com/gandmweb/g-m-v8/ |
| Theme Docs | See CLAUDE.md at theme root and docs/ folder |
| Old/Live Site | /Users/edowns/Local Sites/grain-mortar-website (will be replaced at cutover) |
Integrations
| Service | Status | Details |
|---|---|---|
| Harvest | Not billable | Internal project |
| Todoist (Team) | TBD | |
| Todoist (Dev) | Active | G&M V8 🚀 (project ID 6gFMwq256w3pc4W5). Open board. Sections: Outstanding Assets / Outstanding Content / Outstanding Dev / Completed. |
| Basecamp | TBD | |
| Slack | Active | #gm-V8 (primary) |
| Masterdoc | TBD | |
| Notion | TBD | |
| Figma | Active | Used as source of truth for v8 design system |
| Cloudflare | TBD | |
| SendGrid | TBD | |
| Vimeo | Active — see docs/VIMEO-AUDIT-2026-04-09.md |
Related Projects / Skills
- Sites dashboard entry:
gm-v8in~/.claude/skills/sites-dashboard/sites.json - Performance tuning skill:
/gm-v8-performance— Lighthouse targets 75+ mobile, 85+ desktop - Typography skill:
/gm-v8-typography— semantic typography rules - Dev tools skill:
/gm-dev-tools— module labels, grid overlay, browser width indicator - Old (live) site notes:
~/.claude/project-notes/grain-mortar/
Key Theme Docs
| File | Description |
|---|---|
docs/BACKLOG.md |
Persistent home for deferred follow-up items |
docs/CUTOVER-CHECKLIST.md |
Launch sequence for gm-v8 → production swap |
docs/VIMEO-AUDIT-2026-04-09.md |
Orphan Vimeo videos (112 of 141) |
docs/TAILWIND-TOKENS.md |
Project-specific Tailwind token reference |
Project Status
2026-05-07 — V8 Dev Tweaks evening pass (rows 83, 85, 87, 90)
Continuation of the same Mike batch session that closed earlier in the day at row 89. Four more rows shipped on top of the 60-90 batch already on main:
- Row 87 — Contact form idle preload (commit d1b1e60). The contact form was already lazy-loaded on first panel open (~30-50KB GF script savings per pageload). Mike noticed the resulting "Loading form…" flash on first tap. Added
requestIdleCallback(withsetTimeout(2000)Safari fallback) to warmensureFormLoaded()after page idle. By the time anyone taps a contact trigger, the GF HTML + scripts are already injected — verified in Chrome: 1 admin-ajax POST during idle, 0 extra calls on click, no loading placeholder ever paints. - Row 83 — Pill description fade-down bug fix (commit 5b95da8). First pill click on Branding/Web faded in correctly; clicks 2+ snapped instantly. The popup container had a
transition:none→ reflow →is-openreset dance to guarantee re-fades, but the innerpopupTitle/popupDescdid not. WhenclosePopup()removedis-openandopenPopup()added it back in the same tick, the browser saw no net class change for the children and skipped their CSS transition. Mirrored the reset pattern: force title/desc to closed state inline (opacity: 0,translateY(6px)), commit via reflow, clear inline overrides, then addis-open. - Row 85 — About scroll transition + headline color flip (commits 2924e42, baf92c6). "Get yourself a good partner" was permanently
text-gm-sky, which read low-contrast on the dark-tan starting bg. Wired the H2 into.transition-textand pointed the About zone'stextsselector at it; now the headline starts black on tan and flips to sky as the bg sweeps to black, holding contrast at both ends. Tried softening the easing band from(0.4, 0.55)snap →(0.1, 0.9)gradient with a wider scroll trigger (top 90% → top 20%), but the 1s scrub lag made the gradient look chasy mid-scroll, so reverted to the tight snap matching the homepage. Per-zoneeaseBandconfig mechanism stayed in for future tuning. - Row 90 — Mobile pill descriptions marked complete after refinements; sheet note updated, no new code commit.
Harvest entry 2922382448 (2026-05-08, G&M Internal / G&M theme) updated 2.0h → 3.0h to cover the evening pass.
Status: All four commits on origin/main. Yellow holds remaining on the V8 Dev Tweaks sheet: 11 (rows 60, 61, 67, 69, 71, 77, 78, 79, 80, 81, 82) — most awaiting MD clarifications, two awaiting external assets (71, 77), three awaiting research/Cloudflare cutover (60, 81, 87 originally — 87 now shipped).
2026-05-05 — Big shipping day: animations, perf backlog, full SEO audit + 8-card sweep
Three threads in one session, all on main:
1. Animation work (continuation from earlier):
- Work-single hero choreographed entrance (split-animate-immediate H1 → fade-up-immediate H2 → fade-in-immediate hero image → main content)
- New .fade-in-immediate primitive (pure-opacity load-delayed reveal for hero imagery; mirrors fade-up-immediate without the y-translate). Logged separately above (search: "Work single hero choreography").
- 15-years badge FOUC fix — the SVG was rendering at full opacity before JS reset() could hide its children; added .badge-15-years { visibility: hidden } guard in critical.css + theme.css, JS un-hides after reset
2. Perf backlog cleanup (items #3 + #4 from docs/BACKLOG.md):
- Gravity Forms lazy-load (commit c734972): removed gravity_form() from header.php (it ran on every pageload via the contact panel), replaced with empty mount + AJAX-load on first contact-trigger click. Saves the GF script bundle (~30–50KB) on every non-form pageload. Took 3 cuts to get right — first version missed gforms_hooks inline JS (defines window.gform), then missed flag flips for gform.domLoaded / themeScriptsLoaded, then missed gform_theme_config localization, then missed re-enqueueing GF's CSS that was previously auto-loading via the dequeue side effect. Final version verified end-to-end via puppeteer-driven headless Chrome — form opens, all fields render with floating labels, side-by-side screenshot matches pre-refactor exactly.
- dev-tools gating (commits 6e4309d in ~/Projects/gm-dev-tools + dd090bc syncing inc/dev-tools/): enqueue_assets() was hooked unconditionally on wp_enqueue_scripts, so dev-tools.js + dev-tools.css loaded for every visitor on production even though render_dock() suppressed the visible dock. Added the same gate render_dock uses (current_user_can('manage_options') || is_dev_environment()). Embedded inc/dev-tools/ tree was 5 commits behind upstream — bundled all 5 commits into the sync.
3. SEO + LLM audit + 8-card sweep (cards on G&M V8 🚀 Todoist board, "Outstanding Dev" section):
Full audit ran via seo-llm agent — found 5 critical pre-launch parity issues plus 3 medium-priority improvements. Translated to 9 Todoist cards + worked through 8 of them this session (LocalBusiness schema deferred per audit recommendation):
- Meta descriptions for /branding/ + /websites/ — wrote
_yoast_wpseo_metadescdirectly to wp_postmeta (DB-only, no commit) - Year-counter null guard (commit c1ebefe) —
increase_number_each_year()called.innerTexton a nullgetElementByIdresult, throwing on every non-15-years page. The element it looks for (#number-to-increase) doesn't exist anywhere in the current theme; the function is effectively dead code but flagged for a future cleanup pass rather than removed in this fix. - H1 tags + display-h2 utility extension (commit aac88d7) — 5 of 8 key pages had no H1. Used the existing
display-h*token system to put real H1s on About, Work, 15-Years, Home (sr-only on home + work since those have no visible heading) without changing visual size. Eric clarified mid-task that the visual must NOT change — the project's design tokens already have this exact escape hatch documented. - /llms-full.txt (commit e6fdd63) — companion to /llms.txt. Dynamic via
template_redirect, pulls from project + random-goody + team CPTs and Yoast metas so it stays current as new case studies land. Pattern adapted from Within Reachinc/llms-full-txt.phpcommit d53c518. - Static contact block (commit 0a26df5) — de-obfuscated the existing footer email (was JS-assembled from data-* attrs, invisible to crawlers), replaced with a plain
mailto:+ visible text. Lazy-loaded GF form unaffected. - Organization schema enhancement (commit 355d5c5) — new
functions/schema-organization.phpaddscontactPoint(email-only, no phone published),founderarray (Eric, Mike, Kristin),foundingDate"2011" viawpseo_schema_organizationfilter. <h5>cleanup +.display-h5utility (commit e0a50fd) — fixed two h5 misuses on About (kicker → p, team names → h3) that broke heading outline. New.display-h5token completes the project'sdisplay-h*family. Documented indocs/TAILWIND-TOKENS.mdincluding the bidirectional rule (smaller-visual-on-bigger-tag is valid for SEO fixes).- Article schema on case study singles (commit 003ef62) — new
functions/schema-project.phpinjects Article node viawpseo_schema_graph. Scoped toproject+random-goodyCPTs (skippingteam). Handles ACF field shape per CPT (content/extended_content/herofor project,snippet_content/thumbnail_full/simple_thumbnail_copyfor random-goody). 49 case studies + 23 random goodies now have full Article structured data. - DEFERRED: LocalBusiness schema for Omaha local SEO push — strategic call, not parity-critical.
Scope overreach correction (commit da98f93): I bundled an "Omaha, Nebraska" location line into the de-obfuscation work without it being explicitly approved. Eric pushed back — line came out of footer.php and llms-full-txt.php in one cleanup commit. Lesson: when implementing audit recommendations, separate "what was approved this turn" from "what was in the broader audit doc" — they're not the same thing.
Net SEO posture vs legacy site (grainandmortar.com): Was "weaker than legacy" pre-session (missing H1s, missing meta descriptions, contact form non-crawlable, no llms-full.txt, no Article schema). Now ahead on llms-full.txt + Article schema (legacy doesn't have either) and at parity on everything else.
Status: All session commits on origin/main. inc/dev-tools submodule pointer bumped + 4 new schema/lazy-load PHP files added — /refresh-docs worth running next session to update CLAUDE.md architecture references. Submodule sync left a remote gm-dev-tools branch in clean state at 6e4309d.
Outstanding:
- LocalBusiness schema deferred (Todoist card stays in Outstanding Dev)
- Phone number — confirmed G&M doesn't publish one; relevant cards updated to email-only
- macOS Icon\r artifact still untracked (long-standing, low-priority)
2026-05-05 — Work single hero choreography + .fade-in-immediate primitive
Continuation of the multi-day animation push. After the footer entrance and 15-years choreography landed yesterday, applied the same brand-load pacing to the work single template (single.php) so case-study pages open with the same deliberate cadence as About / 15-years.
Hero block (above the fold, choreographed):
- H1 → .split-animate-immediate lines mode (lands ~1.4s after default 0.7s blank canvas)
- H2 → .fade-up-immediate data-delay="1.6"
- Hero image → .fade-in-immediate data-delay="2.0" (NEW primitive)
- Main content body → .fade-up-immediate data-delay="2.5"
- Scope sidebar → .fade-up-immediate data-delay="2.7"
Below fold (scroll-triggered):
- Each .gallery-item → .fade-up
- Related case studies H2 + tile grid → .fade-up
- Bottom case-studies / random-goodies pills → .fade-up
New library primitive — .fade-in-immediate. Pure opacity, load-delayed reveal that mirrors .fade-up-immediate but skips the y-translate. Built specifically because hero imagery on work singles benefits from "becoming present" rather than "settling in" — the y-shift on a large image reads as the image being placed, which fights the calm choreography. data-delay and data-duration attrs supported. CSS FOUC guards added in both critical.css (inlined in <head>) and theme.css so the element is hidden from first paint regardless of external stylesheet timing. Registered in initAll() between initFadeIn and initStaggerFadeUp.
Bug repeat from 15-years (FOUC for above-fold body content). First pass used .fade-up on the main-content + scope sidebar columns. ScrollTriggers for already-in-view elements fire on JS init, so above-fold body fired immediately — racing ahead of the H1's intentional delay. Same pattern as 15-years. Eric caught it from a screenshot ("bottom text is coming up before the header gets to finish"). Fixed by converting both columns to .fade-up-immediate with progressive data-delay values that wait for the hero sequence to finish. Logged this as an enduring lesson — any above-fold element under a delayed hero MUST use -immediate variants, not scroll-triggered ones.
Verification. Headless Chrome with --virtual-time-budget for time-locked screenshots at t=50/700/1500/2400/3500ms on both Hudl Next (full-bleed hero image case) and Omaha Performing Arts (no hero image case). Mobile and desktop both clean — t=50ms blank canvas, sequence lands by t=3500ms. Chrome MCP was broken throughout the session (same "No page selected" issue from yesterday) so headless Chrome was the verification path.
Status: Two atomic commits pushed to main: 77f53e9 (primitive + FOUC guards in CSS), 7990357 (single.php animation wiring). Per project memory, this site does NOT auto-deploy — staging/prod is manual when ready.
Doc trail this session:
- docs/animations/WORK-SINGLE-CHOREOGRAPHY.md (new — per-template animation doc, mirrors 15-YEARS-BADGE.md / HERO-ORBIT.md format)
- ~/.claude/skills/gsap-animations/SKILL.md — added .fade-up-immediate and .fade-in-immediate to the Basic Fades & Slides table
- ~/.claude/skills/gsap-animations/ANIMATION-CLASSES.md — new sections for both immediate variants
- demo.html deferred — playable demo entry will land in a follow-up skill-maintenance pass
2026-05-04 — Soft-launch tweaks (typography, work single polish, button system unification)
Worked through Eric's soft-launch list while another session handled the parallel Work AJAX filter rebuild. Six fixes:
-
Mobile h5 letter-spacing. Token was
1pxon mobile vs-0.6pxon desktop — text rendered visibly looser on phones than on desktop. Set mobile to-0.4px(proportional to desktop's-0.02em). Updatedtailwind.config.js,docs/TAILWIND-TOKENS.md, and rebuilt outputs. -
Hero descender clipping on Brand/Web. The "g" in "Branding" and "s" tail on "Websites" were getting cropped by
.fp-heading { overflow: hidden; padding-bottom: 0.05em }. Bumped padding-bottom to0.2emso descenders clear the slide-up reveal mask. -
About-mobile white line under header.
gm_get_header_style()returned'dark-tan'for About butgm_get_page_background_color()only painted the body for15-years, so a 1px alignment gap between fixed header bottom and hero bg revealed the cream body. Addedis_page('about')to the dark-tan body branch. -
Work single "Explore more work" — three issues. - Removed the 1px black border above the section (theme.css
:beforerule deleted). - Card hover white-on-light was unreadable on color-set project pages with light backgrounds. Override hover to usetext_colorso it stays legible. - Default state same root cause: theme.css hardcoded.title .sub-title { color: #666 }at specificity (1,2,0), beating the inline#single a:not(.btn)rule (1,1,1). Subtitle never picked uptext_color. Added a higher-specificity override (#single #project-list .title .sub-title, 2,2,0) so subtitle usestext_colorat opacity 0.7 — preserves title→subtitle hierarchy without falling back to a clashing gray. Verified on Foster (cream bg, dark text) and Omaha Performing Arts (purple bg, cream text). -
Bottom-buttons system. Replaced the legacy
.btn.orange_sliderectangle pair (Case Studies / Random Goodies) with.gm-pill--lgpills, split bottom-left + bottom-right per Eric. New pill primitive lives in theme.css scoped under#single, driven by--pill-fg/--pill-bgCSS variables set inline from project text/background colors (with#030303/#ffffallbacks). Hover swaps fg ↔ bg same way the readmore button does. -
Read More button. Rebuilt to use the same
.gm-pill--lgmarkup. Restructured the JS toggle: separate.gm-pill__labeland.gm-pill__iconspans, simplified click handler fromhtml()-rebuilding totext()swap + direct svg transform. Stripped redundant readmore structural CSS in theme.css and the per-color-case readmore rules in single.php — pill class handles both.
Status: All commits pushed to main. bb710dc (multi-fix bundle), 4293dc0 (cards subtitle override). Readmore JS changes were absorbed into a parallel session's commit bdbce7a.
Outstanding: Eric asked at end-of-session for an orchestrated entrance animation on /15-years/ (similar to home/About hero choreography). Got as far as loading the gsap-animations skill before he ran /park. Pick up next session.
2026-05-04 — Bryan May 2 animation batch + capability layout polish
Pulled Bryan's May 2 Dropbox drop into the theme: all 16 icon JSONs replaced with transparent-background versions, the missing slot 04 (Ecommerce, V03 cart re-animation) and a brand-new slot 06 (Maintenance Support) filled in, and all MP4s refreshed to latest versions. Pointed page-websites.php slots 04 and 06 at the real JSONs (they were on placeholder files in library/). Branding page and home hero already used bryan-2026-04/{slug}/data.json paths so the JSON replacement covered them automatically.
Shrunk the capability lottie ~20% on Web and Brand: desktop SVG from 16.67cqi to 13.33cqi, mobile container from 100x100 to 80x80. Reworked mobile layout so description text wraps around the icon (float: right + shape-outside: margin-box) instead of leaving an empty rectangle next to a corner-pinned icon. Required overriding .cap-list from flex to block on mobile (flex containers establish a BFC that ignores external floats) and switching brand-assets from columns: 1 to columns: auto for the same reason.
Unified the Process partial header on the Brand-style inline title + arrows row so Brand and Web look identical. When a subtitle is present (Web), it drops onto its own line below; when absent (Brand), the inline row is the whole header. Reduced the swiper's mobile bottom padding from pb-12 to pb-4 and forced text-size-h4 on the Capabilities, Why, and Process titles so they all match on mobile (Process was the only one already at the desktop H4 size).
Added a G&M logo showcase to page-playground.php (Bryan's May 2 logo style test, sized to max-w-4xl), then identified the JSON had a 1000x1000 white solid baked in as the bottom layer — it was reading as a white square on both light and dark tiles instead of being transparent like the icons. Drafted an email to Bryan asking for a re-export without the solid; waiting on his clean version. Local hand-edit reverted at park time so the repo matches what Bryan delivered until he sends the fix. Also stripped the playground page back to just the G&M showcase + Web/Brand grids (removed the Still Outstanding tracker). All work committed to main and pushed.
2026-04-30 — V8 Dev Tweaks held-row pass + soft-launch skill update
Audited Sheet1 of the V8 Dev Tweaks sheet for items in limbo and yellow-flagged six pending rows: R9 (accordion drawing line — MD), R10 (Brand-Process line off page — MD), R14 (.btn-pill-black Sky→Light Tan scope decision — ED's call), R17 + R23 (Inter font on Industries buttons + Team Single Position — paired MD question on whether to load Inter site-wide or substitute PP Mori), R52 (announcement bar limited-edition copy — MD question). Notes columns updated with Holding —/Awaiting — prefixes so the reason is glanceable.
Formalized the green/yellow convention in the /soft-launch skill. New Status Colors and Marking Items On Hold sections codify: empty = in queue, green + ED stamp = shipped, yellow + blank Completed = pending input. Lifecycle covers empty → green (happy path), empty → yellow → green (paused for input), and green → yellow → green (BR/client re-opened). Committed to skills repo as 34bfdb9.
Status: Six rows in yellow holding pattern. Four awaiting MD calls (drawing lines, line off page, Inter substitution covering R17+R23, announcement bar copy), one awaiting ED scope decision (R14 button color), one BR-paired with the Inter question. Skill update means future soft-launch sessions can mark held items consistently.
2026-04-23 — Work page hover polish + Royal MCP config fix
Post-round-2 polish pass on /work/ cards: made the whole .media a single clickable unit via a stretched-link pseudo, title + subtitle now both fade to white on hover, image scales 1.05x, and all three transitions share a unified .4s ease-out so they land together. Tracked down a subtle bug where a legacy .media a:hover { opacity: .5 } was muting the hovered text to gray — removed it. Also fixed the Royal Claude Code profile: chrome-devtools + granola MCP servers were missing from ~/.claude-royal/.claude.json (only in the default profile's config). Added them so browser-based visual QA works without switching profiles. Commits through 76d7f01, all on main.
Status: Work card hover behavior finalized. Royal profile now has parity with Claude Code default for MCP tools.
2026-04-23 — KD soft-launch, round 2
Second batch of tweaks came in on the same feedback sheet. Shipped: Content Strategy card hover overlay fix on the Websites page (CMS card was sharing grid row 7, now sits cleanly underneath); new taglines on Home orbit hero, Brand page ("We create original brands that connect with people."), and Website page ("Your website is the biggest touchpoint of your brand. Let's make it exceptional."); Branding added to the Ree & Jun scope list via ACF; Work All card descriptions rewritten from short service labels ("Website", "Branding + Website") to full one-sentence project summaries — 47 projects updated from KD's copy doc, one post (University of Nebraska) left untouched because it wasn't in the doc. ACF field label renamed from "📝 Subtitle" → "📝 Work Card Description" for admin clarity. All committed + pushed. Sheet stamped ED + green for the six completed rows.
Parked for ED review: Sheet1 R9 (accordion drawing lines — KD flagged as a possible MD design question).
Status: Round-2 dev items clear. One row waiting on Eric.
2026-04-23 — KD soft-launch feedback processed
Processed all 15 of Kristin's items from her dev checklist sheet (Sheet1 + Copy Edits). Bio social link fixes (Kristin/Brooke/Eric), contact panel confirmation CSS, home tagline swap, Privacy Policy/T&C/For Humans content rewrites (including ownership language change to "Down & DeKay, LLC dba Grain & Mortar"), branding + websites orbital bubbles reduced from 9 to 7 each with KD's new labels and descriptions, Training card updated. All committed, pushed, and live on staging. Sheet stamped row-by-row with ED + green fill. /soft-launch skill also updated to formally recognize KD and MD alongside ED + BR.
Status: Soft-launch batch clear. Awaiting Mike's Loom review on the Bryan animation options before sending feedback back to Bryan.
2026-04-23 — Bryan animation review pipeline
Downloaded Bryan Findell's April batch of 17 Lottie + 19 MP4 icon animations. Built an auto-populating review grid at /playground/ (local + staging). Ran comparison analysis: 14 of 17 Lotties are the clear winner on file size + flexibility; 01 (221 layers), 02, and 09 (embedded 7.7MB PNGs) are MP4 candidates. Per-animation format decision is on hold pending Mike's Loom review. Assets committed to assets/lottie/bryan-2026-04/ and assets/images/animations/bryan-2026-04/.
Status: Awaiting Mike's feedback on review grid before sending Bryan the consolidated note back.