diff --git a/CHANGELOG.md b/CHANGELOG.md index a76c194..a0281a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --- +## [Unreleased] — Build Services page: closing CTA section (LS-1598) + +### Added + +- Added `patterns/sections/services-cta.php` (renamed from the empty, unused `patterns/section-cta.php` stub): "Let's scope it properly" — eyebrow, heading, description, and a single button reusing the exact button already established in `services-hero.php`. +- Added `src/scss/structural/corner-glow.scss`: a shared, multi-consumer two-corner radial-gradient glow background, with its colours as CSS custom properties so future consumers can override them per instance instead of duplicating the file. + +### Fixed + +- Corrected a Figma SVG gradient matrix decode error that made the corner-glow's blobs roughly 10x too small (a missing `r="10"` base-circle multiplier), and set the CTA panel to a real 800px max width. + +[PR #56](https://github.com/lightspeedwp/ls-theme/pull/56) + +--- + ## [Unreleased] — Build Services page: service tiles section (LS-1598) ### Added diff --git a/assets/css/corner-glow.css b/assets/css/corner-glow.css new file mode 100644 index 0000000..eaad3e8 --- /dev/null +++ b/assets/css/corner-glow.css @@ -0,0 +1 @@ +.ls-corner-glow{background-image:radial-gradient(87.5% 172.4% at 20% 30%, color-mix(in srgb, var(--ls-corner-glow-color-1, var(--wp--custom--color--effect--hero--brand)) var(--ls-corner-glow-opacity-1, 14%), transparent) 0%, transparent 60%),radial-gradient(87.5% 172.4% at 80% 70%, color-mix(in srgb, var(--ls-corner-glow-color-2, var(--wp--custom--color--effect--hero--cyan)) var(--ls-corner-glow-opacity-2, 14%), transparent) 0%, transparent 60%);background-position:0 0;background-repeat:no-repeat}.ls-corner-glow .wp-block-buttons{min-inline-size:0}.ls-corner-glow .wp-block-buttons .wp-block-button{min-inline-size:0}.ls-corner-glow .wp-block-buttons .wp-block-button__link{min-inline-size:0;white-space:normal;text-align:center} diff --git a/functions.php b/functions.php index c178c8a..15ba902 100644 --- a/functions.php +++ b/functions.php @@ -75,6 +75,7 @@ function ls_theme_setup() { add_editor_style( 'assets/css/services-service-clusters.css' ); add_editor_style( 'assets/css/services-service-tiles.css' ); add_editor_style( 'assets/css/services-delivery-numbers.css' ); + add_editor_style( 'assets/css/corner-glow.css' ); add_editor_style( 'assets/css/work-hero.css' ); add_editor_style( 'assets/css/work-single-hero.css' ); add_editor_style( 'assets/css/blog-hero.css' ); diff --git a/inc/animations.php b/inc/animations.php index 045312b..dda1bab 100644 --- a/inc/animations.php +++ b/inc/animations.php @@ -76,6 +76,7 @@ function ls_theme_get_bundle_render_markers() { 'services-service-clusters' => array( 'classes' => array( 'ls-cluster-tag' ) ), 'services-service-tiles' => array( 'classes' => array( 'is-style-card-service-tile' ) ), 'services-delivery-numbers' => array( 'classes' => array( 'ls-delivery-stats-row' ) ), + 'corner-glow' => array( 'classes' => array( 'ls-corner-glow' ) ), 'work-hero' => array( 'classes' => array( 'ls-work-hero' ) ), 'work-single-hero' => array( 'classes' => array( 'ls-work-single-meta' ) ), 'blog-hero' => array( 'classes' => array( 'ls-blog-hero' ) ), @@ -315,6 +316,17 @@ function ls_theme_get_effect_styles( $context = 'front' ) { return is_page( 'services' ); }, ), + 'corner-glow' => array( + 'handle' => 'ls-theme-corner-glow', + 'path' => 'assets/css/corner-glow.css', + 'contexts' => array( 'front', 'editor' ), + // Same reasoning as card-shells/cta-buttons above: services-cta.php declares + // Inserter: true, so an editor can place this pattern (and this shared class) on + // any page, not just Services — a page-specific condition would leave it caught + // only by the render_block/footer fallback there, a guaranteed flash of unstyled + // content rather than a rare edge case. At ~400 bytes compressed, cheaper to load + // unconditionally. + ), 'work-hero' => array( 'handle' => 'ls-theme-work-hero', 'path' => 'assets/css/work-hero.css', diff --git a/package.json b/package.json index 2ea322a..352c090 100644 --- a/package.json +++ b/package.json @@ -4,15 +4,15 @@ "description": "LightSpeed Theme is a custom WordPress block theme built by LightSpeed for fast, accessible, maintainable websites using the WordPress Site Editor and block editor.", "type": "module", "scripts": { - "build:css": "sass --no-source-map --no-charset --style=compressed src/scss/animations.scss:assets/css/animations.css src/scss/gsap-animations.scss:assets/css/gsap-animations.css src/scss/structural/taxonomy-filter.scss:assets/css/taxonomy-filter.css src/scss/structural/work-project-card.scss:assets/css/work-project-card.css src/scss/structural/work-archive-sections.scss:assets/css/work-archive-sections.css src/scss/structural/card-shells.scss:assets/css/card-shells.css src/scss/structural/cta-buttons.scss:assets/css/cta-buttons.css src/scss/structural/home-hero.scss:assets/css/home-hero.css src/scss/structural/work-hero.scss:assets/css/work-hero.css src/scss/structural/work-single-hero.scss:assets/css/work-single-hero.css src/scss/structural/blog-hero.scss:assets/css/blog-hero.css src/scss/structural/blog-all-articles.scss:assets/css/blog-all-articles.css src/scss/structural/blog-writing-cta.scss:assets/css/blog-writing-cta.css src/scss/structural/faq.scss:assets/css/faq.css src/scss/structural/links.scss:assets/css/links.css src/scss/structural/button-secondary.scss:assets/css/button-secondary.css src/scss/structural/featured-work.scss:assets/css/featured-work.css src/scss/structural/where-to-fit.scss:assets/css/where-to-fit.css src/scss/structural/homepage-cta.scss:assets/css/homepage-cta.css src/scss/structural/stats-bar.scss:assets/css/stats-bar.css src/scss/structural/homepage-card-rows.scss:assets/css/homepage-card-rows.css src/scss/structural/homepage-why-lightspeed.scss:assets/css/homepage-why-lightspeed.css src/scss/structural/search-results.scss:assets/css/search-results.css src/scss/structural/search-hero.scss:assets/css/search-hero.css src/scss/structural/services-hero.scss:assets/css/services-hero.css src/scss/structural/services-linked-decisions.scss:assets/css/services-linked-decisions.css src/scss/structural/services-service-clusters.scss:assets/css/services-service-clusters.css src/scss/structural/services-service-tiles.scss:assets/css/services-service-tiles.css src/scss/structural/services-delivery-numbers.scss:assets/css/services-delivery-numbers.css", - "build:css:dev": "sass --no-source-map --no-charset --style=expanded src/scss/animations.scss:assets/css/animations.css src/scss/gsap-animations.scss:assets/css/gsap-animations.css src/scss/structural/taxonomy-filter.scss:assets/css/taxonomy-filter.css src/scss/structural/work-project-card.scss:assets/css/work-project-card.css src/scss/structural/work-archive-sections.scss:assets/css/work-archive-sections.css src/scss/structural/card-shells.scss:assets/css/card-shells.css src/scss/structural/cta-buttons.scss:assets/css/cta-buttons.css src/scss/structural/home-hero.scss:assets/css/home-hero.css src/scss/structural/work-hero.scss:assets/css/work-hero.css src/scss/structural/work-single-hero.scss:assets/css/work-single-hero.css src/scss/structural/blog-hero.scss:assets/css/blog-hero.css src/scss/structural/blog-all-articles.scss:assets/css/blog-all-articles.css src/scss/structural/blog-writing-cta.scss:assets/css/blog-writing-cta.css src/scss/structural/faq.scss:assets/css/faq.css src/scss/structural/links.scss:assets/css/links.css src/scss/structural/button-secondary.scss:assets/css/button-secondary.css src/scss/structural/featured-work.scss:assets/css/featured-work.css src/scss/structural/where-to-fit.scss:assets/css/where-to-fit.css src/scss/structural/homepage-cta.scss:assets/css/homepage-cta.css src/scss/structural/stats-bar.scss:assets/css/stats-bar.css src/scss/structural/homepage-card-rows.scss:assets/css/homepage-card-rows.css src/scss/structural/homepage-why-lightspeed.scss:assets/css/homepage-why-lightspeed.css src/scss/structural/search-results.scss:assets/css/search-results.css src/scss/structural/search-hero.scss:assets/css/search-hero.css src/scss/structural/services-hero.scss:assets/css/services-hero.css src/scss/structural/services-linked-decisions.scss:assets/css/services-linked-decisions.css src/scss/structural/services-service-clusters.scss:assets/css/services-service-clusters.css src/scss/structural/services-service-tiles.scss:assets/css/services-service-tiles.css src/scss/structural/services-delivery-numbers.scss:assets/css/services-delivery-numbers.css", + "build:css": "sass --no-source-map --no-charset --style=compressed src/scss/animations.scss:assets/css/animations.css src/scss/gsap-animations.scss:assets/css/gsap-animations.css src/scss/structural/taxonomy-filter.scss:assets/css/taxonomy-filter.css src/scss/structural/work-project-card.scss:assets/css/work-project-card.css src/scss/structural/work-archive-sections.scss:assets/css/work-archive-sections.css src/scss/structural/card-shells.scss:assets/css/card-shells.css src/scss/structural/cta-buttons.scss:assets/css/cta-buttons.css src/scss/structural/home-hero.scss:assets/css/home-hero.css src/scss/structural/work-hero.scss:assets/css/work-hero.css src/scss/structural/work-single-hero.scss:assets/css/work-single-hero.css src/scss/structural/blog-hero.scss:assets/css/blog-hero.css src/scss/structural/blog-all-articles.scss:assets/css/blog-all-articles.css src/scss/structural/blog-writing-cta.scss:assets/css/blog-writing-cta.css src/scss/structural/faq.scss:assets/css/faq.css src/scss/structural/links.scss:assets/css/links.css src/scss/structural/button-secondary.scss:assets/css/button-secondary.css src/scss/structural/featured-work.scss:assets/css/featured-work.css src/scss/structural/where-to-fit.scss:assets/css/where-to-fit.css src/scss/structural/homepage-cta.scss:assets/css/homepage-cta.css src/scss/structural/stats-bar.scss:assets/css/stats-bar.css src/scss/structural/homepage-card-rows.scss:assets/css/homepage-card-rows.css src/scss/structural/homepage-why-lightspeed.scss:assets/css/homepage-why-lightspeed.css src/scss/structural/search-results.scss:assets/css/search-results.css src/scss/structural/search-hero.scss:assets/css/search-hero.css src/scss/structural/services-hero.scss:assets/css/services-hero.css src/scss/structural/services-linked-decisions.scss:assets/css/services-linked-decisions.css src/scss/structural/services-service-clusters.scss:assets/css/services-service-clusters.css src/scss/structural/services-service-tiles.scss:assets/css/services-service-tiles.css src/scss/structural/services-delivery-numbers.scss:assets/css/services-delivery-numbers.css src/scss/structural/corner-glow.scss:assets/css/corner-glow.css", + "build:css:dev": "sass --no-source-map --no-charset --style=expanded src/scss/animations.scss:assets/css/animations.css src/scss/gsap-animations.scss:assets/css/gsap-animations.css src/scss/structural/taxonomy-filter.scss:assets/css/taxonomy-filter.css src/scss/structural/work-project-card.scss:assets/css/work-project-card.css src/scss/structural/work-archive-sections.scss:assets/css/work-archive-sections.css src/scss/structural/card-shells.scss:assets/css/card-shells.css src/scss/structural/cta-buttons.scss:assets/css/cta-buttons.css src/scss/structural/home-hero.scss:assets/css/home-hero.css src/scss/structural/work-hero.scss:assets/css/work-hero.css src/scss/structural/work-single-hero.scss:assets/css/work-single-hero.css src/scss/structural/blog-hero.scss:assets/css/blog-hero.css src/scss/structural/blog-all-articles.scss:assets/css/blog-all-articles.css src/scss/structural/blog-writing-cta.scss:assets/css/blog-writing-cta.css src/scss/structural/faq.scss:assets/css/faq.css src/scss/structural/links.scss:assets/css/links.css src/scss/structural/button-secondary.scss:assets/css/button-secondary.css src/scss/structural/featured-work.scss:assets/css/featured-work.css src/scss/structural/where-to-fit.scss:assets/css/where-to-fit.css src/scss/structural/homepage-cta.scss:assets/css/homepage-cta.css src/scss/structural/stats-bar.scss:assets/css/stats-bar.css src/scss/structural/homepage-card-rows.scss:assets/css/homepage-card-rows.css src/scss/structural/homepage-why-lightspeed.scss:assets/css/homepage-why-lightspeed.css src/scss/structural/search-results.scss:assets/css/search-results.css src/scss/structural/search-hero.scss:assets/css/search-hero.css src/scss/structural/services-hero.scss:assets/css/services-hero.css src/scss/structural/services-linked-decisions.scss:assets/css/services-linked-decisions.css src/scss/structural/services-service-clusters.scss:assets/css/services-service-clusters.css src/scss/structural/services-service-tiles.scss:assets/css/services-service-tiles.css src/scss/structural/services-delivery-numbers.scss:assets/css/services-delivery-numbers.css src/scss/structural/corner-glow.scss:assets/css/corner-glow.css", "schema:validate": "node theme-utils.mjs validate-schema", "theme:validate": "node theme-utils.mjs validate-theme", "patterns:escape": "node theme-utils.mjs escape-patterns", "security:scan": "node theme-utils.mjs security-scan", "lint": "npm run lint:json", "lint:json": "node --input-type=module --eval \"import { readFileSync } from 'fs'; import { glob } from 'glob'; const files = await glob(['theme.json', 'styles/**/*.json']); let ok = true; for (const f of files) { try { JSON.parse(readFileSync(f, 'utf8')); } catch (e) { console.error('Invalid JSON:', f, e.message); ok = false; } } if (ok) console.log('All JSON files are valid.'); else process.exit(1);\"", - "watch:css": "sass --watch --no-source-map --no-charset --style=expanded src/scss/animations.scss:assets/css/animations.css src/scss/gsap-animations.scss:assets/css/gsap-animations.css src/scss/structural/taxonomy-filter.scss:assets/css/taxonomy-filter.css src/scss/structural/work-project-card.scss:assets/css/work-project-card.css src/scss/structural/work-archive-sections.scss:assets/css/work-archive-sections.css src/scss/structural/card-shells.scss:assets/css/card-shells.css src/scss/structural/cta-buttons.scss:assets/css/cta-buttons.css src/scss/structural/home-hero.scss:assets/css/home-hero.css src/scss/structural/work-hero.scss:assets/css/work-hero.css src/scss/structural/work-single-hero.scss:assets/css/work-single-hero.css src/scss/structural/blog-hero.scss:assets/css/blog-hero.css src/scss/structural/blog-all-articles.scss:assets/css/blog-all-articles.css src/scss/structural/blog-writing-cta.scss:assets/css/blog-writing-cta.css src/scss/structural/faq.scss:assets/css/faq.css src/scss/structural/links.scss:assets/css/links.css src/scss/structural/button-secondary.scss:assets/css/button-secondary.css src/scss/structural/featured-work.scss:assets/css/featured-work.css src/scss/structural/where-to-fit.scss:assets/css/where-to-fit.css src/scss/structural/homepage-cta.scss:assets/css/homepage-cta.css src/scss/structural/stats-bar.scss:assets/css/stats-bar.css src/scss/structural/homepage-card-rows.scss:assets/css/homepage-card-rows.css src/scss/structural/homepage-why-lightspeed.scss:assets/css/homepage-why-lightspeed.css src/scss/structural/search-results.scss:assets/css/search-results.css src/scss/structural/search-hero.scss:assets/css/search-hero.css src/scss/structural/services-hero.scss:assets/css/services-hero.css src/scss/structural/services-linked-decisions.scss:assets/css/services-linked-decisions.css src/scss/structural/services-service-clusters.scss:assets/css/services-service-clusters.css src/scss/structural/services-service-tiles.scss:assets/css/services-service-tiles.css src/scss/structural/services-delivery-numbers.scss:assets/css/services-delivery-numbers.css" + "watch:css": "sass --watch --no-source-map --no-charset --style=expanded src/scss/animations.scss:assets/css/animations.css src/scss/gsap-animations.scss:assets/css/gsap-animations.css src/scss/structural/taxonomy-filter.scss:assets/css/taxonomy-filter.css src/scss/structural/work-project-card.scss:assets/css/work-project-card.css src/scss/structural/work-archive-sections.scss:assets/css/work-archive-sections.css src/scss/structural/card-shells.scss:assets/css/card-shells.css src/scss/structural/cta-buttons.scss:assets/css/cta-buttons.css src/scss/structural/home-hero.scss:assets/css/home-hero.css src/scss/structural/work-hero.scss:assets/css/work-hero.css src/scss/structural/work-single-hero.scss:assets/css/work-single-hero.css src/scss/structural/blog-hero.scss:assets/css/blog-hero.css src/scss/structural/blog-all-articles.scss:assets/css/blog-all-articles.css src/scss/structural/blog-writing-cta.scss:assets/css/blog-writing-cta.css src/scss/structural/faq.scss:assets/css/faq.css src/scss/structural/links.scss:assets/css/links.css src/scss/structural/button-secondary.scss:assets/css/button-secondary.css src/scss/structural/featured-work.scss:assets/css/featured-work.css src/scss/structural/where-to-fit.scss:assets/css/where-to-fit.css src/scss/structural/homepage-cta.scss:assets/css/homepage-cta.css src/scss/structural/stats-bar.scss:assets/css/stats-bar.css src/scss/structural/homepage-card-rows.scss:assets/css/homepage-card-rows.css src/scss/structural/homepage-why-lightspeed.scss:assets/css/homepage-why-lightspeed.css src/scss/structural/search-results.scss:assets/css/search-results.css src/scss/structural/search-hero.scss:assets/css/search-hero.css src/scss/structural/services-hero.scss:assets/css/services-hero.css src/scss/structural/services-linked-decisions.scss:assets/css/services-linked-decisions.css src/scss/structural/services-service-clusters.scss:assets/css/services-service-clusters.css src/scss/structural/services-service-tiles.scss:assets/css/services-service-tiles.css src/scss/structural/services-delivery-numbers.scss:assets/css/services-delivery-numbers.css src/scss/structural/corner-glow.scss:assets/css/corner-glow.css" }, "devDependencies": { "@axe-core/playwright": "^4.13.0", diff --git a/patterns/section-cta.php b/patterns/section-cta.php deleted file mode 100644 index 6ceaaa1..0000000 --- a/patterns/section-cta.php +++ /dev/null @@ -1,10 +0,0 @@ - \ No newline at end of file diff --git a/patterns/sections/services-cta.php b/patterns/sections/services-cta.php new file mode 100644 index 0000000..832f8d5 --- /dev/null +++ b/patterns/sections/services-cta.php @@ -0,0 +1,55 @@ + + +
+ + +
+ + +
+ + + +

+ +
+ + + +

+ + + +

+ + + +
+ +
+ +
+ +
+ +
+ diff --git a/patterns/sections/services-service-tiles.php b/patterns/sections/services-service-tiles.php index 37a1ed5..5b54b2f 100644 --- a/patterns/sections/services-service-tiles.php +++ b/patterns/sections/services-service-tiles.php @@ -182,9 +182,7 @@
- -
- +

diff --git a/src/scss/structural/corner-glow.scss b/src/scss/structural/corner-glow.scss new file mode 100644 index 0000000..d7018fe --- /dev/null +++ b/src/scss/structural/corner-glow.scss @@ -0,0 +1,77 @@ +/********** Corner Glow (shared decorative background, multi-consumer) **********/ + +/* + * A soft two-corner radial glow, decoded from Figma's SVG gradientTransform matrices the same + * way as src/scss/structural/search-hero.scss (its own comment documents the exact conversion + * method) — with one correction this file's first version missed: the gradient's base circle + * has r="10" (user-space units) and the transform matrix scales it by 76.861, so the actual + * radius is 10 × 76.861 = 768.61, not 76.861 alone. Using the matrix value by itself produced + * blobs roughly 10x too small (reading as small hard circles instead of a soft, wide wash). + * Positioned as a diagonal pair — one glow near the top-left corner, one near the bottom-right — + * sized 87.5%/172.4% (x/y radius as a fraction of the ~878x446, ~2:1 source frame) centered at + * 20%/30% and 80%/70%. + * + * JSON limitation: color.gradient block support only accepts a single gradient value, not + * layered gradients of any kind — see AGENTS.md Theme-First Approach and the same reasoning + * already documented in search-hero.scss/work-hero.scss/blog-hero.scss. + * + * Reusable across multiple CTAs/sections with different colours: the two glow colours and + * opacities are CSS custom properties, not hardcoded, so each consumer can override them inline + * per instance (e.g. style="--ls-corner-glow-color-1:...;"). Default fallbacks are + * effect.hero.brand / effect.hero.cyan, since every current consumer happens to use that exact + * pair — but a future consumer needing different colours doesn't need a second copy of this + * file, just its own inline override. + */ +.ls-corner-glow { + background-image: + radial-gradient( + 87.5% 172.4% at 20% 30%, + color-mix( + in srgb, + var(--ls-corner-glow-color-1, var(--wp--custom--color--effect--hero--brand)) var(--ls-corner-glow-opacity-1, 14%), + transparent + ) 0%, + transparent 60% + ), + radial-gradient( + 87.5% 172.4% at 80% 70%, + color-mix( + in srgb, + var(--ls-corner-glow-color-2, var(--wp--custom--color--effect--hero--cyan)) var(--ls-corner-glow-opacity-2, 14%), + transparent + ) 0%, + transparent 60% + ); + background-position: 0 0; + background-repeat: no-repeat; +} + +/* + * Button overflow fix (narrow viewports, confirmed live at 320px). core/button's shared styles + * (styles/presets/blocks/core-button.json) set white-space:nowrap on the button link and + * max-inline-size:100% on the wrapping .wp-block-button div — but that div is a flex item of + * .wp-block-buttons, and flex items default to min-width:auto (their content's intrinsic size), + * which overrides max-inline-size and lets a nowrap button refuse to shrink below its text width. + * Inside this card's narrower content column (~170px available at 320px viewport, after the + * section padding + the card's own padding), "Request a systems review" plus its arrow can't + * fit on one line, so the button spills out past the card's rounded border unclipped instead of + * shrinking or wrapping. + * + * Fixed by letting the flex item actually shrink (min-inline-size: 0, overriding the auto + * default) and letting its text wrap onto a second line instead of forcing nowrap. Scoped to + * buttons inside this card only — not a sitewide core/button change, since every other button + * context on the site has enough room and this isn't a general nowrap bug. + */ +.ls-corner-glow .wp-block-buttons { + min-inline-size: 0; +} + +.ls-corner-glow .wp-block-buttons .wp-block-button { + min-inline-size: 0; +} + +.ls-corner-glow .wp-block-buttons .wp-block-button__link { + min-inline-size: 0; + white-space: normal; + text-align: center; +}