🐞 fix: Update styles for proper background
Sync TODOs with Issues / sync_todos (push) Successful in 6s

This commit is contained in:
Keith Solomon
2026-08-18 16:37:55 -05:00
parent 81547254fc
commit d4df6d8678
12 changed files with 401 additions and 456 deletions
+26 -64
View File
@@ -57,27 +57,6 @@
"append": "", "append": "",
"maxlength": "" "maxlength": ""
}, },
{
"key": "field_684ad36ebaf40",
"label": "Fax",
"name": "fax",
"aria-label": "",
"type": "text",
"instructions": "",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"default_value": "",
"maxlength": "",
"allow_in_bindings": 1,
"placeholder": "",
"prepend": "",
"append": ""
},
{ {
"key": "field_5fd3e0437bff0", "key": "field_5fd3e0437bff0",
"label": "Address", "label": "Address",
@@ -97,26 +76,6 @@
"maxlength": "", "maxlength": "",
"rows": 3, "rows": 3,
"new_lines": "br" "new_lines": "br"
},
{
"key": "field_60381dcb082b5",
"label": "Hours",
"name": "hours",
"aria-label": "",
"type": "textarea",
"instructions": "",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"default_value": "",
"placeholder": "",
"maxlength": "",
"rows": 3,
"new_lines": "br"
} }
] ]
}, },
@@ -209,9 +168,9 @@
"placeholder": "" "placeholder": ""
}, },
{ {
"key": "field_677bf0e692d40", "key": "field_6a82713dd82d4",
"label": "Youtube", "label": "Github",
"name": "youtube", "name": "github",
"aria-label": "", "aria-label": "",
"type": "url", "type": "url",
"instructions": "", "instructions": "",
@@ -223,25 +182,7 @@
"id": "" "id": ""
}, },
"default_value": "", "default_value": "",
"allow_in_bindings": 1, "allow_in_bindings": 0,
"placeholder": ""
},
{
"key": "field_677bf0e692d3f",
"label": "Pinterest",
"name": "pinterest",
"aria-label": "",
"type": "url",
"instructions": "",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"default_value": "",
"allow_in_bindings": 1,
"placeholder": "" "placeholder": ""
} }
] ]
@@ -286,6 +227,24 @@
"max_height": "", "max_height": "",
"max_size": "", "max_size": "",
"mime_types": "" "mime_types": ""
},
{
"key": "field_6a846bd4360da",
"label": "Resume Link",
"name": "resume_link",
"aria-label": "",
"type": "url",
"instructions": "",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"default_value": "",
"allow_in_bindings": 0,
"placeholder": ""
} }
] ]
}, },
@@ -455,5 +414,8 @@
"active": true, "active": true,
"description": "", "description": "",
"show_in_rest": 0, "show_in_rest": 0,
"modified": 1749744328 "display_title": "",
"allow_ai_access": false,
"ai_description": "",
"modified": 1787063276
} }
+1 -4
View File
@@ -14,9 +14,7 @@ if ( ! $hero_intro ) {
$hero_intro = __( 'A comprehensive catalog of WordPress plugins, custom themes, and open-source contributions developed for scalable enterprise environments. Focused on modern development practices, performant architectures, and secure integrations.', 'ks-portfolio' ); $hero_intro = __( 'A comprehensive catalog of WordPress plugins, custom themes, and open-source contributions developed for scalable enterprise environments. Focused on modern development practices, performant architectures, and secure integrations.', 'ks-portfolio' );
} }
?> ?>
<section class="archive-projects aura-bg"> <section class="archive-projects">
<?php get_template_part( 'views/partials/aura-bg' ); ?>
<div class="aura-bg__content">
<div class="container mx-auto my-section"> <div class="container mx-auto my-section">
<header class="archive-projects__head"> <header class="archive-projects__head">
<h1 class="archive-projects__title"><?php echo esc_html__( 'Project Archive', 'ks-portfolio' ); ?></h1> <h1 class="archive-projects__title"><?php echo esc_html__( 'Project Archive', 'ks-portfolio' ); ?></h1>
@@ -51,7 +49,6 @@ if ( ! $hero_intro ) {
</div> </div>
<?php endif; ?> <?php endif; ?>
</div> </div>
</div>
</section> </section>
<?php <?php
+12 -69
View File
@@ -1,6 +1,6 @@
<?php <?php
/** /**
* Front Page Template — Portfolio 2026 home * Front Page Template
* *
* @package KsPortfolio * @package KsPortfolio
*/ */
@@ -8,77 +8,20 @@
namespace KsPortfolio; namespace KsPortfolio;
get_header(); get_header();
$hero_heading = get_field( 'homepage_hero_heading' );
$hero_intro = get_field( 'homepage_hero_intro' );
$hero_cta_1 = get_field( 'homepage_hero_cta_1' ); // ACF link fields return shape: URL, title, target.
$hero_cta_2 = get_field( 'homepage_hero_cta_2' );
?> ?>
<section class="home-hero aura-bg">
<?php get_template_part( 'views/partials/aura-bg' ); ?>
<div class="aura-bg__content">
<div class="container mx-auto my-section">
<div class="home-hero__inner">
<?php if ( $hero_heading ) : ?>
<h1 class="home-hero__heading"><?php echo esc_html( $hero_heading ); ?></h1>
<?php endif; ?>
<?php if ( $hero_intro ) : ?>
<p class="home-hero__intro"><?php echo esc_html( $hero_intro ); ?></p>
<?php endif; ?>
<div class="home-hero__actions">
<?php if ( ! empty( $hero_cta_1['url'] ) && ! empty( $hero_cta_1['title'] ) ) : ?>
<a class="button button--primary" href="<?php echo esc_url( $hero_cta_1['url'] ); ?>"<?php echo ! empty( $hero_cta_1['target'] ) ? ' target="_blank" rel="noopener noreferrer"' : ''; ?>>
<?php echo esc_html( $hero_cta_1['title'] ); ?>
</a>
<?php endif; ?>
<?php if ( ! empty( $hero_cta_2['url'] ) && ! empty( $hero_cta_2['title'] ) ) : ?>
<a class="button button--outline" href="<?php echo esc_url( $hero_cta_2['url'] ); ?>"<?php echo ! empty( $hero_cta_2['target'] ) ? ' target="_blank" rel="noopener noreferrer"' : ''; ?>>
<?php echo esc_html( $hero_cta_2['title'] ); ?>
</a>
<?php endif; ?>
</div>
</div>
</div>
</div>
</section>
<section class="home-recent container mx-auto my-section">
<header class="home-recent__head">
<h2 class="home-recent__title"><?php echo esc_html__( 'Recent Projects', 'ks-portfolio' ); ?></h2>
<a class="home-recent__view-all" href="<?php echo esc_url( get_post_type_archive_link( 'projects' ) ); ?>">
<?php echo esc_html__( 'View All', 'ks-portfolio' ); ?> &rarr;
</a>
</header>
<hr class="home-recent__divider" />
<div class="container my-section lg:my-0 mx-auto">
<div>
<?php <?php
$recent = new \WP_Query( // Content block
array( if ( have_posts() ) {
'post_type' => 'projects', while ( have_posts() ) {
'posts_per_page' => 3, the_post();
'no_found_rows' => true, the_content();
) }
); }
if ( $recent->have_posts() ) :
?>
<div class="home-recent__grid grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<?php
while ( $recent->have_posts() ) :
$recent->the_post();
get_template_part( 'views/components/project-card' );
endwhile;
wp_reset_postdata();
?> ?>
</div> </div>
<?php else : ?> </div>
<div class="home-recent__empty">
<h3><?php echo esc_html__( 'Nothing here yet&hellip;', 'ks-portfolio' ); ?></h3>
<p><?php echo esc_html__( 'No published projects found.', 'ks-portfolio' ); ?></p>
</div>
<?php endif; ?>
</section>
<?php <?php get_footer(); ?>
get_footer();
+7 -23
View File
@@ -11,6 +11,7 @@ namespace KsPortfolio;
global $views; global $views;
$headerLogo = getFieldValue( 'header.header_logo.url' ) ? getFieldValue( 'header.header_logo.url' ) : get_theme_file_uri( '/static/img/logo.svg' ); $headerLogo = getFieldValue( 'header.header_logo.url' ) ? getFieldValue( 'header.header_logo.url' ) : get_theme_file_uri( '/static/img/logo.svg' );
$linkResume = getFieldValue( 'header.resume_link' ) ? getFieldValue( 'header.resume_link' ) : '';
// Check conditions for displaying the hero section // Check conditions for displaying the hero section
$showHero = in_array( $showHero = in_array(
@@ -25,23 +26,6 @@ $showHero = in_array(
), ),
true true
); );
// Carbon Blue project templates render their own <h1> inside the .aura-bg
// hero, so suppress the page-hero partial on those templates to avoid
// duplicate <h1> elements on the page.
$projectTemplates = array( 'front-page', 'archive-projects', 'single-projects' );
$isProjectTemplate = in_array( get_page_template_slug( get_the_ID() ), $projectTemplates, true );
if ( ! $isProjectTemplate ) {
$isProjectTemplate = in_array( get_post_type(), array( 'projects' ), true ) && (
is_front_page()
|| is_archive( 'projects' )
|| is_singular( 'projects' )
);
}
if ( $isProjectTemplate ) {
$showHero = false;
}
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
@@ -60,19 +44,19 @@ if ( $isProjectTemplate ) {
<?php echo esc_html__( 'Skip to main content' ); ?> <?php echo esc_html__( 'Skip to main content' ); ?>
</a> </a>
<header role="banner" class="site-header bg-secondary flex flex-col items-center justify-start"> <?php get_template_part( 'views/partials/aura-bg' ); ?>
<?php get_template_part( 'views/components/nav-aux' ); ?>
<header role="banner" class="site-header bg-secondary flex flex-col items-center justify-start">
<div class="header__nav-main container py-4 items-center grid gap-x-8 gap-y-0 grid-cols-[auto_1fr_auto] grid-rows-[1fr] justify-between"> <div class="header__nav-main container py-4 items-center grid gap-x-8 gap-y-0 grid-cols-[auto_1fr_auto] grid-rows-[1fr] justify-between">
<a href="<?php echo esc_url( home_url( '/' ) ); ?>" class="site-header__logo block"> <a href="<?php echo esc_url( home_url( '/' ) ); ?>" class="site-header__logo m-0 p-0 flex gap-x-4 items-center justify-start text-white! text-45px font-bold leading-none hover:underline">
<img class="site-header__logo-img" src="<?php echo esc_url( $headerLogo ); ?>" alt="<?php echo esc_attr( get_bloginfo( 'name' ) ); ?> logo" /> <img class="site-header__logo-img aspect-square h-full w-full max-h-12 max-w-12" src="<?php echo esc_url( $headerLogo ); ?>" alt="<?php echo esc_attr( get_bloginfo( 'name' ) ); ?> logo" /> Keith Solomon
</a> </a>
<?php get_template_part( 'views/components/nav-main' ); ?> <?php get_template_part( 'views/components/nav-main' ); ?>
<div class="site-header__aux"> <div class="site-header__aux">
<a class="button button--outline" href="<?php echo esc_url( home_url( '/cv/' ) ); ?>"> <a class="button button--outline" href="<?php echo esc_url( $linkResume ); ?>">
<?php echo esc_html__( 'Download CV', 'ks-portfolio' ); ?> <?php echo esc_html__( 'Resume', 'ks-portfolio' ); ?>
</a> </a>
</div> </div>
</div> </div>
+7 -3
View File
@@ -65,16 +65,20 @@ add_filter(
/** /**
* Checks if the page should render a page header. * Checks if the page should render a page header.
* *
* Returns true only when the page heading ACF field is explicitly set to
* 'default'. When 'none' is selected, no page header should render (the
* page instead relies on its own hero block / template hero).
*
* @return bool true if page header should be rendered, false otherwise * @return bool true if page header should be rendered, false otherwise
*/ */
function hasPageHeader() { function hasPageHeader() {
global $post; global $post;
if ( get_field( 'hero_style' ) !== 'none' ) { if ( get_field( 'hero_style' ) === 'default' ) {
return false; return true;
} }
return true; return false;
} }
/** Create the Owner role. /** Create the Owner role.
+1 -4
View File
@@ -27,9 +27,7 @@ while ( have_posts() ) :
$type_label = ! empty( $type_terms ) && ! is_wp_error( $type_terms ) ? strtoupper( $type_terms[0]->name ) : ''; $type_label = ! empty( $type_terms ) && ! is_wp_error( $type_terms ) ? strtoupper( $type_terms[0]->name ) : '';
$excerpt = has_excerpt( $project_id ) ? get_the_excerpt( $project_id ) : ''; $excerpt = has_excerpt( $project_id ) ? get_the_excerpt( $project_id ) : '';
?> ?>
<article class="single-project aura-bg"> <article class="single-project">
<?php get_template_part( 'views/partials/aura-bg' ); ?>
<div class="aura-bg__content">
<div class="container mx-auto my-section"> <div class="container mx-auto my-section">
<header class="single-project__hero"> <header class="single-project__hero">
@@ -160,7 +158,6 @@ while ( have_posts() ) :
</aside> </aside>
</div> </div>
</div> </div>
</div>
</article> </article>
<?php <?php
endwhile; endwhile;
+2 -2
View File
@@ -45,9 +45,9 @@
--color-surface-container-low: #1a1b21; --color-surface-container-low: #1a1b21;
--color-surface-container: #1e1f25; --color-surface-container: #1e1f25;
--color-surface-container-high: #292a2f; --color-surface-container-high: #292a2f;
--color-surface-container-highest:#34343a; --color-surface-container-highest: #34343a;
--color-on-surface: #e3e1e9; --color-on-surface: #e3e1e9;
--color-on-surface-variant:#c5c5d3; --color-on-surface-variant: #c5c5d3;
--color-outline: #8f909d; --color-outline: #8f909d;
--color-outline-variant: #444651; --color-outline-variant: #444651;
--color-page-base: #100e0b; --color-page-base: #100e0b;
+9 -4
View File
@@ -84,12 +84,17 @@ main#maincontent {
.embed { position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; } .embed { position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; }
.embed iframe, .embed object, .embed embed, .embed video { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } .embed iframe, .embed object, .embed embed, .embed video { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
/* Carbon Blue atmospheric field (decorative — content must sit in z-index: 1) */ /* Carbon Blue atmospheric field — rendered once globally (in header.php)
* as a fixed-position layer behind all content. Decorative only; content
* stays clickable thanks to pointer-events: none. The body carries
* `background-color: #100e0b` so the gradient's mix-blend-mode layers
* have something to composite against. */
.aura-bg { .aura-bg {
position: relative; position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
overflow: hidden; overflow: hidden;
min-height: 100vh;
isolation: isolate;
} }
.aura-layer-1 { .aura-layer-1 {
+1 -3
View File
@@ -169,9 +169,7 @@ pre code {
padding: 0; padding: 0;
} }
code { code { @apply bg-black/30 px-0.25 py-0.5 font-mono text-black text-xs rounded-sm; }
@apply bg-black/30 px-[3px] py-0.5 font-mono text-black text-xs rounded-sm;
}
hr { hr {
background-color: black; background-color: black;
+1 -4
View File
@@ -12,9 +12,7 @@ get_header();
$queried = get_queried_object(); $queried = get_queried_object();
$term_name = $queried && ! is_wp_error( $queried ) ? $queried->name : __( 'Projects', 'ks-portfolio' ); $term_name = $queried && ! is_wp_error( $queried ) ? $queried->name : __( 'Projects', 'ks-portfolio' );
?> ?>
<section class="archive-projects aura-bg"> <section class="archive-projects">
<?php get_template_part( 'views/partials/aura-bg' ); ?>
<div class="aura-bg__content">
<div class="container mx-auto my-section"> <div class="container mx-auto my-section">
<header class="archive-projects__head"> <header class="archive-projects__head">
<h1 class="archive-projects__title"><?php echo esc_html( $term_name ); ?></h1> <h1 class="archive-projects__title"><?php echo esc_html( $term_name ); ?></h1>
@@ -53,7 +51,6 @@ $term_name = $queried && ! is_wp_error( $queried ) ? $queried->name : __( 'Proje
</div> </div>
<?php endif; ?> <?php endif; ?>
</div> </div>
</div>
</section> </section>
<?php <?php
+58
View File
@@ -0,0 +1,58 @@
const { test, expect } = require('@playwright/test');
test.use({ viewport: { width: 1920, height: 1080 } });
test.describe('aura-bg Carbon Blue gradient (global, fixed background)', () => {
test('body carries the dark base color that the aura layers blend against', async ({ page }) => {
await page.goto('/');
// Without the body color, mix-blend-mode on the aura layers has nothing
// to composite against and the gradient disappears.
const bodyBg = await page.evaluate(() => getComputedStyle(document.body).backgroundColor);
// #100e0b = rgb(16, 14, 11)
expect(bodyBg).toBe('rgb(16, 14, 11)');
});
test('.aura-bg renders globally as a fixed viewport layer (not a per-template wrapper)', async ({ page }) => {
await page.goto('/');
// aura-bg is rendered once in header.php and must be position:fixed so
// it covers the entire viewport behind all content regardless of scroll.
const auraBg = page.locator('.aura-bg').first();
await expect(auraBg).toBeAttached();
const position = await auraBg.evaluate((el) => getComputedStyle(el).position);
expect(position).toBe('fixed');
// z-index: -1 puts the gradient behind page content. Content must sit
// on top via its own stacking context (which the body and main do not
// create, so the negative z-index is safe).
const zIndex = await auraBg.evaluate((el) => getComputedStyle(el).zIndex);
expect(zIndex).toBe('-1');
// pointer-events: none so clicks pass through to content underneath.
const pointerEvents = await auraBg.evaluate((el) => getComputedStyle(el).pointerEvents);
expect(pointerEvents).toBe('none');
});
test('.aura-layer-1 renders the Carbon Blue linear gradient', async ({ page }) => {
await page.goto('/');
const layer1 = page.locator('.aura-layer-1').first();
await expect(layer1).toBeAttached();
const bgImage = await layer1.evaluate((el) => getComputedStyle(el).backgroundImage);
expect(bgImage).toMatch(/linear-gradient/);
});
test('.aura-bg is not isolated (no stacking context traps blend modes)', async ({ page }) => {
await page.goto('/');
// isolation: isolate on the .aura-bg parent would trap mix-blend-mode
// children inside an empty container, preventing them from blending
// with the body's #100e0b beneath. The global fixed layer must let
// blend modes reach through to the body.
const isolation = await page.locator('.aura-bg').first().evaluate((el) => getComputedStyle(el).isolation);
expect(isolation).not.toBe('isolate');
});
});
+1 -1
View File
@@ -9,7 +9,7 @@ test.describe('home', () => {
await page.screenshot({ path: 'test-results/home.png', fullPage: true }); await page.screenshot({ path: 'test-results/home.png', fullPage: true });
// Hero region must be present. // Hero region must be present.
await expect(page.locator('.home-hero')).toBeVisible(); await expect(page.locator('.homepage-hero')).toBeVisible();
// Either the grid OR the empty state must be present. // Either the grid OR the empty state must be present.
const grid = page.locator('.home-recent__grid'); const grid = page.locator('.home-recent__grid');