fix(phasefinal-web): clean up the multi-page site

The 2026-09-28 expansion grew the one-page design to nine pages by
bolting a nav band under each hero. This makes the cluster one site:
- One site header on every page: the wordmark (home link) and a single
  row of short, consistent labels (Applications, Systems, Hosting, AI,
  Engagement, Track record, Contact). The nav no longer wraps into two
  rows at desktop width or four on a phone.
- A real <h1> on every page (the title was a <p>), a skip link, and one
  footer outside <main> on every page, home included.
- The contact page was unreadable: its section borrowed the home page's
  dark contact-card id, so its copy was grey on near-black (2.3:1) and
  its headings measured 1.0:1. It is an ordinary section now.
- Section numbers only where there is a sequence (home, engagement).
- The spec bar names all four services; it stacks cleanly on a phone.
- Contrast: --text-tertiary 4.3:1 -> 4.96:1, --accent-text 4.36:1 ->
  4.74:1 on paper. Track-record labels drop tracked capitals.
- The grid behind the hero and the contact card is its own layer; the
  contact card loses its left side-tab stripe.
- The stylesheet link is versioned (style.css?v=2026-09-28): CSS is
  cached for an hour, and the new markup must not meet the old styles.
- README: nine pages, the shared structure, the CSS-version rule, and the
  operator's anti-slop waivers (the hero's volt rule, Space Grotesk).

Copy is unchanged apart from nav labels (the brief's legal constraints
hold). Still zero JavaScript and zero external requests. Impeccable
detector (controls 7/0, static + rendered at 1280 and 390, light and
dark): 200 unwaived -> 54, all of them the two waived brand devices;
two identical runs. Operator: "ship the site cleanup, keep the rule and
the font".
This commit is contained in:
vh
2026-09-28 16:29:02 -07:00
parent 2296fbba12
commit 85f8a3a072
11 changed files with 378 additions and 278 deletions
+97 -63
View File
@@ -13,16 +13,17 @@
@font-face { font-family: "IBM Plex Mono"; src: url("fonts/IBMPlexMono-SemiBold.woff2") format("woff2"); font-weight: 600; font-display: swap; }
:root {
color-scheme: light dark;
--ink: #0f1318;
--ink-2: #181d22;
--text: #0f1318;
--text-secondary: #4d5763;
--text-tertiary: #6b7682;
--text-tertiary: #626d78; /* 4.96:1 on paper (was #6b7682, 4.3:1) */
--paper: #f6f8f9;
--border: #c2cad2;
--border-subtle: #dde2e7;
--accent: #90c73e;
--accent-text: #588021; /* AA on light */
--accent-text: #527a1e; /* 4.74:1 on paper (was #588021, 4.36:1) */
--volt-200: #d0e8a0;
--volt-300: #b8db72;
--volt-400: #a3d052;
@@ -65,6 +66,52 @@ body {
::selection { background: var(--volt-200); color: #0f1318; }
a { color: var(--accent-text); text-decoration: underline; text-underline-offset: 3px; }
:focus-visible { outline: 2px solid var(--volt-500); outline-offset: 3px; }
/* ---- Skip link: first stop for the keyboard, off-screen until focused ---- */
.skip {
position: absolute; left: 16px; top: 12px; z-index: 10;
transform: translateY(-200%);
padding: 8px 12px; border-radius: 6px;
background: var(--paper); color: var(--text);
font-family: var(--mono); font-size: 12.5px;
}
.skip:focus-visible { transform: none; }
/* ---- Site header: the brand and the whole site's nav, one row, every page ---- */
.site-header { background: var(--ink); color: #f6f8f9; }
.site-header-inner {
max-width: 920px;
margin: 0 auto;
padding: 18px 28px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 14px 32px;
flex-wrap: wrap;
}
.brand { display: block; line-height: 0; }
.brand img { height: 28px; width: auto; display: block; }
.site-nav ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-wrap: wrap;
gap: 4px 22px;
}
.site-nav a {
display: inline-block;
padding: 6px 0;
font-family: var(--mono);
font-size: 12px;
letter-spacing: 0.08em;
text-transform: uppercase;
text-decoration: none;
color: var(--slate-300);
}
.site-nav a:hover { color: var(--volt-300); }
.site-nav a[aria-current="page"] { color: #ffffff; box-shadow: inset 0 -2px 0 var(--volt-500); }
p { margin: 0; text-wrap: pretty; }
/* ---- Hero: ink console surface with engineering grid ---- */
@@ -72,28 +119,37 @@ p { margin: 0; text-wrap: pretty; }
background: var(--ink);
color: #f6f8f9;
position: relative;
isolation: isolate;
overflow: hidden;
border-bottom: 3px solid var(--volt-500);
}
/* The engineering grid is its own layer, so the text's background is the ink it
actually sits on (a detector reading the gradient as the background saw 1.1:1). */
#hero::before, .contact-card::before {
content: "";
position: absolute;
inset: 0;
z-index: -1;
pointer-events: none;
background-image:
linear-gradient(rgba(246,248,249,0.05) 1px, transparent 1px),
linear-gradient(90deg, rgba(246,248,249,0.05) 1px, transparent 1px);
background-size: 48px 48px;
border-bottom: 3px solid var(--volt-500);
}
.hero-inner {
max-width: 920px;
margin: 0 auto;
padding: clamp(56px, 9vw, 104px) 28px clamp(56px, 8vw, 96px);
padding: clamp(40px, 7vw, 80px) 28px clamp(52px, 8vw, 88px);
display: flex;
flex-direction: column;
gap: clamp(40px, 6vw, 64px);
}
.wordmark { height: clamp(48px, 7.5vw, 72px); width: auto; display: block; align-self: flex-start; }
.hero-copy { max-width: 800px; }
.lede {
margin: 0;
font-family: var(--display);
font-size: clamp(32px, 5.6vw, 54px);
line-height: 1.1;
@@ -128,6 +184,11 @@ p { margin: 0; text-wrap: pretty; }
.spec-bar span { padding: 0 18px; border-left: 1px solid var(--slate-700); }
.spec-bar span:first-child { padding-left: 0; border-left: none; }
.spec-bar .spec-accent { color: var(--volt-300); }
@media (max-width: 600px) {
/* stacked, a divider would only ever start a line: drop it */
.spec-bar { flex-direction: column; gap: 6px; }
.spec-bar span { padding: 0; border-left: none; }
}
/* ---- Body ---- */
main {
@@ -143,7 +204,7 @@ section {
flex-wrap: wrap;
gap: 32px;
}
#services { border-top: none; padding-top: clamp(52px, 7vw, 76px); }
main > section:first-of-type { border-top: none; padding-top: 72px; }
h2 {
margin: 0;
@@ -191,9 +252,7 @@ h2 .num { color: var(--accent-text); margin-right: 12px; }
.record + .record { border-top: 1px solid var(--border-subtle); }
.record dt {
font-family: var(--mono);
font-size: 12.5px;
letter-spacing: 0.05em;
text-transform: uppercase;
font-size: 13px;
color: var(--text-tertiary);
margin-bottom: 6px;
}
@@ -201,22 +260,20 @@ h2 .num { color: var(--accent-text); margin-right: 12px; }
.record dd { margin: 0; font-size: 17.5px; }
.record strong { font-family: var(--display); font-weight: 600; }
/* Contact — ink console panel */
#contact {
/* Contact — ink console panel (the home page's closing card) */
.contact-card {
display: block;
position: relative;
isolation: isolate;
overflow: hidden;
border-top: none;
background: var(--ink-2);
background-image:
linear-gradient(rgba(246,248,249,0.05) 1px, transparent 1px),
linear-gradient(90deg, rgba(246,248,249,0.05) 1px, transparent 1px);
background-size: 48px 48px;
border-left: 3px solid var(--volt-500);
border-radius: 16px;
padding: clamp(40px, 6vw, 72px);
padding: 64px;
color: #f6f8f9;
}
#contact h2 { color: var(--slate-400); margin-bottom: 20px; }
#contact h2 .num { color: var(--volt-400); }
.contact-card h2 { color: var(--slate-400); margin-bottom: 20px; }
.contact-card h2 .num { color: var(--volt-400); }
.contact-address {
font-size: clamp(23px, 4vw, 38px);
line-height: 1.25;
@@ -237,67 +294,49 @@ h2 .num { color: var(--accent-text); margin-right: 12px; }
font-size: 16px;
}
/* Footer */
footer {
/* Footer — the same on every page */
.site-footer {
max-width: 864px;
width: calc(100% - 56px);
margin: 0 auto;
padding: 28px 0 48px;
border-top: 1px solid var(--border-subtle);
display: flex;
justify-content: space-between;
align-items: baseline;
gap: 16px;
gap: 12px 24px;
flex-wrap: wrap;
padding-top: 28px;
font-family: var(--mono);
font-size: 12.5px;
color: var(--text-tertiary);
}
.site-footer nav { display: flex; flex-wrap: wrap; gap: 4px 18px; }
.site-footer nav a { color: var(--text-tertiary); text-decoration: none; }
.site-footer nav a:hover { color: var(--accent-text); text-decoration: underline; }
.site-footer nav a[aria-current="page"] { color: var(--text); }
@media (max-width: 480px) {
main { padding: 0 20px 56px; }
.hero-inner { padding-left: 20px; padding-right: 20px; }
.hero-inner, .site-header-inner { padding-left: 20px; padding-right: 20px; }
.site-footer { width: calc(100% - 40px); }
section { padding: 40px 0 48px; }
main > section:first-of-type { padding-top: 48px; }
.contact-card { padding: 36px 28px; }
.site-nav ul { gap: 2px 18px; }
}
/* ---- Multi-page additions (2026-09-28) ---- */
/* Top nav: monospace strip under the hero rule, matching the spec-bar voice */
.site-nav {
background: var(--ink-2);
border-bottom: 1px solid var(--border);
}
.site-nav ul {
max-width: 920px;
margin: 0 auto;
padding: 0 28px;
list-style: none;
display: flex;
flex-wrap: wrap;
gap: 4px 0;
}
.site-nav a {
display: block;
padding: 12px 16px;
font-family: var(--mono);
font-size: 12px;
letter-spacing: 0.09em;
text-transform: uppercase;
text-decoration: none;
color: var(--slate-400);
}
.site-nav a:hover { color: var(--volt-300); }
.site-nav a[aria-current="page"] {
color: #f6f8f9;
box-shadow: inset 0 -2px 0 var(--volt-500);
}
/* Sub-pages get a compact page header instead of the full hero */
.page-header {
background: var(--ink);
border-bottom: 3px solid var(--volt-500);
color: #f6f8f9;
}
.page-header .hero-inner { gap: 20px; padding-bottom: clamp(36px, 5vw, 56px); padding-top: clamp(36px, 5vw, 56px); }
.page-header .hero-inner { gap: 20px; padding-bottom: clamp(36px, 5vw, 56px); padding-top: clamp(28px, 4vw, 44px); }
.page-header .lede { font-size: clamp(26px, 4.4vw, 40px); }
.page-header .sublede { margin-top: 14px; }
.page-header .wordmark { height: clamp(30px, 4.5vw, 40px); }
.page-header .lede { line-height: 1.18; }
/* Service detail pages */
.detail-lede { font-size: 18.5px; max-width: 62ch; }
@@ -330,9 +369,4 @@ footer {
text-transform: uppercase;
color: var(--text-tertiary);
}
.related a { margin-right: 18px; }
/* Footer grows a nav echo */
footer nav { display: flex; flex-wrap: wrap; gap: 4px 18px; }
footer nav a { color: var(--text-tertiary); text-decoration: none; }
footer nav a:hover { color: var(--accent-text); }
.related a { margin-right: 18px; display: inline-block; white-space: nowrap; }