);
}
/* Compact footer glossary - reachable from every page.
Matches the home and Knowledge Governance glossaries: canonical Mingi line,
knowledge execution layer as the noun, no spaced hyphens, no since-2009. */
const GLOSSARY_GENERAL = [
["Knowledge Execution", "The category. The compliant, AI-ready knowledge execution layer."],
["knowledge execution layer","The compliant layer between fragmented data and the humans, agents, and robots that act on it."],
["Trust Gate", "Human verification checkpoint. Nothing becomes knowledge without it."],
["knowledge packet", "The atomic unit. Small, self-contained, machine-legible."],
["GxP", "The regulated standard in life sciences."],
];
const GLOSSARY_BRAND = [
["Mingi", "Minerva's compliant intelligence, the result of integration between humans and AI."],
["VISDI", "Visual-Digital Knowledge. The architecture the layer is built on."],
["The Ledger", "Auditable, append-only governance and comms layer. Nothing is ever overwritten."],
["CLV", "Context Language Validation. The context-layer counterpart to CSV."],
];
/* Site footer */
function SiteFooter() {
const dim="rgba(231,239,250,0.55)";
const cols = [
{ label:"Explore", links:[["Knowledge Execution","/home/"],["Knowledge Governance","/knowledge-governance/"],["Compliant AI Readiness","/compliant-ai-readiness/"]] },
{ label:"Knowledge Governance", links:[
["Product Development","/product-development/"],
["Quality Improvement","/quality-improvement/"],
["Investigations","/investigations/"],
["Visualization","/visualization/"],
["Digitalization","/digitalization/"],
["Knowledge Management","/knowledge-management/"],
["Risk Management","/risk-management/"],
["Industries","/industries/"],
] },
{ label:"Compliant AI Readiness", links:[
["The Method","/method/"],
["Mingi","/mingi/"],
["Products","/products/"],
["By Function","/by-function/"],
] },
{ label:"The Firm", links:[
["About Minerva","https://minervakrm.com"],
["Our Team","/about-minerva/"],
["Blog","/blog/"],
["Start a Diagnostic","/start-a-diagnostic/"],
] },
];
return (
);
}
/* Shared closing band — single tagline + Start a Diagnostic button (dark theme).
Mirrors the KG domain/discipline closing bands, adapted to the CAIR pages. */
const DIAG_HREF = "/start-a-diagnostic/";
function DiagnosticClose({ headline, bg = "#0B1828" }) {
return (
{headline}
the Minerva way
Start a Diagnostic
);
}
Object.assign(window, { WheelMark, NavBar, Btn, Eyebrow, EyebrowMark, HeadlineDivider, Arrow, Icon, CircuitSVG, VineBorder, PageHero, SiteFooter, DiagnosticClose, STAGE, WORDMARK, MARK_SRC, VISDI_ICON });
/* ── Scroll-triggered animations - injected once, active on all pages ──
IMPORTANT: this preview engine has a bug where a dynamically-injected
attribute-selector CSS rule (e.g. [data-animate]{opacity:0}) wrongly beats
an element's own inline style on React-rendered nodes - so a CSS hidden
base state can leave content stuck invisible. We therefore use NO opacity
CSS at all: the hidden state and the reveal are BOTH set as inline styles
(which behave correctly), and a MutationObserver hides nodes the instant
React inserts them so there is no first-paint flash. */
(function initAnim() {
if (window.__vaInit) return; window.__vaInit = true;
const SEL = '[data-animate],[data-stagger]';
const EASE = 'cubic-bezier(.2,.8,.2,1)';
const reduce = matchMedia('(prefers-reduced-motion:reduce)').matches;
const targets = el => el.hasAttribute('data-stagger') ? [...el.children] : [el];
const prep = el => {
if (el.__vaPrepped) return; el.__vaPrepped = true;
if (reduce) return; // reduced motion → never hide
const dur = el.hasAttribute('data-stagger') ? '.6s' : '.7s';
targets(el).forEach((t, i) => {
t.style.transition = `opacity ${dur} ${EASE}`;
if (el.hasAttribute('data-stagger')) t.style.transitionDelay = (i * 0.1) + 's';
t.style.opacity = '0';
});
};
const show = el => targets(el).forEach(t => { if (t.style.opacity !== '1') t.style.opacity = '1'; });
const inView = el => {
const r = el.getBoundingClientRect();
const h = window.innerHeight || document.documentElement.clientHeight;
return r.top < h * 0.92 && r.bottom > 0;
};
const scan = () => document.querySelectorAll(SEL).forEach(el => { prep(el); if (reduce || inView(el)) show(el); });
/* Hide tagged nodes the moment React inserts them (kills first-paint flash). */
const mo = new MutationObserver(scan);
const startMO = () => mo.observe(document.getElementById('root') || document.body, { childList: true, subtree: true });
startMO();
/* Poll ~5s to cover React's async render + reveal whatever is in view; the
scroll/resize listeners then reveal everything below the fold, forever. */
let tries = 0;
(function tick() { scan(); if (++tries < 50) setTimeout(tick, 100); })();
addEventListener('scroll', scan, { passive: true });
addEventListener('resize', scan, { passive: true });
/* Hard fallback - never leave content stuck invisible. */
setTimeout(() => document.querySelectorAll(SEL).forEach(show), 6000);
})();