← Launch screen

Canvas & Current — Website

UX/UI design studio site. Hybrid local + national SEO architecture, Bootstrap 5.3 authoring layer, built as a system so new pages cost content time and never design time.

Round 1 built 2026-09-16. Three homepage directions for selection.


What is here

dist/
  index.html                        REVIEW LAUNCHER - open this first
  cc-home-a-deepwater.html          Direction A, navy-dominant, conversion-tight
  cc-home-b-chart.html              Direction B, cream editorial, chart system
  cc-home-c-riptide.html            Direction C, the deliberate overshoot
  favicon.ico                       at the ROOT of the deploy zip, browsers ask for it unprompted
  apple-touch-icon.png  icons/  site.webmanifest
  portable/                         html.to.design import variants (see below)
  cc-home-*-390.png                 full-page mobile captures

_build/
  src.scss        the only import chain. ORDER IS LOAD-BEARING, see below
  _theme.scss     brand tokens as Bootstrap Sass variable overrides
  _house.scss     grounds, .wrap, .eyebrow, buttons, cards, chrome, motion
  _skin-a/b/c     per-direction skins
  _mobile390.scss the 390 pass, appended LAST so it wins on source order
  entry-a/b/c.scss  src + skin + mobile390
  out-a/b/c.css   compiled, never edited by hand

build.py        emits the three pages from ONE content source
mkportable.py   emits the Figma-import variants
verify.js       the full sweep. run it after every change
brand-dna.md    palette, measured contrast, type, density, the mark
seo-architecture.md   the full page architecture, templates, schema, linking model
snapshots/      1280 and 390 captures per direction

Rebuilding

npm i -D bootstrap@5.3 sass playwright
cd _build && for d in a b c; do
  npx sass entry-$d.scss out-$d.css --style=compressed \
    --load-path=../node_modules --quiet-deps --silence-deprecation=import
done
cd .. && python3 build.py && python3 mkportable.py && node verify.js

Dart Sass prints @import deprecation warnings for Bootstrap's internals. Noise, not errors. Bootstrap 5.3 is built on @import; do not convert it to @use.

Never deploy HTML ahead of its recompiled CSS. build.py asserts --bs-primary equals the brand hex and that the buttons module is present, because a stale or silently-failed compile ships an unstyled page with no console error and nothing in the network tab.

The order rule

Every Bootstrap variable carries !default. A value set before variables wins; a value set after it is silently ignored. $primary: #67CCCF placed late compiles to Bootstrap blue with no warning at all. So _theme.scss is imported between functions and variables, and it contains no !default.

Budget

ABC
Inlined CSS96 KB97 KB98 KB
Page total205 KB191 KB196 KB
External requests1 (font stylesheet)11
Unique hexes in CSS27, all brand2729

Under the 100 KB CSS budget. The trim is $colors: (), $grays: (), a two-entry $theme-colors, a filtered $utilities map and only the Bootstrap modules actually used. Full Bootstrap is 232 KB.

Fonts

The build environment could not reach fonts.googleapis.com (egress policy), so the fonts ship as a <link> rather than base64-inlined. This is the documented fallback and the public host is an acceptable external ref. Before any client-facing review, base64-embed the display font so a cold cache or an ad-blocker cannot silently swap it for a system face, which is what "is this different fonts?" always turns out to be. Each direction already carries a narrow local fallback ("Arial Narrow", Georgia) so a slow load does not blow out the hero width.

Verification

verify.js sweeps nine widths (1600, 1440, 1280, 1200, 1024, 900, 768, 600, 390) and asserts:

Current state: 0 failing check groups across all three directions.

What the machine pass cannot see

Run a human pass alongside it, every time. On this build the screenshots caught two defects every assertion had passed:

  1. SVG arrows inside .chip ballooned to fill the flex container. House rule 4b scopes the fix to .btn; the same is true of every flex icon slot, and it is now in _house.scss for chips, the topbar, eyebrows, the drawer and the footer.
  2. The marquee's edge mask was applied to the element carrying the teal background, so it faded the band itself out at both ends.

Accessibility

WCAG 2.2 AA. Skip link, visible focus rings at 3px, prefers-reduced-motion honoured on every animation, semantic landmarks, aria-hidden on every decorative SVG, aria-label on every icon link, <details> for the FAQ so it works with no JS at all.

CSS-only animation throughout. JavaScript only ever adds a class (IntersectionObserver for scroll reveals, and the one-open-at-a-time FAQ); it never tweens a value.

Portable variants

dist/portable/ holds the html.to.design import files. Forms become static div replicas that keep their original classes, the Services mega menu and the drawer are hard-coded open (the portable strips JS, so anything that opens via a JS class reads as missing and invites a rebuild of something that already exists), and the generator asserts no unresolvable asset ref survives.

Regenerate them from the live files after every design change. Never fix a design in the portable — it is an import artifact and fixes made there never reach the real site.