Files
esh-pfi-infrastructure/stacks/phasefinal-web/conf/site/style.css
T
vh 85f8a3a072 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".
2026-09-28 16:29:02 -07:00

373 lines
11 KiB
CSS

/* Phase Final, Inc. — multi-page site
Brand: Volt #90C73E over cool slate neutrals, per Phase Final tokens.
Zero external requests; no JavaScript.
FONTS: the brand faces are Space Grotesk (display), IBM Plex Sans (body),
IBM Plex Mono (labels). To keep this zip free of external requests they are
referenced by local name only, with system fallbacks. To ship the exact
faces, place woff2 files in fonts/ and uncomment the @font-face blocks. */
@font-face { font-family: "Space Grotesk"; src: url("fonts/SpaceGrotesk-Var.woff2") format("woff2"); font-weight: 300 700; font-display: swap; }
@font-face { font-family: "IBM Plex Sans"; src: url("fonts/IBMPlexSans-Var.woff2") format("woff2"); font-weight: 100 700; font-display: swap; }
@font-face { font-family: "IBM Plex Mono"; src: url("fonts/IBMPlexMono-Regular.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@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: #626d78; /* 4.96:1 on paper (was #6b7682, 4.3:1) */
--paper: #f6f8f9;
--border: #c2cad2;
--border-subtle: #dde2e7;
--accent: #90c73e;
--accent-text: #527a1e; /* 4.74:1 on paper (was #588021, 4.36:1) */
--volt-200: #d0e8a0;
--volt-300: #b8db72;
--volt-400: #a3d052;
--volt-500: #90c73e;
--slate-300: #c2cad2;
--slate-400: #97a2ad;
--slate-700: #394149;
--slate-800: #262c33;
--display: "Space Grotesk", "IBM Plex Sans", -apple-system, "Segoe UI", Helvetica, sans-serif;
--sans: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
--mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}
@media (prefers-color-scheme: dark) {
:root {
--text: #f6f8f9;
--text-secondary: #c2cad2;
--text-tertiary: #97a2ad;
--paper: #0f1318;
--border: #394149;
--border-subtle: #262c33;
--accent-text: #b8db72;
--ink: #0a0d11;
--ink-2: #181d22;
}
}
* { box-sizing: border-box; }
body {
margin: 0;
background: var(--paper);
color: var(--text);
font-family: var(--sans);
font-size: 16.5px;
line-height: 1.65;
-webkit-font-smoothing: antialiased;
}
::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 ---- */
#hero {
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;
}
.hero-inner {
max-width: 920px;
margin: 0 auto;
padding: clamp(40px, 7vw, 80px) 28px clamp(52px, 8vw, 88px);
display: flex;
flex-direction: column;
gap: clamp(40px, 6vw, 64px);
}
.hero-copy { max-width: 800px; }
.lede {
margin: 0;
font-family: var(--display);
font-size: clamp(32px, 5.6vw, 54px);
line-height: 1.1;
letter-spacing: -0.02em;
font-weight: 500;
color: #ffffff;
text-wrap: balance;
}
.sublede {
margin-top: 24px;
font-size: clamp(16.5px, 2vw, 19px);
color: var(--slate-300);
max-width: 62ch;
}
.intro-note {
margin-top: 20px;
font-size: 16px;
color: var(--slate-400);
max-width: 62ch;
}
.spec-bar {
font-family: var(--mono);
font-size: 12.5px;
letter-spacing: 0.07em;
text-transform: uppercase;
color: var(--slate-400);
display: flex;
flex-wrap: wrap;
gap: 10px 0;
}
.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 {
max-width: 920px;
margin: 0 auto;
padding: 0 28px 72px;
}
section {
border-top: 1px solid var(--border);
padding: 52px 0 64px;
display: flex;
flex-wrap: wrap;
gap: 32px;
}
main > section:first-of-type { border-top: none; padding-top: 72px; }
h2 {
margin: 0;
flex: 0 0 208px;
font-family: var(--mono);
font-size: 12px;
font-weight: 600;
letter-spacing: 0.15em;
text-transform: uppercase;
color: var(--text-tertiary);
}
h2 .num { color: var(--accent-text); margin-right: 12px; }
.section-body { flex: 1 1 380px; max-width: 620px; }
/* Services */
.service-list {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 30px;
}
.service-list h3 {
margin: 0 0 6px;
font-family: var(--display);
font-size: 22px;
line-height: 1.3;
letter-spacing: -0.01em;
font-weight: 600;
}
.service-list h3 a { color: inherit; text-decoration: none; }
.service-list h3 a:hover { color: var(--accent-text); text-decoration: underline; }
.service-list p { color: var(--text-secondary); }
/* Engagement */
#engagement .section-body p + p { margin-top: 18px; }
.referral-note { color: var(--text-secondary); }
/* Track record */
.record-list { margin: 0; }
.record { padding: 24px 0 26px; }
.record:first-child { padding-top: 0; }
.record + .record { border-top: 1px solid var(--border-subtle); }
.record dt {
font-family: var(--mono);
font-size: 13px;
color: var(--text-tertiary);
margin-bottom: 6px;
}
.record .idx { color: var(--accent-text); margin-right: 6px; }
.record dd { margin: 0; font-size: 17.5px; }
.record strong { font-family: var(--display); font-weight: 600; }
/* 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);
border-radius: 16px;
padding: 64px;
color: #f6f8f9;
}
.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;
}
.contact-address a {
font-family: var(--display);
font-weight: 600;
letter-spacing: -0.015em;
color: var(--volt-300);
text-decoration: none;
border-bottom: 2px solid var(--volt-500);
}
.contact-address a:hover { color: var(--volt-200); }
.contact-note {
margin-top: 20px;
color: var(--slate-300);
max-width: 56ch;
font-size: 16px;
}
/* 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: 12px 24px;
flex-wrap: wrap;
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, .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) ---- */
/* 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(28px, 4vw, 44px); }
.page-header .lede { font-size: clamp(26px, 4.4vw, 40px); }
.page-header .sublede { margin-top: 14px; }
.page-header .lede { line-height: 1.18; }
/* Service detail pages */
.detail-lede { font-size: 18.5px; max-width: 62ch; }
.detail-lede + .detail-lede { margin-top: 18px; }
.detail-list {
list-style: none;
margin: 26px 0 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 24px;
}
.detail-list h3 {
margin: 0 0 4px;
font-family: var(--display);
font-size: 19px;
font-weight: 600;
letter-spacing: -0.01em;
}
.detail-list p { color: var(--text-secondary); }
/* Cross-links between pages */
.related {
margin-top: 28px;
padding-top: 18px;
border-top: 1px solid var(--border-subtle);
font-family: var(--mono);
font-size: 12.5px;
letter-spacing: 0.05em;
text-transform: uppercase;
color: var(--text-tertiary);
}
.related a { margin-right: 18px; display: inline-block; white-space: nowrap; }