diff --git a/CHANGELOG.md b/CHANGELOG.md index 8784f40..91454dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Added a `Menu Item Card` pattern (`patterns/menu/menu-item-card.php`) as the single reusable source of the mega-menu list item structure (icon well, title/description, hover-reveal trailing arrow), used across the Work, Solutions, Pricing, Insights, and About mega menus — Services is excluded, it uses its own per-phase item style. Deliberately a plain registered pattern, not a Synced Pattern, so each insertion stays independently editable per menu item (LS-1618). +- Added 6 real mega menu template parts for Ollie Menu Designer's Dropdown Menu block, each with final content, no shared placeholder scaffold: `parts/work-mega-menu.html`, `parts/solutions-mega-menu.html`, `parts/pricing-mega-menu.html`, `parts/insights-mega-menu.html`, `parts/about-mega-menu.html` (Default item styling), and `parts/services-mega-menu.html` (Service item styling, 6 lifecycle-phase columns). All registered in `theme.json` `templateParts` (LS-1618). +- Added `Mega Menu Item - Default` and `Mega Menu Item - Service` block styles (`styles/blocks/groups/mega-menu-item-default.json`, `mega-menu-item-service.json`) as the single reusable, registered source of a row's structural styling (padding, radius) — the icon well itself carries no separate style, just plain inline block attributes, so it has no independent interactive behaviour of its own. +- Added `.is-style-mega-menu-item-default` hover/focus behaviour (row background highlight + trailing arrow icon reveal) in `src/scss/animations/_menu-motion.scss`, compiled to `assets/css/animations.css`. This couldn't be expressed in the JSON style itself — WordPress's global-styles engine only generates `:hover`/`:focus` CSS for the built-in `elements` allowlist (link/button/etc.), not for arbitrary block style variations — so it's authored here instead, scoped tightly to this one selector. +- Added a `Mega Menu Panel` section style (`styles/sections/menu/mega-menu-panel.json`) plus a `shadow.popover` custom shadow token for the dropdown panel shell, and moved its border colour onto native JSON `border.color` instead of a CSS override. +- Added a `phase.discover|create|build|launch|grow|evolve` semantic colour token family (six new `phase-*` / `phase-*-strong` palette presets) for the Services mega menu's lifecycle-phase colour coding, with light-mode values darkened to meet WCAG AA 4.5:1 against the light card surface. +- Added a `text.subtle` semantic colour token (`neutral-600` light / `neutral-500` dark) for a tertiary text tier between `text.muted` and full-contrast text. - Added the Search Results template (`search.html` + `template-search.php`), a Page (No Title) custom template (`page-no-title.html` + `template-page-no-title.php`, registered in `theme.json` `customTemplates`), and a shared Taxonomy template (`taxonomy.html` + `template-taxonomy.php`) covering all four Portfolio taxonomies (LS-1226). - Extracted `front-page.html`, `index.html`, `page.html`, `single.html`, and `archive.html` into dedicated pattern files (`hero` + `front-page-latest-posts`, `template-index`, `template-page`, `template-single`, `template-archive`) so every template body is a single pattern injection, per the new template/pattern naming convention (LS-1226). - Built out `archive.html`'s main content (query title, term description, paginated post query loop), which previously rendered no content at all (LS-1226). @@ -89,11 +96,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Removed the experimental vanilla JavaScript spotlight card implementation pending GSAP evaluation. - Removed the section style contract loader for `styles/sections/*.json` runtime CSS generation. - Removed the temporary experimental button variation and its temporary selector path. +- Removed the temporary CSS/JS light-dark toggle built for the header (`inc/theme-toggle.php`, `assets/js/theme-toggle.js`, `assets/css/theme-toggle.css`, the `generate-theme-toggle` command in `theme-utils.mjs`, and the toggle button markup in `patterns/header.php`). This was a workaround built before discovering the site already has a proper, native light/dark switcher — the `ls-plugin/style-switcher` block registered by the LightSpeed Site Plugin, which reads `styles/*.json` variations directly and needs no theme-side duplicate. The header currently has no light/dark toggle until that block is wired in as follow-up work; fully recoverable from git history if needed sooner (LS-1618). ### Fixed - Fixed an invalid nested `wp:site-title` block inside `patterns/footer.php`'s paragraph markup that broke block parsing on every template (LS-1226). - Fixed `patterns/breadcrumbs.php` rendering full-bleed instead of content width by removing an unnecessary `align:full` (LS-1226). +- Fixed the header search field rendering incorrectly in the Site Editor (input shown expanded by default) by adding `assets/css/animations.css` via `add_editor_style()` in `functions.php`, so it reliably reaches the Site Editor's iframed canvas rather than only the outer wp-admin document (LS-1618). +- Fixed inconsistent column widths in the footer nav link grid (`patterns/footer.php`): the second row (Company/Studio) used a fixed `226px` column against an auto column, splitting differently than the first row's three auto-equal columns above it, so nothing lined up as a grid. Both rows now use the same auto-equal column pattern, with an empty spacer column completing the second row to three tracks (LS-1618). +- Fixed mega-menu item icon alignment across the Work, Solutions, Pricing, Insights, and About menus (31 items total): the icon, text block, and trailing arrow were direct siblings all vertically centred together, so aligning the icon to the top would have also incorrectly pushed the arrow to the top. Wrapped the text block and arrow together in their own centred group so the icon can align to the top independently while the arrow stays vertically centred against the text (LS-1618). +- Fixed the footer's phase-colour nav dots and social icons rendering black in both light and dark mode: none of their `` markup declared `fill="currentColor"`, so the browser's default SVG fill (solid black) was used instead of the semantic colour token set via their inline `color` style. Added `.site-footer .icon-container svg { fill: currentColor; }` in `src/scss/animations/_footer-motion.scss`, the same fix already used for `is-style-icon-frame-glow` and the Services card icon shell (LS-1618). ### Security diff --git a/assets/css/animations.css b/assets/css/animations.css index 2d05f20..c1f0a93 100644 --- a/assets/css/animations.css +++ b/assets/css/animations.css @@ -1155,3 +1155,408 @@ transition: none; } } +/********** Mega Menu Item **********/ +/* + * Hover/focus states for .is-style-mega-menu-item-default (styles/blocks/groups/mega-menu-item-default.json). + * WordPress's global-styles engine only generates :hover/:focus CSS for the elements.link/button/etc. + * allowlist — arbitrary block style variations never get pseudo-state rules, so this piece can't be + * expressed in the JSON style and lives here instead. Base (non-hover) styles for this row, and the + * icon well's own appearance, remain authored in theme.json/style JSON. + */ +.is-style-mega-menu-item-default { + transition: background-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); +} +.is-style-mega-menu-item-default:hover, .is-style-mega-menu-item-default:focus-within { + background-color: var(--wp--custom--color--surface--card-raised); +} +.is-style-mega-menu-item-default .wp-block-outermost-icon-block { + transition: color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); +} +.is-style-mega-menu-item-default:hover .wp-block-outermost-icon-block, .is-style-mega-menu-item-default:focus-within .wp-block-outermost-icon-block { + color: var(--wp--custom--color--text--subtle); +} + +@media (prefers-reduced-motion: reduce) { + .is-style-mega-menu-item-default, + .is-style-mega-menu-item-default .wp-block-outermost-icon-block { + transition: none; + } +} +/* + * Hover/focus states for .is-style-mega-menu-item-service (styles/blocks/groups/mega-menu-item-service.json), + * matching the Default menu's row-background convention. Same WordPress core limitation as above applies. + */ +.is-style-mega-menu-item-service { + transition: background-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); +} +.is-style-mega-menu-item-service:hover, .is-style-mega-menu-item-service:focus-within { + background-color: var(--wp--custom--color--surface--card-raised); +} + +@media (prefers-reduced-motion: reduce) { + .is-style-mega-menu-item-service { + transition: none; + } +} +/* + * Services mega menu panel structural fixes. + */ +.is-style-mega-menu-panel-services { + /* + * "Hug" the panel to its own content instead of stretching to whatever width the Ollie dropdown + * container's ancestor happens to give it. Without this, the panel's background/border render at + * the ancestor's (narrower) width while the flex-wrapped columns inside still need their full + * natural width, so content visibly overflows past the card edge. There's no theme.json dimensions + * property for width/fit-content, so this has to be CSS. + */ + width: fit-content; + max-width: 100vw; + /* + * core/columns divides its row into equal shares with no per-column minimum, so at narrower + * widths the phase labels (Discover, Create, etc.) run out of room and wrap mid-word. Neither a + * column minimum-width nor a guaranteed-no-wrap label is expressible via theme.json (dimensions + * only supports aspectRatio/minHeight, and typography has no whiteSpace property), so both are + * set here: each phase column gets a floor matching Figma's 120px minimum, wrapping onto a new + * row via flex-wrap once six no longer fit, instead of shrinking below that floor; the label text + * itself is also pinned to one line as a belt-and-suspenders guarantee. + */ +} +.is-style-mega-menu-panel-services .wp-block-columns { + flex-wrap: wrap; +} +.is-style-mega-menu-panel-services .wp-block-column { + flex: 1 1 120px; + min-width: 120px; +} + +.is-style-mega-menu-panel-services .wp-block-column > .wp-block-group p { + white-space: nowrap; +} + +/* + * Per-phase hover colour for the Services mega menu: the phase-header group (dot + label + arrow) + * and every service row underneath it hover in that same column's phase colour. Each phase always + * occupies the same column position (Discover 1st ... Evolve 6th), so this is targeted structurally + * via :nth-child rather than adding a per-instance custom property to the markup — the same custom + * hover mechanic that broke block validation earlier in this file. var(--wp--custom--color--phase--*) + * already resolves to the "strong" preset in light mode and the plain preset in dark mode, so one + * token covers both the header hover and the "Phase X strong" row hover in a single declaration. + */ +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(1) > .wp-block-group:first-child { + border-radius: var(--wp--preset--border-radius--300); + transition: background-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); +} +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(1) > .wp-block-group:first-child:hover, .is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(1) > .wp-block-group:first-child:focus-within { + background-color: color-mix(in srgb, var(--wp--custom--color--phase--discover) 15%, transparent); +} +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(1) .is-style-mega-menu-item-service:hover, .is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(1) .is-style-mega-menu-item-service:focus-within { + background-color: color-mix(in srgb, var(--wp--custom--color--phase--discover) 15%, transparent); +} +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(1) .is-style-mega-menu-item-service:hover a, .is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(1) .is-style-mega-menu-item-service:focus-within a { + color: var(--wp--custom--color--phase--discover); +} + +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(2) > .wp-block-group:first-child { + border-radius: var(--wp--preset--border-radius--300); + transition: background-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); +} +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(2) > .wp-block-group:first-child:hover, .is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(2) > .wp-block-group:first-child:focus-within { + background-color: color-mix(in srgb, var(--wp--custom--color--phase--create) 15%, transparent); +} +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(2) .is-style-mega-menu-item-service:hover, .is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(2) .is-style-mega-menu-item-service:focus-within { + background-color: color-mix(in srgb, var(--wp--custom--color--phase--create) 15%, transparent); +} +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(2) .is-style-mega-menu-item-service:hover a, .is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(2) .is-style-mega-menu-item-service:focus-within a { + color: var(--wp--custom--color--phase--create); +} + +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(3) > .wp-block-group:first-child { + border-radius: var(--wp--preset--border-radius--300); + transition: background-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); +} +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(3) > .wp-block-group:first-child:hover, .is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(3) > .wp-block-group:first-child:focus-within { + background-color: color-mix(in srgb, var(--wp--custom--color--phase--build) 15%, transparent); +} +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(3) .is-style-mega-menu-item-service:hover, .is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(3) .is-style-mega-menu-item-service:focus-within { + background-color: color-mix(in srgb, var(--wp--custom--color--phase--build) 15%, transparent); +} +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(3) .is-style-mega-menu-item-service:hover a, .is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(3) .is-style-mega-menu-item-service:focus-within a { + color: var(--wp--custom--color--phase--build); +} + +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(4) > .wp-block-group:first-child { + border-radius: var(--wp--preset--border-radius--300); + transition: background-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); +} +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(4) > .wp-block-group:first-child:hover, .is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(4) > .wp-block-group:first-child:focus-within { + background-color: color-mix(in srgb, var(--wp--custom--color--phase--launch) 15%, transparent); +} +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(4) .is-style-mega-menu-item-service:hover, .is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(4) .is-style-mega-menu-item-service:focus-within { + background-color: color-mix(in srgb, var(--wp--custom--color--phase--launch) 15%, transparent); +} +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(4) .is-style-mega-menu-item-service:hover a, .is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(4) .is-style-mega-menu-item-service:focus-within a { + color: var(--wp--custom--color--phase--launch); +} + +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(5) > .wp-block-group:first-child { + border-radius: var(--wp--preset--border-radius--300); + transition: background-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); +} +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(5) > .wp-block-group:first-child:hover, .is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(5) > .wp-block-group:first-child:focus-within { + background-color: color-mix(in srgb, var(--wp--custom--color--phase--grow) 15%, transparent); +} +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(5) .is-style-mega-menu-item-service:hover, .is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(5) .is-style-mega-menu-item-service:focus-within { + background-color: color-mix(in srgb, var(--wp--custom--color--phase--grow) 15%, transparent); +} +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(5) .is-style-mega-menu-item-service:hover a, .is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(5) .is-style-mega-menu-item-service:focus-within a { + color: var(--wp--custom--color--phase--grow); +} + +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(6) > .wp-block-group:first-child { + border-radius: var(--wp--preset--border-radius--300); + transition: background-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); +} +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(6) > .wp-block-group:first-child:hover, .is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(6) > .wp-block-group:first-child:focus-within { + background-color: color-mix(in srgb, var(--wp--custom--color--phase--evolve) 15%, transparent); +} +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(6) .is-style-mega-menu-item-service:hover, .is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(6) .is-style-mega-menu-item-service:focus-within { + background-color: color-mix(in srgb, var(--wp--custom--color--phase--evolve) 15%, transparent); +} +.is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(6) .is-style-mega-menu-item-service:hover a, .is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(6) .is-style-mega-menu-item-service:focus-within a { + color: var(--wp--custom--color--phase--evolve); +} + +@media (prefers-reduced-motion: reduce) { + .is-style-mega-menu-panel-services .wp-block-column > .wp-block-group:first-child { + transition: none; + } +} +/********** Site Footer **********/ +/* + * "LightSpeed notes" badge: a flex group with no explicit width constraint defaults to filling + * its row, so the border/background stretch across the notes panel instead of hugging the label + * text. There's no theme.json dimensions property for width/fit-content, so this has to be CSS — + * same fix as the Services mega menu panel. + */ +.footer-notes-badge { + width: fit-content; +} + +/* + * Decorative background: top edge glow bar + ambient radial-gradient glow behind the footer. + * Authored as layered CSS gradients rather than embedding Figma's raw multi-layer SVG data-URIs, + * which would be extremely brittle to maintain. Every colour route through the same semantic + * custom properties used everywhere else in the theme (phase.create, effect.spotlight), so the + * glow automatically tones itself down under the light global-styles variation instead of needing + * a separate light/dark branch — there's no runtime class/attribute toggle in this theme, dark mode + * is a full alternate theme.json variation, so re-resolving the same custom properties is enough. + */ +.site-footer { + position: relative; + overflow: clip; + background: radial-gradient(ellipse 480px 420px at 12% 0%, color-mix(in srgb, var(--wp--custom--color--effect--spotlight--primary) 16%, transparent) 0%, transparent 60%), radial-gradient(ellipse 460px 400px at 92% 22%, color-mix(in srgb, var(--wp--custom--color--phase--create) 12%, transparent) 0%, transparent 60%), var(--wp--custom--color--surface--canvas); +} +.site-footer::before { + content: ""; + position: absolute; + inset-block-start: 0; + inset-inline: 0; + block-size: 4px; + z-index: var(--wp--custom--z-index--content); + background-image: linear-gradient(90deg, transparent 0%, color-mix(in srgb, var(--wp--custom--color--phase--create) 60%, transparent) 24%, var(--wp--custom--color--phase--create) 50%, color-mix(in srgb, var(--wp--custom--color--phase--create) 60%, transparent) 76%, transparent 100%); + box-shadow: 0 0 16px 0 color-mix(in srgb, var(--wp--custom--color--phase--create) 70%, transparent), 0 8px 32px 0 color-mix(in srgb, var(--wp--custom--color--phase--create) 30%, transparent); +} + +/* + * Blurred accent blob behind the nav-column grid, echoing Figma's "Mask Group" glow. Purely + * decorative and non-interactive, so it's safe to skip under reduced motion (nothing here + * animates — it's a static blur, included in the reduced-motion block only for parity/consistency). + * Targets the explicit .site-footer__columns class rather than :nth-of-type(2) — that selector + * counted by tag name among siblings sharing a parent, not a global count of wp-block-columns, so + * it was also accidentally matching the nested Company/Studio sub-grid two levels down. + */ +.site-footer__columns { + position: relative; +} +.site-footer__columns::after { + content: ""; + position: absolute; + inset-block-start: 10%; + inset-inline-end: 8%; + inline-size: min(38vw, 520px); + block-size: min(30vw, 360px); + background: radial-gradient(ellipse closest-side, color-mix(in srgb, var(--wp--custom--color--phase--create) 14%, transparent) 0%, transparent 70%); + filter: blur(40px); + pointer-events: none; + z-index: 0; +} +.site-footer__columns > * { + position: relative; + z-index: 1; +} + +/* + * Icon Block SVGs (the phase-colour dots beside each nav-column heading, the "Available for + * selected projects" checkmark, and the social icons) render with the browser's default SVG fill + * — solid black — because none of their markup declares fill="currentColor". That means the + * `color` set via their inline style (the semantic phase/text colour token) was never actually + * reaching the icon glyph, in either light or dark mode. Same fix already applied to + * is-style-icon-frame-glow and the Services card icon shell elsewhere in this file family. + */ +.site-footer .icon-container svg { + fill: currentColor; +} + +/* + * Footer nav links (is-style-footer-nav-link, styles/blocks/paragraphs/footer-nav-link.json): + * underline reveals on hover/focus by animating decoration-colour from transparent, rather than + * toggling text-decoration-line itself. Matches the approved reference screenshot, and matches the + * pattern already used for is-style-link-underline-accent elsewhere in this file family. + */ +.is-style-footer-nav-link a { + color: inherit; + text-decoration-line: underline; + text-decoration-color: transparent; + text-underline-offset: 3px; + transition: color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard), text-decoration-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); +} + +.is-style-footer-nav-link a:hover, +.is-style-footer-nav-link a:focus-visible { + color: var(--wp--custom--color--phase--create); + text-decoration-color: var(--wp--custom--color--phase--create); +} + +/* + * Proof-point card (styles/blocks/groups/footer-proof-card.json): base structural CSS — the JSON + * file documents this shape but was never actually implemented as real CSS anywhere (these style + * variation JSON files aren't auto-consumed by WordPress, see AGENTS.md). Hover lift matches the + * rest of the theme's card-hover conventions; no hover state shown in the Figma reference — added + * per explicit approval as a consistency default. + */ +.is-style-footer-proof-card { + background-color: var(--wp--custom--color--surface--card); + border: 1px solid var(--wp--custom--color--border--card); + border-radius: var(--wp--preset--border-radius--300); + padding: var(--wp--preset--spacing--20); + transition: background-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard), border-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); +} +.is-style-footer-proof-card:hover, .is-style-footer-proof-card:focus-within { + background-color: var(--wp--custom--color--surface--card-raised); + border-color: var(--wp--custom--color--phase--create); +} + +/* + * Social icon circle (styles/blocks/groups/footer-social-icon.json): same missing-base-CSS gap as + * above. min-inline-size and min-block-size are both set explicitly and equal — a border-radius + * intended to make a circle only works if the box is actually square first; without a matching + * min-block-size, the box's height was left to flex/content sizing, producing an elongated pill + * instead of a circle on both desktop and mobile. + */ +.is-style-footer-social-icon { + display: flex; + align-items: center; + justify-content: center; + min-inline-size: 44px; + min-block-size: 44px; + padding: var(--wp--preset--spacing--10); + border: 1px solid var(--wp--custom--color--border--card); + border-radius: var(--wp--preset--border-radius--500); + background-color: var(--wp--custom--color--surface--card); + transition: background-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard), border-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); +} +.is-style-footer-social-icon:hover, .is-style-footer-social-icon:focus-within { + background-color: var(--wp--custom--color--surface--card-raised); + border-color: var(--wp--custom--color--phase--create); +} + +@media (prefers-reduced-motion: reduce) { + .is-style-footer-nav-link a, + .is-style-footer-proof-card, + .is-style-footer-social-icon { + transition: none; + } +} +/********** Site Header **********/ +/* + * Header icon buttons (search, light/dark toggle) and the gradient CTA. The base circular-button + * shell (border/background/sizing) matches styles/blocks/groups/header-icon-button.json — kept + * here rather than as a registered block style because it needs to sit alongside the hover + * treatment, and WordPress doesn't generate :hover CSS for arbitrary block style variations. + */ +.is-style-header-icon-button { + display: flex; + align-items: center; + justify-content: center; + min-inline-size: 44px; + min-block-size: 44px; + padding: var(--wp--preset--spacing--10); + border: 1px solid var(--wp--custom--color--border--card); + border-radius: var(--wp--preset--border-radius--500); + background-color: color-mix(in srgb, var(--wp--custom--color--surface--highlight) 4%, transparent); + color: var(--wp--custom--color--text--default); + transition: background-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard), border-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); +} +.is-style-header-icon-button:hover, .is-style-header-icon-button:focus-within { + background-color: var(--wp--custom--color--surface--card-raised); + border-color: var(--wp--custom--color--phase--create); +} + +.is-style-button-cta-gradient .wp-block-button__link { + transition: transform var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard), box-shadow var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); +} +.is-style-button-cta-gradient .wp-block-button__link:hover, .is-style-button-cta-gradient .wp-block-button__link:focus-visible { + transform: translateY(-1px); + box-shadow: var(--wp--custom--shadow--interactive--accent), var(--wp--custom--shadow--elevation--300); +} + +/* + * Header search (core/search, buttonPosition: button-only): the input is collapsed to 0 width by + * default and expands via the .site-header__search--expanded class. core/search's "button-only" + * position only changes layout (it hides the input and renders just a submit button) — there's no + * built-in click-to-expand behaviour in core, and a pure-CSS :focus-within trick can't reveal a + * zero-width input either (nothing to click into until it's already visible). The class is toggled + * by assets/js/header-search.js, which intercepts the button's first click to expand + focus the + * field instead of submitting immediately. + */ +.site-header__search .wp-block-search__button { + display: flex; + align-items: center; + justify-content: center; + min-inline-size: 44px; + min-block-size: 44px; + padding: var(--wp--preset--spacing--10); + border: 1px solid var(--wp--custom--color--border--card); + border-radius: var(--wp--preset--border-radius--500); + background-color: color-mix(in srgb, var(--wp--custom--color--surface--highlight) 4%, transparent); + color: var(--wp--custom--color--text--default); + transition: background-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard), border-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); +} +.site-header__search .wp-block-search__button:hover, +.site-header__search .wp-block-search__button:focus-visible { + background-color: var(--wp--custom--color--surface--card-raised); + border-color: var(--wp--custom--color--phase--create); +} +.site-header__search .wp-block-search__input { + inline-size: 0; + min-inline-size: 0; + padding-inline: 0; + border-width: 0; + opacity: 0; + transition: inline-size var(--wp--custom--animation--duration--medium) var(--wp--custom--animation--easing--standard), opacity var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard), padding-inline var(--wp--custom--animation--duration--medium) var(--wp--custom--animation--easing--standard); +} +.site-header__search.site-header__search--expanded .wp-block-search__input { + inline-size: 12rem; + padding-inline: var(--wp--preset--spacing--10); + border-width: 1px; + opacity: 1; +} + +@media (prefers-reduced-motion: reduce) { + .is-style-header-icon-button, + .is-style-button-cta-gradient .wp-block-button__link, + .site-header__search .wp-block-search__button, + .site-header__search .wp-block-search__input { + transition: none; + } +} diff --git a/assets/js/header-search.js b/assets/js/header-search.js new file mode 100644 index 0000000..009ef1b --- /dev/null +++ b/assets/js/header-search.js @@ -0,0 +1,70 @@ +/** + * Header search expand-on-click. + * + * core/search in "button-only" position renders just a submit button with the input hidden — + * there is no built-in core behavior to reveal and focus that input on click. A pure-CSS + * :focus-within trick can't do it either, since there's nothing visible to click into until the + * input is already revealed. This intercepts the button's first click to expand + focus the field + * instead of submitting immediately; a second click (now that the field has focus) submits + * normally, matching standard expand-to-search UX. + * + * The collapsed input is zero-width/invisible via CSS but stays in the DOM, so without help it + * would still sit in the natural tab order — a keyboard user tabbing past the visible button would + * land on a control they can't see or expand (expansion is click-driven, no keyboard-only path + * exists). tabindex="-1" is applied while collapsed to skip it, and cleared once expanded so it + * behaves like a normal focusable field again. + */ +( function () { + 'use strict'; + + var EXPANDED_CLASS = 'site-header__search--expanded'; + + function collapseInput( input ) { + input.setAttribute( 'tabindex', '-1' ); + } + + function expandInput( input ) { + input.removeAttribute( 'tabindex' ); + } + + document.querySelectorAll( '.site-header__search .wp-block-search__input' ).forEach( collapseInput ); + + document.addEventListener( 'click', function ( event ) { + var button = event.target.closest( '.site-header__search .wp-block-search__button' ); + if ( ! button ) { + return; + } + + var container = button.closest( '.site-header__search' ); + if ( ! container || container.classList.contains( EXPANDED_CLASS ) ) { + return; + } + + event.preventDefault(); + container.classList.add( EXPANDED_CLASS ); + + var input = container.querySelector( '.wp-block-search__input' ); + if ( input ) { + expandInput( input ); + input.focus(); + } + } ); + + document.addEventListener( 'focusout', function ( event ) { + var container = event.target.closest && event.target.closest( '.site-header__search' ); + if ( ! container ) { + return; + } + // Wait a tick so focus can land on the next element inside the same container (e.g. the + // button itself) before deciding the field has genuinely lost focus. + window.setTimeout( function () { + if ( ! container.contains( document.activeElement ) ) { + container.classList.remove( EXPANDED_CLASS ); + var input = container.querySelector( '.wp-block-search__input' ); + if ( input ) { + collapseInput( input ); + } + } + }, 0 ); + } ); +} )(); diff --git a/functions.php b/functions.php index e9eee83..d1e7e1e 100644 --- a/functions.php +++ b/functions.php @@ -18,6 +18,9 @@ /** Loads the presets integration files */ require get_template_directory() . '/inc/presets.php'; +/** Loads site header assets */ +require get_template_directory() . '/inc/header.php'; + /** * Sets up theme supports. */ @@ -31,8 +34,11 @@ function ls_theme_setup() { // Add support for editor styles. add_theme_support( 'editor-styles' ); - // Enqueue editor styles. + // Enqueue editor styles. animations.css must be listed here (not just enqueued via + // enqueue_block_editor_assets) so the header/footer interactive-control CSS — the collapsed + // search field, the icon-toggle button shell — reliably reaches the Site Editor's iframed canvas. add_editor_style( 'style.css' ); + add_editor_style( 'assets/css/animations.css' ); } add_action( 'after_setup_theme', 'ls_theme_setup' ); diff --git a/inc/header.php b/inc/header.php new file mode 100644 index 0000000..361f359 --- /dev/null +++ b/inc/header.php @@ -0,0 +1,26 @@ + +
+
+
+

About

+ + + +

Who we are and what we commit to.

+
+ + + + +
+ + + +
+
+
+
+
+
+ + + +
+
+
Why LightSpeed
+ + + +

The thinking behind a specialist WordPress and WooCommerce partner.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
Getting started
+ + + +

What the first conversation produces and the route into delivery.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
AI governance
+ + + +

How we handle AI tools, data and editorial responsibility.

+
+ + + +
+
+
+
+ + + +
+
+
+
+
+ + + +
+
+
Our process
+ + + +

Six lifecycle stages — Discover, Create, Build, Launch, Grow, Evolve.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
Guarantees
+ + + +

What we commit to before, during and after launch.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
Accessibility
+ + + +

Our accessibility statement and how we work to WCAG 2.2 AA.

+
+ + + +
+
+
+
+
+ + + +
+

Prefer to talk?

+ + + + +
+
+ diff --git a/parts/insights-mega-menu.html b/parts/insights-mega-menu.html new file mode 100644 index 0000000..482ea57 --- /dev/null +++ b/parts/insights-mega-menu.html @@ -0,0 +1,177 @@ + +
+
+
+

Insights

+ + + +

Writing, notes and resources from real engagements.

+
+ + + + +
+ + + +
+
+
+
+
+
+ + + +
+
+
Block themes & FSE
+ + + +

Notes on running production sites on block-first WordPress.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
Design systems
+ + + +

theme.json, patterns and reusable visual language for editors.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
Migrations & rebuilds
+ + + +

How we plan replatforming as risk management.

+
+ + + +
+
+
+
+ + + +
+
+
+
+
+ + + +
+
+
WooCommerce in depth
+ + + +

Subscriptions, performance and store operations at scale.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
AI readiness
+ + + +

Governance, content structure and search before any AI add-ons.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
Resources & guides
+ + + +

Practical checklists, briefs and downloadable references.

+
+ + + +
+
+
+
+
+ + + +
+

Want it in your inbox?

+ + + + +
+
+ diff --git a/parts/pricing-mega-menu.html b/parts/pricing-mega-menu.html new file mode 100644 index 0000000..8c4aacf --- /dev/null +++ b/parts/pricing-mega-menu.html @@ -0,0 +1,177 @@ + +
+
+
+

Pricing

+ + + +

Find where you are likely to fit.

+
+ + + + +
+ + + +
+
+
+
+
+
+ + + +
+
+
Foundation
+ + + +

A cleaner platform baseline for teams resetting their site.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
Enterprise
+ + + +

Larger orgs where governance and integrations matter more deeply.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
Website packages
+ + + +

The three routes side-by-side, with scope and outcomes.

+
+ + + +
+
+
+
+ + + +
+
+
+
+
+ + + +
+
+
Growth
+ + + +

For organisations with traction that need the platform to support more.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
How we price work
+ + + +

The principles behind a LightSpeed engagement, not a price grid.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
Guarantees
+ + + +

What we commit to before, during and after launch.

+
+ + + +
+
+
+
+
+ + + +
+

Need a tailored estimate?

+ + + + +
+
+ diff --git a/parts/services-mega-menu.html b/parts/services-mega-menu.html new file mode 100644 index 0000000..432d17e --- /dev/null +++ b/parts/services-mega-menu.html @@ -0,0 +1,177 @@ + +
+
+
+

Services by lifecycle phase

+ + + +

Services that span the WordPress lifecycle grouped by phase.

+
+ + + + +
+ + + +
+
+
+
+ + + +

Discover

+ + + +
+
+ + + +

Discovery

+
+ + + +
+
+
+ + + +

Create

+ + + +
+
+ + + +

Content

+ + + +

Design

+
+ + + +
+
+
+ + + +

Build

+ + + +
+
+ + + +

Development

+ + + +

Migrations

+
+ + + +
+
+
+ + + +

Launch

+ + + +
+
+ + + +

Hosting

+ + + +

Performance

+ + + +

Security

+ + + +

Training

+
+ + + +
+
+
+ + + +

Grow

+ + + +
+
+ + + +

Support

+ + + +

SEO

+ + + +

Accessibility

+ + + +

Email marketing

+
+ + + +
+
+
+ + + +

Evolve

+
+ + + +

AI

+
+
+ + + +
+

Each service is colour-coded by its lifecycle phase

+ + + + +
+
+ diff --git a/parts/solutions-mega-menu.html b/parts/solutions-mega-menu.html new file mode 100644 index 0000000..a2229c5 --- /dev/null +++ b/parts/solutions-mega-menu.html @@ -0,0 +1,191 @@ + +
+
+
+

Solutions

+ + + +

Pick a route by the problem you're solving for.

+
+ + + + +
+ + + +
+
+
+
+
+
+ + + +
+
+
WordPress
+ + + +

A stronger platform foundation, cleaner structure and more long-term control.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
Publishing
+ + + +

For editorial platforms dealing with scale, structure and long-term maintainability.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
AI
+ + + +

For teams preparing content, governance and platform structure for deliberate AI use.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
AI Chatbots
+ + + +

For teams considering chatbot delivery once content, governance and escalation routes are in place.

+
+ + + +
+
+
+
+ + + +
+
+
+
+
+ + + +
+
+
WooCommerce
+ + + +

For teams managing product complexity, subscriptions and ecommerce operational pressure.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
Tour Operators
+ + + +

For travel websites that need rich content, clearer booking journeys and operational clarity.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
Design Systems
+ + + +

For teams that need stronger consistency between content, design and implementation.

+
+ + + +
+
+
+
+
+
+ diff --git a/parts/work-mega-menu.html b/parts/work-mega-menu.html new file mode 100644 index 0000000..078293a --- /dev/null +++ b/parts/work-mega-menu.html @@ -0,0 +1,177 @@ + +
+
+
+

Work

+ + + +

Real platform work, not portfolio decoration.

+
+ + + + +
+ + + +
+
+
+
+
+
+ + + +
+
+
Travel publisher rebuild
+ + + +

Block-first WordPress for a high-volume travel publisher.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
Design system rollout
+ + + +

Reusable patterns and theme.json discipline across products.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
All case studies
+ + + +

Every engagement, with the business context up front.

+
+ + + +
+
+
+
+ + + +
+
+
+
+
+ + + +
+
+
Subscriptions reset
+ + + +

WooCommerce Subscriptions, performance and self-serve.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
Migration care
+ + + +

Replatforming as risk management, not a content move.

+
+ + + +
+
+
+ + + +
+
+
+
+ + + +
+
+
Testimonials
+ + + +

Approved client praise — names, roles, companies.

+
+ + + +
+
+
+
+
+ + + +
+

Starting a project?

+ + + + +
+
+ diff --git a/patterns/footer.php b/patterns/footer.php index fef0ee2..5a8bd13 100644 --- a/patterns/footer.php +++ b/patterns/footer.php @@ -4,19 +4,313 @@ * Slug: ls-theme/footer * Categories: footer * Block Types: core/template-part/footer - * Description: Footer columns with logo, title, tagline and links. + * Description: Full site footer — editorial notes panel, company summary with proof points, 5-column link grid, and legal/social bottom bar. */ ?> - - + + diff --git a/patterns/header.php b/patterns/header.php index b49d3b8..80b12b9 100644 --- a/patterns/header.php +++ b/patterns/header.php @@ -4,18 +4,29 @@ * Slug: ls-theme/header * Categories: header * Block Types: core/template-part/header - * Description: Site header with site title and navigation. + * Description: Site header — logo, primary navigation, search, light/dark toggle, and "Start a project" CTA. */ ?> - - + + diff --git a/patterns/menu/menu-item-card.php b/patterns/menu/menu-item-card.php new file mode 100644 index 0000000..30823e6 --- /dev/null +++ b/patterns/menu/menu-item-card.php @@ -0,0 +1,44 @@ + + +
+ +
+ +
+ +
+ + + +
+ +
+ +
+ + + +

+ +
+ + + +
+ +
+ +
+ diff --git a/src/scss/animations.scss b/src/scss/animations.scss index 4540db6..17fc0c5 100644 --- a/src/scss/animations.scss +++ b/src/scss/animations.scss @@ -4,4 +4,7 @@ @use "animations/details-motion"; @use "animations/card-motion"; @use "animations/button-motion"; -@use "animations/faq-motion"; \ No newline at end of file +@use "animations/faq-motion"; +@use "animations/menu-motion"; +@use "animations/footer-motion"; +@use "animations/header-motion"; \ No newline at end of file diff --git a/src/scss/animations/_footer-motion.scss b/src/scss/animations/_footer-motion.scss new file mode 100644 index 0000000..5927b69 --- /dev/null +++ b/src/scss/animations/_footer-motion.scss @@ -0,0 +1,183 @@ +@use "../abstracts/mixins/motion"; + +/********** Site Footer **********/ + +/* + * "LightSpeed notes" badge: a flex group with no explicit width constraint defaults to filling + * its row, so the border/background stretch across the notes panel instead of hugging the label + * text. There's no theme.json dimensions property for width/fit-content, so this has to be CSS — + * same fix as the Services mega menu panel. + */ +.footer-notes-badge { + width: fit-content; +} + +/* + * Decorative background: top edge glow bar + ambient radial-gradient glow behind the footer. + * Authored as layered CSS gradients rather than embedding Figma's raw multi-layer SVG data-URIs, + * which would be extremely brittle to maintain. Every colour route through the same semantic + * custom properties used everywhere else in the theme (phase.create, effect.spotlight), so the + * glow automatically tones itself down under the light global-styles variation instead of needing + * a separate light/dark branch — there's no runtime class/attribute toggle in this theme, dark mode + * is a full alternate theme.json variation, so re-resolving the same custom properties is enough. + */ +.site-footer { + position: relative; + overflow: clip; + background: + radial-gradient( + ellipse 480px 420px at 12% 0%, + color-mix(in srgb, var(--wp--custom--color--effect--spotlight--primary) 16%, transparent) 0%, + transparent 60% + ), + radial-gradient( + ellipse 460px 400px at 92% 22%, + color-mix(in srgb, var(--wp--custom--color--phase--create) 12%, transparent) 0%, + transparent 60% + ), + var(--wp--custom--color--surface--canvas); + + &::before { + content: ""; + position: absolute; + inset-block-start: 0; + inset-inline: 0; + block-size: 4px; + z-index: var(--wp--custom--z-index--content); + background-image: linear-gradient( + 90deg, + transparent 0%, + color-mix(in srgb, var(--wp--custom--color--phase--create) 60%, transparent) 24%, + var(--wp--custom--color--phase--create) 50%, + color-mix(in srgb, var(--wp--custom--color--phase--create) 60%, transparent) 76%, + transparent 100% + ); + box-shadow: + 0 0 16px 0 color-mix(in srgb, var(--wp--custom--color--phase--create) 70%, transparent), + 0 8px 32px 0 color-mix(in srgb, var(--wp--custom--color--phase--create) 30%, transparent); + } +} + +/* + * Blurred accent blob behind the nav-column grid, echoing Figma's "Mask Group" glow. Purely + * decorative and non-interactive, so it's safe to skip under reduced motion (nothing here + * animates — it's a static blur, included in the reduced-motion block only for parity/consistency). + * Targets the explicit .site-footer__columns class rather than :nth-of-type(2) — that selector + * counted by tag name among siblings sharing a parent, not a global count of wp-block-columns, so + * it was also accidentally matching the nested Company/Studio sub-grid two levels down. + */ +.site-footer__columns { + position: relative; + + &::after { + content: ""; + position: absolute; + inset-block-start: 10%; + inset-inline-end: 8%; + inline-size: min(38vw, 520px); + block-size: min(30vw, 360px); + background: radial-gradient( + ellipse closest-side, + color-mix(in srgb, var(--wp--custom--color--phase--create) 14%, transparent) 0%, + transparent 70% + ); + filter: blur(40px); + pointer-events: none; + z-index: 0; + } + + > * { + position: relative; + z-index: 1; + } +} + +/* + * Icon Block SVGs (the phase-colour dots beside each nav-column heading, the "Available for + * selected projects" checkmark, and the social icons) render with the browser's default SVG fill + * — solid black — because none of their markup declares fill="currentColor". That means the + * `color` set via their inline style (the semantic phase/text colour token) was never actually + * reaching the icon glyph, in either light or dark mode. Same fix already applied to + * is-style-icon-frame-glow and the Services card icon shell elsewhere in this file family. + */ +.site-footer .icon-container svg { + fill: currentColor; +} + +/* + * Footer nav links (is-style-footer-nav-link, styles/blocks/paragraphs/footer-nav-link.json): + * underline reveals on hover/focus by animating decoration-colour from transparent, rather than + * toggling text-decoration-line itself. Matches the approved reference screenshot, and matches the + * pattern already used for is-style-link-underline-accent elsewhere in this file family. + */ +.is-style-footer-nav-link a { + color: inherit; + text-decoration-line: underline; + text-decoration-color: transparent; + text-underline-offset: 3px; + transition: color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard), + text-decoration-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); +} + +.is-style-footer-nav-link a:hover, +.is-style-footer-nav-link a:focus-visible { + color: var(--wp--custom--color--phase--create); + text-decoration-color: var(--wp--custom--color--phase--create); +} + +/* + * Proof-point card (styles/blocks/groups/footer-proof-card.json): base structural CSS — the JSON + * file documents this shape but was never actually implemented as real CSS anywhere (these style + * variation JSON files aren't auto-consumed by WordPress, see AGENTS.md). Hover lift matches the + * rest of the theme's card-hover conventions; no hover state shown in the Figma reference — added + * per explicit approval as a consistency default. + */ +.is-style-footer-proof-card { + background-color: var(--wp--custom--color--surface--card); + border: 1px solid var(--wp--custom--color--border--card); + border-radius: var(--wp--preset--border-radius--300); + padding: var(--wp--preset--spacing--20); + transition: background-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard), + border-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); + + &:hover, + &:focus-within { + background-color: var(--wp--custom--color--surface--card-raised); + border-color: var(--wp--custom--color--phase--create); + } +} + +/* + * Social icon circle (styles/blocks/groups/footer-social-icon.json): same missing-base-CSS gap as + * above. min-inline-size and min-block-size are both set explicitly and equal — a border-radius + * intended to make a circle only works if the box is actually square first; without a matching + * min-block-size, the box's height was left to flex/content sizing, producing an elongated pill + * instead of a circle on both desktop and mobile. + */ +.is-style-footer-social-icon { + display: flex; + align-items: center; + justify-content: center; + min-inline-size: 44px; + min-block-size: 44px; + padding: var(--wp--preset--spacing--10); + border: 1px solid var(--wp--custom--color--border--card); + border-radius: var(--wp--preset--border-radius--500); + background-color: var(--wp--custom--color--surface--card); + transition: background-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard), + border-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); + + &:hover, + &:focus-within { + background-color: var(--wp--custom--color--surface--card-raised); + border-color: var(--wp--custom--color--phase--create); + } +} + +@include motion.reduced-motion { + .is-style-footer-nav-link a, + .is-style-footer-proof-card, + .is-style-footer-social-icon { + transition: none; + } +} diff --git a/src/scss/animations/_header-motion.scss b/src/scss/animations/_header-motion.scss new file mode 100644 index 0000000..0228da4 --- /dev/null +++ b/src/scss/animations/_header-motion.scss @@ -0,0 +1,100 @@ +@use "../abstracts/mixins/motion"; + +/********** Site Header **********/ + +/* + * Header icon buttons (search, light/dark toggle) and the gradient CTA. The base circular-button + * shell (border/background/sizing) matches styles/blocks/groups/header-icon-button.json — kept + * here rather than as a registered block style because it needs to sit alongside the hover + * treatment, and WordPress doesn't generate :hover CSS for arbitrary block style variations. + */ +.is-style-header-icon-button { + display: flex; + align-items: center; + justify-content: center; + min-inline-size: 44px; + min-block-size: 44px; + padding: var(--wp--preset--spacing--10); + border: 1px solid var(--wp--custom--color--border--card); + border-radius: var(--wp--preset--border-radius--500); + background-color: color-mix(in srgb, var(--wp--custom--color--surface--highlight) 4%, transparent); + color: var(--wp--custom--color--text--default); + transition: background-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard), + border-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); + + &:hover, + &:focus-within { + background-color: var(--wp--custom--color--surface--card-raised); + border-color: var(--wp--custom--color--phase--create); + } +} + +.is-style-button-cta-gradient .wp-block-button__link { + transition: transform var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard), + box-shadow var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); + + &:hover, + &:focus-visible { + transform: translateY(-1px); + box-shadow: var(--wp--custom--shadow--interactive--accent), var(--wp--custom--shadow--elevation--300); + } +} + +/* + * Header search (core/search, buttonPosition: button-only): the input is collapsed to 0 width by + * default and expands via the .site-header__search--expanded class. core/search's "button-only" + * position only changes layout (it hides the input and renders just a submit button) — there's no + * built-in click-to-expand behaviour in core, and a pure-CSS :focus-within trick can't reveal a + * zero-width input either (nothing to click into until it's already visible). The class is toggled + * by assets/js/header-search.js, which intercepts the button's first click to expand + focus the + * field instead of submitting immediately. + */ +.site-header__search { + .wp-block-search__button { + display: flex; + align-items: center; + justify-content: center; + min-inline-size: 44px; + min-block-size: 44px; + padding: var(--wp--preset--spacing--10); + border: 1px solid var(--wp--custom--color--border--card); + border-radius: var(--wp--preset--border-radius--500); + background-color: color-mix(in srgb, var(--wp--custom--color--surface--highlight) 4%, transparent); + color: var(--wp--custom--color--text--default); + transition: background-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard), + border-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); + } + + .wp-block-search__button:hover, + .wp-block-search__button:focus-visible { + background-color: var(--wp--custom--color--surface--card-raised); + border-color: var(--wp--custom--color--phase--create); + } + + .wp-block-search__input { + inline-size: 0; + min-inline-size: 0; + padding-inline: 0; + border-width: 0; + opacity: 0; + transition: inline-size var(--wp--custom--animation--duration--medium) var(--wp--custom--animation--easing--standard), + opacity var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard), + padding-inline var(--wp--custom--animation--duration--medium) var(--wp--custom--animation--easing--standard); + } + + &.site-header__search--expanded .wp-block-search__input { + inline-size: 12rem; + padding-inline: var(--wp--preset--spacing--10); + border-width: 1px; + opacity: 1; + } +} + +@include motion.reduced-motion { + .is-style-header-icon-button, + .is-style-button-cta-gradient .wp-block-button__link, + .site-header__search .wp-block-search__button, + .site-header__search .wp-block-search__input { + transition: none; + } +} diff --git a/src/scss/animations/_menu-motion.scss b/src/scss/animations/_menu-motion.scss new file mode 100644 index 0000000..ea3b600 --- /dev/null +++ b/src/scss/animations/_menu-motion.scss @@ -0,0 +1,150 @@ +@use "sass:list"; +@use "../abstracts/mixins/motion"; + +/********** Mega Menu Item **********/ + +/* + * Hover/focus states for .is-style-mega-menu-item-default (styles/blocks/groups/mega-menu-item-default.json). + * WordPress's global-styles engine only generates :hover/:focus CSS for the elements.link/button/etc. + * allowlist — arbitrary block style variations never get pseudo-state rules, so this piece can't be + * expressed in the JSON style and lives here instead. Base (non-hover) styles for this row, and the + * icon well's own appearance, remain authored in theme.json/style JSON. + */ +.is-style-mega-menu-item-default { + transition: background-color var(--wp--custom--animation--duration--base) + var(--wp--custom--animation--easing--standard); + + &:hover, + &:focus-within { + background-color: var(--wp--custom--color--surface--card-raised); + } + + .wp-block-outermost-icon-block { + transition: color var(--wp--custom--animation--duration--base) + var(--wp--custom--animation--easing--standard); + } + + &:hover .wp-block-outermost-icon-block, + &:focus-within .wp-block-outermost-icon-block { + color: var(--wp--custom--color--text--subtle); + } +} + +@include motion.reduced-motion { + .is-style-mega-menu-item-default, + .is-style-mega-menu-item-default .wp-block-outermost-icon-block { + transition: none; + } +} + +/* + * Hover/focus states for .is-style-mega-menu-item-service (styles/blocks/groups/mega-menu-item-service.json), + * matching the Default menu's row-background convention. Same WordPress core limitation as above applies. + */ +.is-style-mega-menu-item-service { + transition: background-color var(--wp--custom--animation--duration--base) + var(--wp--custom--animation--easing--standard); + + &:hover, + &:focus-within { + background-color: var(--wp--custom--color--surface--card-raised); + } +} + +@include motion.reduced-motion { + .is-style-mega-menu-item-service { + transition: none; + } +} + +/* + * Services mega menu panel structural fixes. + */ +.is-style-mega-menu-panel-services { + /* + * "Hug" the panel to its own content instead of stretching to whatever width the Ollie dropdown + * container's ancestor happens to give it. Without this, the panel's background/border render at + * the ancestor's (narrower) width while the flex-wrapped columns inside still need their full + * natural width, so content visibly overflows past the card edge. There's no theme.json dimensions + * property for width/fit-content, so this has to be CSS. + */ + width: fit-content; + max-width: 100vw; + + /* + * core/columns divides its row into equal shares with no per-column minimum, so at narrower + * widths the phase labels (Discover, Create, etc.) run out of room and wrap mid-word. Neither a + * column minimum-width nor a guaranteed-no-wrap label is expressible via theme.json (dimensions + * only supports aspectRatio/minHeight, and typography has no whiteSpace property), so both are + * set here: each phase column gets a floor matching Figma's 120px minimum, wrapping onto a new + * row via flex-wrap once six no longer fit, instead of shrinking below that floor; the label text + * itself is also pinned to one line as a belt-and-suspenders guarantee. + */ + .wp-block-columns { + flex-wrap: wrap; + } + + .wp-block-column { + flex: 1 1 120px; + min-width: 120px; + } +} + +.is-style-mega-menu-panel-services .wp-block-column > .wp-block-group p { + white-space: nowrap; +} + +/* + * Per-phase hover colour for the Services mega menu: the phase-header group (dot + label + arrow) + * and every service row underneath it hover in that same column's phase colour. Each phase always + * occupies the same column position (Discover 1st ... Evolve 6th), so this is targeted structurally + * via :nth-child rather than adding a per-instance custom property to the markup — the same custom + * hover mechanic that broke block validation earlier in this file. var(--wp--custom--color--phase--*) + * already resolves to the "strong" preset in light mode and the plain preset in dark mode, so one + * token covers both the header hover and the "Phase X strong" row hover in a single declaration. + */ +$ls-mega-menu-phases: 1 discover, 2 create, 3 build, 4 launch, 5 grow, 6 evolve; + +@each $pair in $ls-mega-menu-phases { + $index: list.nth($pair, 1); + $phase: list.nth($pair, 2); + + .is-style-mega-menu-panel-services .wp-block-columns > .wp-block-column:nth-child(#{$index}) { + > .wp-block-group:first-child { + border-radius: var(--wp--preset--border-radius--300); + transition: background-color var(--wp--custom--animation--duration--base) + var(--wp--custom--animation--easing--standard); + + &:hover, + &:focus-within { + background-color: color-mix( + in srgb, + var(--wp--custom--color--phase--#{$phase}) 15%, + transparent + ); + } + } + + .is-style-mega-menu-item-service { + &:hover, + &:focus-within { + background-color: color-mix( + in srgb, + var(--wp--custom--color--phase--#{$phase}) 15%, + transparent + ); + } + + &:hover a, + &:focus-within a { + color: var(--wp--custom--color--phase--#{$phase}); + } + } + } +} + +@include motion.reduced-motion { + .is-style-mega-menu-panel-services .wp-block-column > .wp-block-group:first-child { + transition: none; + } +} diff --git a/styles/blocks/buttons/button-cta-gradient.json b/styles/blocks/buttons/button-cta-gradient.json new file mode 100644 index 0000000..901f238 --- /dev/null +++ b/styles/blocks/buttons/button-cta-gradient.json @@ -0,0 +1,35 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.9/theme.json", + "version": 3, + "title": "Button CTA Gradient", + "slug": "button-cta-gradient", + "blockTypes": [ + "core/button" + ], + "description": "Gradient-filled pill CTA button (header \"Start a project\"). The gradient is a literal color.gradient value (theme.json's dedicated gradient property — color.background only accepts solid colours, which is why this previously rendered with no visible fill), fully expressible in JSON — only the hover lift lives in src/scss/animations/_header-motion.scss.", + "styles": { + "border": { + "color": "var:custom|color|border|card", + "radius": "var:preset|border-radius|500", + "style": "solid", + "width": "1px" + }, + "color": { + "gradient": "linear-gradient(135deg, var(--wp--custom--color--phase--create) 0%, var(--wp--custom--color--link--accent) 60%, var(--wp--custom--color--link--accent) 100%)", + "text": "var:custom|color|text|on-dark" + }, + "shadow": "var:preset|shadow|interactive-accent", + "spacing": { + "padding": { + "top": "var:preset|spacing|10", + "right": "var:preset|spacing|20", + "bottom": "var:preset|spacing|10", + "left": "var:preset|spacing|20" + } + }, + "typography": { + "fontWeight": "var:custom|typography|font-weight|extrabold", + "fontSize": "var:preset|font-size|100" + } + } +} diff --git a/styles/blocks/groups/footer-proof-card.json b/styles/blocks/groups/footer-proof-card.json new file mode 100644 index 0000000..09a967b --- /dev/null +++ b/styles/blocks/groups/footer-proof-card.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.9/theme.json", + "version": 3, + "title": "Footer Proof Card", + "slug": "footer-proof-card", + "blockTypes": [ + "core/group" + ], + "description": "Compact glass stat card for the footer's proof points (15+/AA/100%). Structural styling only — the hover background lift is authored in src/scss/animations/_footer-motion.scss (WordPress doesn't generate :hover CSS for arbitrary block style variations).", + "styles": { + "color": { + "background": "var:custom|color|surface|card", + "text": "var:custom|color|text|muted" + }, + "border": { + "color": "var:custom|color|border|card", + "radius": "var:preset|border-radius|300", + "style": "solid", + "width": "1px" + }, + "spacing": { + "blockGap": "var:preset|spacing|5", + "padding": { + "top": "var:preset|spacing|20", + "right": "var:preset|spacing|20", + "bottom": "var:preset|spacing|20", + "left": "var:preset|spacing|20" + } + } + } +} diff --git a/styles/blocks/groups/footer-social-icon.json b/styles/blocks/groups/footer-social-icon.json new file mode 100644 index 0000000..6de641a --- /dev/null +++ b/styles/blocks/groups/footer-social-icon.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.9/theme.json", + "version": 3, + "title": "Footer Social Icon", + "slug": "footer-social-icon", + "blockTypes": [ + "core/group" + ], + "description": "Circular social icon button for the footer. Structural styling only — the hover background lift is authored in src/scss/animations/_footer-motion.scss (WordPress doesn't generate :hover CSS for arbitrary block style variations).", + "styles": { + "color": { + "background": "var:custom|color|surface|card", + "text": "var:custom|color|text|default" + }, + "border": { + "color": "var:custom|color|border|card", + "radius": "var:preset|border-radius|500", + "style": "solid", + "width": "1px" + }, + "dimensions": { + "minHeight": "44px" + }, + "spacing": { + "padding": { + "top": "var:preset|spacing|10", + "right": "var:preset|spacing|10", + "bottom": "var:preset|spacing|10", + "left": "var:preset|spacing|10" + } + } + } +} diff --git a/styles/blocks/groups/header-icon-button.json b/styles/blocks/groups/header-icon-button.json new file mode 100644 index 0000000..8c14623 --- /dev/null +++ b/styles/blocks/groups/header-icon-button.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.9/theme.json", + "version": 3, + "title": "Header Icon Button", + "slug": "header-icon-button", + "blockTypes": [ + "core/group" + ], + "description": "Circular icon button for the header (search, light/dark toggle). Structural styling only — the hover background lift is authored in src/scss/animations/_header-motion.scss (WordPress doesn't generate :hover CSS for arbitrary block style variations).", + "styles": { + "color": { + "background": "color-mix(in srgb, var(--wp--custom--color--surface--highlight) 4%, transparent)", + "text": "var:custom|color|text|default" + }, + "border": { + "color": "var:custom|color|border|card", + "radius": "var:preset|border-radius|500", + "style": "solid", + "width": "1px" + }, + "dimensions": { + "minHeight": "44px" + }, + "spacing": { + "padding": { + "top": "var:preset|spacing|10", + "right": "var:preset|spacing|10", + "bottom": "var:preset|spacing|10", + "left": "var:preset|spacing|10" + } + } + } +} diff --git a/styles/blocks/groups/mega-menu-item-default.json b/styles/blocks/groups/mega-menu-item-default.json new file mode 100644 index 0000000..67badf9 --- /dev/null +++ b/styles/blocks/groups/mega-menu-item-default.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.9/theme.json", + "version": 3, + "title": "Mega Menu Item - Default", + "slug": "mega-menu-item-default", + "blockTypes": [ + "core/group" + ], + "description": "Single style for the whole Default mega-menu row (icon well + title/description + trailing arrow). Only this row reacts to hover/focus: its background highlights and the trailing arrow icon becomes visible. The icon well itself carries no className/registered style of its own, so it has no hover behaviour to trigger.", + "styles": { + "border": { + "radius": "var:preset|border-radius|300" + }, + "spacing": { + "padding": { + "top": "var:preset|spacing|10", + "right": "var:preset|spacing|10", + "bottom": "var:preset|spacing|10", + "left": "var:preset|spacing|10" + } + }, + "blocks": { + "outermost/icon-block": { + "color": { + "text": "transparent" + } + } + } + } +} diff --git a/styles/blocks/groups/mega-menu-item-service.json b/styles/blocks/groups/mega-menu-item-service.json new file mode 100644 index 0000000..e3a273d --- /dev/null +++ b/styles/blocks/groups/mega-menu-item-service.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.9/theme.json", + "version": 3, + "title": "Mega Menu Item - Service", + "slug": "mega-menu-item-service", + "blockTypes": [ + "core/paragraph" + ], + "description": "Menu-item row for the Service mega menu's phase columns. Structural padding/radius live here; the row background-on-hover/focus treatment (matching the Default menu's convention) is authored in src/scss/animations/_menu-motion.scss, since WordPress doesn't generate :hover/:focus CSS for arbitrary block style variations.", + "styles": { + "border": { + "radius": "var:preset|border-radius|300" + }, + "spacing": { + "padding": { + "top": "var:preset|spacing|10", + "right": "var:preset|spacing|10", + "bottom": "var:preset|spacing|10", + "left": "var:preset|spacing|10" + } + } + } +} diff --git a/styles/blocks/paragraphs/footer-nav-link.json b/styles/blocks/paragraphs/footer-nav-link.json new file mode 100644 index 0000000..53cf830 --- /dev/null +++ b/styles/blocks/paragraphs/footer-nav-link.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.9/theme.json", + "version": 3, + "title": "Footer Nav Link", + "slug": "footer-nav-link", + "blockTypes": [ + "core/paragraph" + ], + "description": "Footer nav column link row. Static colour/spacing only — the underline-reveal-on-hover treatment lives in src/scss/animations/_footer-motion.scss, since WordPress doesn't generate :hover CSS for arbitrary block style variations.", + "styles": { + "color": { + "text": "var:custom|color|text|muted" + }, + "spacing": { + "margin": { + "top": "0", + "bottom": "0" + } + }, + "typography": { + "textDecoration": "none" + } + } +} diff --git a/styles/dark.json b/styles/dark.json index d64a5c3..5a1caf5 100644 --- a/styles/dark.json +++ b/styles/dark.json @@ -9,6 +9,7 @@ "default": "var:preset|color|base", "inverse": "var:preset|color|contrast", "muted": "var:preset|color|neutral-400", + "subtle": "var:preset|color|neutral-500", "brand": "var:preset|color|cta-500", "brand-strong": "var:preset|color|cta-200", "on-dark": "var:preset|color|base", @@ -43,6 +44,17 @@ "accent": "var:preset|color|accent-three-500" } }, + "phase": { + "discover": "var:preset|color|phase-one", + "create": "var:preset|color|phase-two", + "build": "var:preset|color|phase-three", + "launch": "var:preset|color|phase-four", + "grow": "var:preset|color|phase-five", + "evolve": "var:preset|color|phase-six" + }, + "status": { + "success": "var:preset|color|success-foreground" + }, "text-shadow": { "contrast": "var:preset|color|base", "base": "var:preset|color|contrast" @@ -100,6 +112,12 @@ }, "card": { "hover": "var(--wp--custom--shadow--elevation--400), 0 28px 56px -28px color-mix(in srgb, var(--wp--custom--color--link--accent) 52%, transparent), 0 14px 30px -18px color-mix(in srgb, var(--wp--custom--color--link--accent) 32%, transparent)" + }, + "popover": { + "menu": "0 32px 80px 0 color-mix(in srgb, var(--wp--custom--color--effect--spotlight--primary) 18%, transparent), var(--wp--custom--shadow--elevation--200)" + }, + "footer": { + "notes": "0 0 0 1px color-mix(in srgb, var(--wp--custom--color--phase--create) 24%, transparent), 0 0 34px 0 color-mix(in srgb, var(--wp--custom--color--phase--create) 18%, transparent)" } } } diff --git a/styles/presets/links.json b/styles/presets/links.json index 1a6e35d..ad09807 100644 --- a/styles/presets/links.json +++ b/styles/presets/links.json @@ -10,6 +10,25 @@ ":hover": { "color": { "text": "var:custom|color|link|accent-hover" + }, + "typography": { + + "textDecoration": "none" + + } + + } + } + }, + "blocks": { + "core/navigation": { + "elements": { + "link": { + ":hover": { + "typography": { + "textDecoration": "none" + } + } } } } diff --git a/styles/presets/shadows.json b/styles/presets/shadows.json index b5bfcde..cabaec7 100644 --- a/styles/presets/shadows.json +++ b/styles/presets/shadows.json @@ -34,6 +34,21 @@ "name": "X-Large", "slug": "600", "shadow": "var(--wp--custom--shadow--elevation--600)" + }, + { + "name": "Popover", + "slug": "popover", + "shadow": "var(--wp--custom--shadow--popover--menu)" + }, + { + "name": "Footer Notes Glow", + "slug": "footer-notes", + "shadow": "var(--wp--custom--shadow--footer--notes)" + }, + { + "name": "Interactive Accent Glow", + "slug": "interactive-accent", + "shadow": "var(--wp--custom--shadow--interactive--accent)" } ] } diff --git a/styles/sections/footer/footer-notes-panel.json b/styles/sections/footer/footer-notes-panel.json new file mode 100644 index 0000000..125a54f --- /dev/null +++ b/styles/sections/footer/footer-notes-panel.json @@ -0,0 +1,32 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.9/theme.json", + "version": 3, + "title": "Footer Notes Panel", + "slug": "footer-notes-panel", + "blockTypes": [ + "core/group" + ], + "description": "Cyan-tinted glass panel for the footer's editorial teaser (badge + heading + paragraph). Static — no hover state, unlike the interactive is-style-glass-card.", + "styles": { + "color": { + "background": "color-mix(in srgb, var(--wp--custom--color--phase--create) 6%, var(--wp--custom--color--surface--card))", + "text": "var:custom|color|text|muted" + }, + "border": { + "color": "color-mix(in srgb, var(--wp--custom--color--phase--create) 24%, transparent)", + "radius": "var:preset|border-radius|400", + "style": "solid", + "width": "1px" + }, + "shadow": "var:preset|shadow|footer-notes", + "spacing": { + "blockGap": "var:preset|spacing|10", + "padding": { + "top": "var:preset|spacing|40", + "right": "var:preset|spacing|30", + "bottom": "var:preset|spacing|40", + "left": "var:preset|spacing|30" + } + } + } +} diff --git a/styles/sections/menu/mega-menu-panel.json b/styles/sections/menu/mega-menu-panel.json new file mode 100644 index 0000000..c64679a --- /dev/null +++ b/styles/sections/menu/mega-menu-panel.json @@ -0,0 +1,32 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.9/theme.json", + "version": 3, + "title": "Mega Menu Panel", + "slug": "mega-menu-panel", + "blockTypes": [ + "core/group" + ], + "description": "Dropdown panel shell for Ollie Menu Designer mega menus. Card surface with a card-family border and popover shadow.", + "styles": { + "color": { + "background": "var:custom|color|surface|card", + "text": "var:custom|color|text|default" + }, + "border": { + "color": "var:custom|color|border|card", + "radius": "var:preset|border-radius|300", + "style": "solid", + "width": "1px" + }, + "shadow": "var:preset|shadow|popover", + "spacing": { + "blockGap": "var:preset|spacing|20", + "padding": { + "top": "var:preset|spacing|30", + "right": "var:preset|spacing|20", + "bottom": "var:preset|spacing|30", + "left": "var:preset|spacing|20" + } + } + } +} diff --git a/theme.json b/theme.json index b82d85f..47b2d30 100644 --- a/theme.json +++ b/theme.json @@ -399,6 +399,66 @@ "name": "Success Foreground", "slug": "success-foreground", "color": "#10B981" + }, + { + "name": "Phase One", + "slug": "phase-one", + "color": "#5DE81C" + }, + { + "name": "Phase One Strong", + "slug": "phase-one-strong", + "color": "#32800D" + }, + { + "name": "Phase Two", + "slug": "phase-two", + "color": "#18CAE9" + }, + { + "name": "Phase Two Strong", + "slug": "phase-two-strong", + "color": "#0E7B8E" + }, + { + "name": "Phase Three", + "slug": "phase-three", + "color": "#FE5EAD" + }, + { + "name": "Phase Three Strong", + "slug": "phase-three-strong", + "color": "#DB016D" + }, + { + "name": "Phase Four", + "slug": "phase-four", + "color": "#FADC2F" + }, + { + "name": "Phase Four Strong", + "slug": "phase-four-strong", + "color": "#826F03" + }, + { + "name": "Phase Five", + "slug": "phase-five", + "color": "#22CD94" + }, + { + "name": "Phase Five Strong", + "slug": "phase-five-strong", + "color": "#157F5C" + }, + { + "name": "Phase Six", + "slug": "phase-six", + "color": "#7A7CF9" + }, + { + "name": "Phase Six Strong", + "slug": "phase-six-strong", + "color": "#585AF7" } ] }, @@ -419,6 +479,7 @@ "default": "var:preset|color|contrast", "inverse": "var:preset|color|base", "muted": "var:preset|color|neutral-700", + "subtle": "var:preset|color|neutral-600", "brand": "var:preset|color|brand-500", "brand-strong": "var:preset|color|brand-800", "on-dark": "var:preset|color|base", @@ -453,6 +514,17 @@ "accent": "var:preset|color|accent-500" } }, + "phase": { + "discover": "var:preset|color|phase-one-strong", + "create": "var:preset|color|phase-two-strong", + "build": "var:preset|color|phase-three-strong", + "launch": "var:preset|color|phase-four-strong", + "grow": "var:preset|color|phase-five-strong", + "evolve": "var:preset|color|phase-six-strong" + }, + "status": { + "success": "var:preset|color|success-foreground" + }, "text-shadow": { "contrast": "var:preset|color|contrast", "base": "var:preset|color|base" @@ -543,6 +615,12 @@ }, "card": { "hover": "0 9px 28px -16px color-mix(in srgb, var(--wp--custom--color--text--brand) 80%, transparent), 0 8px 18px -14px color-mix(in srgb, var(--wp--custom--color--text--brand-strong) 24%, transparent)" + }, + "popover": { + "menu": "0 32px 80px 0 color-mix(in srgb, var(--wp--custom--color--effect--spotlight--primary) 18%, transparent), var(--wp--custom--shadow--elevation--200)" + }, + "footer": { + "notes": "0 0 0 1px color-mix(in srgb, var(--wp--custom--color--phase--create) 14%, transparent), 0 0 24px 0 color-mix(in srgb, var(--wp--custom--color--phase--create) 10%, transparent)" } }, "animation": { @@ -602,6 +680,36 @@ "name": "footer", "title": "Footer", "area": "footer" + }, + { + "name": "work-mega-menu", + "title": "Work Mega Menu", + "area": "uncategorized" + }, + { + "name": "solutions-mega-menu", + "title": "Solutions Mega Menu", + "area": "uncategorized" + }, + { + "name": "pricing-mega-menu", + "title": "Pricing Mega Menu", + "area": "uncategorized" + }, + { + "name": "insights-mega-menu", + "title": "Insights Mega Menu", + "area": "uncategorized" + }, + { + "name": "about-mega-menu", + "title": "About Mega Menu", + "area": "uncategorized" + }, + { + "name": "services-mega-menu", + "title": "Services Mega Menu", + "area": "uncategorized" } ], "customTemplates": [