chore: phase 1 reset — minimalist child theme + content-source extraction
Resets the child theme to its Bricks-first minimalist form (per RESTART-PLAN.md
phases 1a-1d) and extracts the textual copy into a runtime-independent
/content-source/ directory.
Child theme files removed
- header.php, footer.php, page.php, index.php, front-page.php
- template-parts/{solution,industry,conversion-form}.php
- templates/page-*.php (10 Custom Page Templates)
- inc/render-blocks.php, render-blocks-native.php, render-bricks.php
- inc/shortcodes.php, i18n.php, form-handler.php, seo.php
- assets/css/components.css, assets/js/main.js
Reasoning: Bricks Templates (Header / Footer / Single — Page) and Bricks-edited
pages now drive every screen. Anything emitted from the child theme would
fight Bricks' own rendering and waste CSS specificity battles.
Child theme now contains only
- style.css, functions.php (simplified to ~60 lines), theme.json
- inc/cpt.php (case_study + scenario + industry taxonomy)
- assets/css/tokens.css (untouched — design system source of truth)
- assets/css/utilities.css (trimmed to skip-link + sr-only + focus-visible
+ reduced motion — everything else handled by Bricks)
- assets/fonts/Inter-Variable*.woff2 (RGPD self-hosted)
- README.md spelling out the Bricks-first contract
Content moved to /content-source/
- solutions-data.php, industries-data.php, technology-data.php,
editorial-data.php, forms-data.php — git mv preserves history
- README.md explaining their dual role: copy reference while building
in Bricks, and source for programmatic page generation when we
replicate an archetype across its variants.
Root README.md updated with the new repo layout + a pointer to
RESTART-PLAN.md and the archive/session-2-php-templates branch.
Memory file project_asterion_status.md updated for next-session resume.
What's preserved as before
- /BRIEF-Claude-Code.md, both PDFs, all .txt extracts
- /MISSING-ASSETS.md
- /ThirdParty/ (Bricks + WPML ZIPs, gitignored)
- LocalWP site at localhost:10004, Bricks v2.3.4 + WPML 4.9.3 active
- WPML EN/FR with directory URL strategy
- All Git history, both main and archive/session-2-php-templates branches
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,110 +1,13 @@
|
||||
/**
|
||||
* Asterion Bricks — Utilities
|
||||
* Asterion Bricks — Utilities (minimalist)
|
||||
*
|
||||
* Modern CSS reset + reusable utility classes.
|
||||
* Loaded after tokens.css, before components.css.
|
||||
*
|
||||
* Naming : prefix `av-` on every custom class.
|
||||
* Loaded after tokens.css. Holds the small set of helper classes Bricks
|
||||
* Builder cannot easily provide on its own (skip link, screen-reader-only
|
||||
* text, focus ring). Everything else — section padding, container widths,
|
||||
* button design, card styles — is set inside Bricks via tokens.
|
||||
*/
|
||||
|
||||
/* ============================================================================
|
||||
Modern CSS reset (inspired by Andy Bell's modern-css-reset, Josh Comeau)
|
||||
============================================================================ */
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
|
||||
* { margin: 0; padding: 0; }
|
||||
|
||||
html {
|
||||
font-size: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
scroll-behavior: smooth;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: var(--font-body);
|
||||
font-size: var(--text-body-md);
|
||||
line-height: var(--leading-body-md);
|
||||
color: var(--color-text-primary);
|
||||
background-color: var(--color-bg-default);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
img, picture, video, canvas, svg {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
input, button, textarea, select { font: inherit; color: inherit; }
|
||||
|
||||
p, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
ul, ol { list-style: none; }
|
||||
|
||||
table { border-collapse: collapse; border-spacing: 0; }
|
||||
|
||||
/* ============================================================================
|
||||
Heading hierarchy — opinionated defaults consumed when an element
|
||||
carries no Bricks-specific class. Bricks may override, that's expected.
|
||||
============================================================================ */
|
||||
|
||||
h1 {
|
||||
font-family: var(--font-display);
|
||||
font-size: var(--text-h1);
|
||||
line-height: var(--leading-h1);
|
||||
font-weight: var(--font-weight-bold);
|
||||
letter-spacing: var(--tracking-snug);
|
||||
}
|
||||
h2 {
|
||||
font-family: var(--font-display);
|
||||
font-size: var(--text-h2);
|
||||
line-height: var(--leading-h2);
|
||||
font-weight: var(--font-weight-bold);
|
||||
letter-spacing: var(--tracking-snug);
|
||||
}
|
||||
h3 {
|
||||
font-family: var(--font-display);
|
||||
font-size: var(--text-h3);
|
||||
line-height: var(--leading-h3);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
letter-spacing: var(--tracking-snug);
|
||||
}
|
||||
h4 {
|
||||
font-family: var(--font-display);
|
||||
font-size: var(--text-h4);
|
||||
line-height: var(--leading-h4);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
}
|
||||
|
||||
p {
|
||||
max-width: 72ch; /* prose readability per Design Handoff section 2.2 */
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
Focus visible — keyboard accessibility
|
||||
Removes outline only when focus came from the mouse; preserves it for keyboard.
|
||||
============================================================================ */
|
||||
|
||||
:focus { outline: none; }
|
||||
|
||||
:focus-visible {
|
||||
outline: var(--focus-ring-width) solid var(--focus-ring-color);
|
||||
outline-offset: var(--focus-ring-offset);
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
Skip link — first focusable element on every page (a11y)
|
||||
============================================================================ */
|
||||
|
||||
/* === A11y skip link — first focusable element on every page === */
|
||||
.av-skip-link {
|
||||
position: absolute;
|
||||
top: -40px;
|
||||
@@ -114,6 +17,7 @@ p {
|
||||
color: var(--color-text-on-dark);
|
||||
font-size: var(--text-body-sm);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
text-decoration: none;
|
||||
z-index: var(--z-toast);
|
||||
border-bottom-right-radius: var(--radius-md);
|
||||
}
|
||||
@@ -122,10 +26,7 @@ p {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
Visually hidden — content readable by screen readers, hidden visually
|
||||
============================================================================ */
|
||||
|
||||
/* === Visually hidden — readable by screen readers, hidden visually === */
|
||||
.av-sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
@@ -138,77 +39,25 @@ p {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
Container — centred max-width with responsive padding
|
||||
============================================================================ */
|
||||
|
||||
.av-container {
|
||||
max-width: var(--container-max);
|
||||
margin-inline: auto;
|
||||
padding-inline: var(--container-padding-mobile);
|
||||
width: 100%;
|
||||
/* === Focus visible — keyboard accessibility on every focusable element === */
|
||||
:focus { outline: none; }
|
||||
:focus-visible {
|
||||
outline: var(--focus-ring-width, 2px) solid var(--focus-ring-color, var(--color-info));
|
||||
outline-offset: var(--focus-ring-offset, 2px);
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.av-container { padding-inline: var(--container-padding-tablet); }
|
||||
}
|
||||
|
||||
@media (min-width: 1280px) {
|
||||
.av-container { padding-inline: var(--container-padding-desktop); }
|
||||
}
|
||||
|
||||
.av-container--narrow {
|
||||
max-width: 800px; /* article body */
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
Tap target minimum — WCAG AA / Apple HIG (44×44px)
|
||||
============================================================================ */
|
||||
|
||||
/* === Touch target minimum (WCAG AA / Apple HIG) === */
|
||||
.av-tap-target {
|
||||
min-width: var(--tap-target-min);
|
||||
min-height: var(--tap-target-min);
|
||||
min-width: var(--tap-target-min, 44px);
|
||||
min-height: var(--tap-target-min, 44px);
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
Stack helpers — vertical rhythm via owl-selector
|
||||
============================================================================ */
|
||||
|
||||
.av-stack > * + * { margin-top: var(--av-stack-gap, var(--space-4)); }
|
||||
.av-stack--sm > * + * { margin-top: var(--space-2); }
|
||||
.av-stack--md > * + * { margin-top: var(--space-4); }
|
||||
.av-stack--lg > * + * { margin-top: var(--space-8); }
|
||||
.av-stack--xl > * + * { margin-top: var(--space-12); }
|
||||
|
||||
/* ============================================================================
|
||||
Section padding helpers (vertical rhythm between page sections)
|
||||
============================================================================ */
|
||||
|
||||
.av-section {
|
||||
padding-block: var(--space-16);
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.av-section { padding-block: var(--space-20); }
|
||||
}
|
||||
|
||||
.av-section--hero {
|
||||
padding-block: var(--space-24);
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.av-section--hero { padding-block: var(--space-32); }
|
||||
}
|
||||
|
||||
.av-section--dark {
|
||||
background-color: var(--color-bg-dark);
|
||||
color: var(--color-text-on-dark);
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
Print
|
||||
============================================================================ */
|
||||
|
||||
@media print {
|
||||
.av-skip-link, .av-no-print { display: none !important; }
|
||||
body { color: #000; background: #fff; }
|
||||
a::after { content: " (" attr(href) ")"; font-size: 0.8em; }
|
||||
/* === Reduced motion — respect user preference === */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*, *::before, *::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
/**
|
||||
* Asterion Bricks — main JS
|
||||
*
|
||||
* Vanilla JS, defer-loaded. Wraps everything in DOMContentLoaded.
|
||||
* Performance budget : initial bundle < 200 KB gzipped.
|
||||
*
|
||||
* Modules planned :
|
||||
* - Header scroll behavior (background swap after 80px)
|
||||
* - Mega menu trigger (hover desktop, click touch, ESC closes)
|
||||
* - Mobile drawer (full-screen overlay, accordion sections)
|
||||
* - Scroll-triggered fade-in (IntersectionObserver, threshold 0.15)
|
||||
* - Stat callouts count-up (1000ms ease-out)
|
||||
* - Hero video lazy-load + reduced-motion fallback to poster
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Detect reduced motion once and expose a flag for downstream modules.
|
||||
* Updated reactively if the user toggles the setting mid-session.
|
||||
*/
|
||||
const reducedMotionQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
|
||||
let prefersReducedMotion = reducedMotionQuery.matches;
|
||||
reducedMotionQuery.addEventListener('change', (e) => {
|
||||
prefersReducedMotion = e.matches;
|
||||
});
|
||||
|
||||
/**
|
||||
* Header scroll behavior.
|
||||
* After 80px scroll, header gets a `is-scrolled` class
|
||||
* (consumed by .av-header.is-scrolled rule in components.css).
|
||||
*/
|
||||
function initHeaderScroll() {
|
||||
const header = document.querySelector('.av-header');
|
||||
if (!header) return;
|
||||
|
||||
let ticking = false;
|
||||
const onScroll = () => {
|
||||
if (!ticking) {
|
||||
window.requestAnimationFrame(() => {
|
||||
header.classList.toggle('is-scrolled', window.scrollY > 80);
|
||||
ticking = false;
|
||||
});
|
||||
ticking = true;
|
||||
}
|
||||
};
|
||||
onScroll();
|
||||
window.addEventListener('scroll', onScroll, { passive: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll-triggered fade-in (Design Handoff section 5.3).
|
||||
* Sections fade-in + slide-up 16px on entry, threshold 0.15, trigger once.
|
||||
* Skipped entirely if user prefers reduced motion.
|
||||
*/
|
||||
function initScrollReveal() {
|
||||
if (prefersReducedMotion) return;
|
||||
|
||||
const targets = document.querySelectorAll('[data-av-reveal]');
|
||||
if (!targets.length) return;
|
||||
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add('is-revealed');
|
||||
observer.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
}, { threshold: 0.15, rootMargin: '0px 0px -10% 0px' });
|
||||
|
||||
targets.forEach((target) => observer.observe(target));
|
||||
}
|
||||
|
||||
/**
|
||||
* Stat count-up (Design Handoff section 5.3).
|
||||
* Element : <span data-av-countup="0|target|duration">target</span>
|
||||
* Animates from 0 to target value over duration ms, ease-out.
|
||||
*/
|
||||
function initStatCountUp() {
|
||||
if (prefersReducedMotion) return;
|
||||
|
||||
const stats = document.querySelectorAll('[data-av-countup]');
|
||||
if (!stats.length) return;
|
||||
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (!entry.isIntersecting) return;
|
||||
const el = entry.target;
|
||||
const target = parseFloat(el.dataset.avCountup) || 0;
|
||||
const duration = parseInt(el.dataset.avCountupDuration || '1000', 10);
|
||||
const start = performance.now();
|
||||
|
||||
const tick = (now) => {
|
||||
const elapsed = Math.min((now - start) / duration, 1);
|
||||
// ease-out cubic
|
||||
const eased = 1 - Math.pow(1 - elapsed, 3);
|
||||
el.textContent = Math.round(target * eased).toLocaleString();
|
||||
if (elapsed < 1) requestAnimationFrame(tick);
|
||||
};
|
||||
requestAnimationFrame(tick);
|
||||
observer.unobserve(el);
|
||||
});
|
||||
}, { threshold: 0.5 });
|
||||
|
||||
stats.forEach((s) => observer.observe(s));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mobile drawer toggle.
|
||||
* Trigger : <button class="av-drawer-toggle" aria-controls="av-drawer">
|
||||
* Drawer : <div id="av-drawer" class="av-drawer">
|
||||
*/
|
||||
function initMobileDrawer() {
|
||||
const toggle = document.querySelector('.av-drawer-toggle');
|
||||
const drawer = document.getElementById('av-drawer');
|
||||
if (!toggle || !drawer) return;
|
||||
|
||||
const open = () => {
|
||||
drawer.classList.add('is-open');
|
||||
toggle.setAttribute('aria-expanded', 'true');
|
||||
document.body.style.overflow = 'hidden';
|
||||
};
|
||||
const close = () => {
|
||||
drawer.classList.remove('is-open');
|
||||
toggle.setAttribute('aria-expanded', 'false');
|
||||
document.body.style.overflow = '';
|
||||
};
|
||||
|
||||
toggle.addEventListener('click', () => {
|
||||
drawer.classList.contains('is-open') ? close() : open();
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape' && drawer.classList.contains('is-open')) close();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Boot.
|
||||
*/
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
initHeaderScroll();
|
||||
initScrollReveal();
|
||||
initStatCountUp();
|
||||
initMobileDrawer();
|
||||
});
|
||||
|
||||
})();
|
||||
Reference in New Issue
Block a user