Skip to content

feat(website): the reliability band becomes a preflight checklist - #1067

Merged
blove merged 23 commits into
mainfrom
blove/reliability-dark-redesign
Sep 8, 2026
Merged

feat(website): the reliability band becomes a preflight checklist#1067
blove merged 23 commits into
mainfrom
blove/reliability-dark-redesign

Conversation

@blove

@blove blove commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Two connected changes to the homepage's dark proof band, on the aviation theme the site now uses.

Compatibility moved out. The band was arguing two things at once, and the partner logos were invisible on the dark ground. <Compatibility /> is now its own light section that names all twelve integrations instead of hiding three behind a "+3 more" badge.

The band became a preflight checklist. It previously argued trustworthiness as four big figures and three prose receipts — a certificate, not a preflight. Pilots run checklists, and the useful half of a checklist is the part still outstanding. So:

  • Threadplane — 11 ticked rows, each linking to the doc page that proves it.
  • Yours — 8 rows, phrased in the docs' own words. These boxes never fill. That is the argument, not an oversight.
  • Airworthiness — 8 rows where the response is the figure, each linking to its source.

The framing stays: the "Climb performance" eyebrow and the Vx/Vy aside (Vx clears today's obstacle; Vy gets you to altitude).

Three claims were wrong, and the docs caught them

The rows were verified against the docs rather than written from memory, which is the only reason the band can keep saying "not self-reported":

  • "Destructive actions — HELD FOR APPROVAL" was false. <chat> does not render the interrupt panel; the docs say to compose <chat-interrupt-panel> yourself. It is two Yours rows now, which is the stronger claim anyway. This had appeared in every mockup.
  • "Errors & retry" had been held back as unverified and is in fact the strongest line on the list — zero-config retry across five classified error kinds. It leads the column.
  • Keyboard & screen reader stays off. Four components document accessibility; there is no overview, no audit, nothing to link. A tick would overclaim.

Notes

  • #proof, #proof-heading and data-surface="dark" are unchanged, so e2e/website.spec.ts passes without being edited.
  • The HVTrust grade stays a live badge image rather than becoming text — it sits near an A-band floor of 80 and has flipped grade several times in a month.
  • The Angular range is derived from WEBSITE_SUPPORTED_ANGULAR_MAJORS, not typed, so bumping a major updates the homepage. The guard for this is mutation-verified: hardcoding the string fails with expected '20-22' to be '41-43'.
  • compatibility-heading was added to the e2e spine — the new section could otherwise have been deleted from page.tsx with all 128 tests green.

Test Plan

  • npx nx test website — green
  • npx nx lint website — 0 errors
  • npx nx build website — green
  • npx nx e2e website — 128 passed, 1 skipped, #proof assertions unedited
  • All 13 internal proof links return 200; all off-site sources resolve (npmjs.com 403s to curl via Cloudflare bot-blocking — both packages confirmed present via the registry API, and that link is already live in production)
  • Measured in a real browser at 1440px: 27 boxes, exactly two left edges, all 16x16; 19 links, 8 unlinked; 19 ticked, 0 in Yours
  • At 390px: columns stack, all boxes on one left edge, no row wraps, no horizontal overflow
  • Verify on production after merge

Spec: docs/superpowers/specs/2026-09-08-preflight-checklist-design.md
Plan: docs/superpowers/plans/2026-09-08-preflight-checklist.md

🤖 Generated with Claude Code

blove and others added 23 commits September 8, 2026 11:57
…ction

Three measured defects: the works-with logos have no colour treatment at all
so dark marks sit invisible on navy; the proof cells kept neutral
rgb(28,28,28) surfaces after #1058 moved the ground to scope navy; and the
hero strip is the same navy as the section that starts 78px later, so it
cannot close the yellow block the way it was designed to.

The aviation frame is Vx versus Vy — best angle clears the obstacle in front
of you and leaves you lower ten minutes later; best rate is what actually gets
you to altitude. It lands in the aside line, not the heading, so the working
argument and the copy guard are left alone.

Fixes are subtractive: card chrome off the figures, one pitch-ladder divider
instead of four background layers, and the logo row out of the section
entirely. Moving that row to a light ground retires the CSS filter an earlier
draft needed — the marks are drawn for light backgrounds, so on white there is
nothing to normalise and nothing to guard.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Six tasks, TDD where there is something to assert. Notable details the plan
pins down rather than leaving to discovery:

- The masthead needs margin-top: calc(-1 * var(--spacing-section-y)). Section
  sets its own top padding, so a first child would sit below it with a navy gap
  above — defeating the point of moving the strip to the seam.
- The ordering assertion uses getAttribute('class') for the SVG, because
  className on an SVG element is an SVGAnimatedString and comparing it to a
  string fails confusingly.
- "+ 4 more" becomes "+ 3 more": a comment in Reliability.tsx documents the
  four as Azure OpenAI, Pydantic AI, Microsoft Agent Framework and AWS Strands,
  and Strands is now named in the runtimes group — it was already cited by name
  in a reliability receipt, so hiding it in a count was odd.
- The watermark is explicitly protected. No task touches it and it sits in the
  same stretch of CSS as the chrome being removed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A negative margin-top on an in-flow first child drags every following sibling
up with it, not just itself. So pulling the masthead onto the section's top
edge also removed the proof band's entire top padding — the eyebrow would have
sat flush against the bar. The matching bottom margin returns exactly what the
top pulled away.

Verified in a real layout engine, since jsdom applies no CSS: at 1280px the
masthead is flush with both the hero's bottom and the section's top (0 and 0)
and the heading keeps 143px of clearance.

Also corrects two comment claims: the bar is flat --color-scope while the band
is a gradient that only reaches that value at its bottom, and that difference
is what stops the bar dissolving into the band.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…mily

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…are gone

gap: 20px was a card-to-card gutter. With the cards removed, whitespace is the
only grouping cue left, and 20px was no larger than the gaps INSIDE a cell —
so wherever the grid stacks (≤900px and ≤560px) the rhythm argued that a
caption belonged to the numeral below it rather than above.

Now 44px 40px: the row gutter beats the intra-cell spacing 44 to 12, and the
column gutter is the old card padding expressed as column-gap, which is what
column-gap is for. That also drops a padding-right that was being applied to
the last cell too, shaving the row's right edge out of line with the receipts
border beneath it.

Also corrects two comments the previous commits made stale: the rationale cited
proof cards that no longer exist (--color-surface now dresses the secondary
button and the focus halo in that band), and a note 130 lines away still called
the dark scope's surface "dark grey".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The works-with row closed the dark reliability band, where the vendor
marks were invisible: .reliability-logo set only width/height/object-fit,
so Anthropic's #181818 mark sat on navy and Google's full-colour one was
the loudest thing in a band meant to be quiet. The section was also
carrying two arguments at once — trustworthy, and compatible.

The row now has its own light section, which is what makes the marks
legible: they are drawn for light grounds and need no treatment there,
so there is no CSS filter to guard. It is grouped (providers, runtimes,
protocols) instead of a flat run, AWS Strands is promoted out of the
hidden count (a reliability receipt already names it), and the
compatibility-not-endorsement claim is now visible text rather than
alt="" plus a spec comment.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… a count

The compatibility section named nine integrations and closed the Agent
runtimes group with a "+ 3 more" badge. The three it hid were Azure
OpenAI, Pydantic AI and Microsoft Agent Framework — and Azure OpenAI is
a model provider, not a runtime, so the section told a reader there were
three more runtimes when one of them was not. The badge's trigger was
`group.label === 'Agent runtimes'`, a string comparison against display
copy: rewording the label would have made it silently vanish. All three
marks were already on disk, so all twelve are now named in the group
each actually belongs to and COMPATIBILITY_MORE_COUNT is gone.

The spec could not see content disappear. Every test iterated
COMPATIBILITY_GROUPS — the same constant the component renders from — so
deleting the entire Protocols group, LangGraph and AG-UI, the two with
shipped first-party adapters, left all five tests green. A new test pins
the shape independently: three groups by name, twelve items, and four
entries looked up by literal text. Verified non-vacuous by deleting the
Protocols group and watching only that test fail.

The group lists had also lost their accessible name. The old markup
pointed each <ul> at a label via aria-labelledby; the rewrite left the
label in a bare <p> with no association, and the test that replaced the
old assertion was named for checking it without doing so. Each list now
takes its name from the sibling label through an id derived from that
label, so a reword cannot leave the list unnamed, and the spec asserts
getByRole('list', { name }) for every group.

Also: the adapter-guide CTA gains a weight bump and a hover colour (on
this light ground --color-accent is navy against near-black ink, a very
small hue step at 11px with no underline); the pitch-ladder comment no
longer claims a horizon the drawing does not have; and the ladder's
hairlines take vector-effect: non-scaling-stroke so they survive the
svg scaling down below its 700px viewBox. That property is not
inherited, so it sits on the lines rather than the <g> elements.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…cution

The badge could not be stated honestly: it rendered only under Agent runtimes
while one of the three hidden entries, Azure OpenAI, is a model provider. All
three marks already existed on disk, so the shipped version names all twelve
and deletes the count.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Capped at 700px and left-aligned inside a 1120px container, the instrument's
waterline landed ~210px left of the band's centre and the whole thing read as
stray marks rather than an attitude indicator. Full width puts the waterline
on the container's centre line (640/640 measured) and makes it what the
comment always claimed it was: a divider that happens to mean something.

The strokes hold their weight at any scale because vector-effect:
non-scaling-stroke is on the lines, not the groups — vector-effect is not an
inherited property, so on the groups it would have been a no-op that looked
correct.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ee stale documents

The Compatibility section shipped as a new top-level block with no e2e
presence. The spine spec enumerates the homepage by heading id and asserts
document order, but `compatibility-heading` was never added — so the section
could have been reordered or deleted from page.tsx outright with all 128
Playwright tests and the whole unit suite still green (the unit spec renders
the component in isolation and never asserts it is mounted). Verified by
mutation: commenting out <Compatibility /> now fails the spine spec on
`locator('#compatibility-heading')` not being attached.

A comment in Reliability.tsx inverted the colour relationship it explained.
It described the masthead bar as --color-scope flat against a band gradient
"that only reaches that value at its bottom", which was true when written; a
later commit moved the band to #0B1622 → #0F1C2E, which never reaches
--color-scope #15253E, so the bar is now lighter than every part of the band.

The plan and the design spec still described a design that did not ship: cell
padding that became the grid's column-gap, a ladder max-width cap that was
removed and stroke rules that gained vector-effect, and a compatibility list
of eight marks with a "+ 4 more" badge where twelve are now named with no
count constant.

Also: the 900px .proof-strip-grid gap was left at 32px while the cells grid
was re-tuned to a 44px row gutter, inverting the grouping the cells comment
argues for; an orphan .compatibility-name class with no stylesheet rule and a
.proof-strip-cell positioning context whose ::before was deleted are gone; the
customer-claim copy guard is restored to Reliability.spec.tsx alongside its
copy in Compatibility.spec.tsx; the Compatibility region's aria-labelledby is
now pinned; and the proof cells list gained aria-label="Published scores" so
it is not an unnamed list beside a named one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Four pages share that component and inherited the darker ground. Verified on
the rendered /langgraph rather than reasoned about: the secondary button was
the same grey-black-on-navy mismatch the proof cards had, and unlike the cards
it still exists — so it is the one element the change visibly improves.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Pilots run checklists, and the band's most useful half turns out to be the
part still outstanding: 11 ticked rows for what Threadplane provides, 8
unticked for what stays yours, phrased in the docs' own words. The Yours boxes
never fill — that is the argument, not an oversight. Beneath, the audit
numbers become an Airworthiness block where the response IS the figure.

Every row was checked against the docs rather than written from memory, and
that caught three errors. "Destructive actions — HELD FOR APPROVAL" was FALSE:
<chat> does not render the interrupt panel, and the docs say so outright. It
became two Yours rows. "Errors & retry", which had been held back as
unverified, is the opposite — zero-config retry across five classified error
kinds, now the first row. Keyboard and screen reader stays off: four
components document a11y, there is no audit, and reduced motion exists only in
code with nothing to link.

Supersedes the pitch ladder from the scope-redesign spec — the checklist is
the aviation device now, and two would be one too many.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…range

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The plan's version asserted the response contains the first and last
supported major, which the literal '20-22' satisfies just as well as the
template does. It would only have failed once someone bumped a major --
by which point the homepage had already shipped the wrong range.

Stub the dependency to [41,42,43] instead and assert the value follows.
Mutation-verified: hardcoding the string fails with
'expected 20-22 to be 41-43'.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The margin was on the list, so the heading sat flat against the last
Threadplane row -- measured 0px between them -- while being pushed away
from the rows it labels. Measured 38px after.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
threadplane Ready Ready Preview Sep 8, 2026 7:05pm UTC

Request Review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated approval: this PR received an intelligent (AI) code review. See the review comments on this PR.

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Claude finished @blove's task in 0s —— View job


I'll analyze this and get back to you.

@blove
blove merged commit 8b18f1a into main Sep 8, 2026
33 checks passed
@blove
blove deleted the blove/reliability-dark-redesign branch September 8, 2026 19:18
blove added a commit that referenced this pull request Sep 9, 2026
…1089)

* feat(website): replace the whitepaper disclosure and drop the direct links

Requested change. The form now reads 'We will never spam you or share your
email address.' in place of the three-email outreach disclosure, and the
two 'Download the PDF directly' escapes are gone: the 'Already on the list?'
line and the one in the failure block.

Recorded because it is not a copy edit: whitepaper signups are still
enrolled into the founder campaign (campaign/send.ts treats formKind
'whitepaper' as a campaign context), so the follow-up sequence still sends
and is no longer disclosed at the point of capture. Raised before making
the change and confirmed. GROWTH_FORM_POLICY_VERSION is bumped to
growth_v1.2026-09-09 so consent captured under the old wording stays
distinguishable from consent captured under this one, and the constant is
renamed WHITEPAPER_PRIVACY_ASSURANCE because it no longer discloses outreach.

The SUCCESS block keeps its direct link -- that reader has already given
their address and the copy promises it ('the PDF is here too'). The failure
block now says 'Try again in a moment.' rather than handing over the file.

Also removes the .wp-already rules and the home_whitepaper_direct_inline
analytics id, both of which nothing can reach any more.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(website): reorder the fork band, trim the plate, swap the briefing titles

- OpenSourceStrip moves above Stage, so the fork band follows the
  architecture diagram. The e2e spine order moves with it.
- The airport plate loses its N/S/E taxiways -- lines, letters, the
  TaxiwayLetter component, the TWY_* constants and the .ap-taxiway /
  .ap-twy-* rules -- and gains 44 viewBox units of margin below the
  southern runway (NEAT 444->488, VIEW 536->580, furniture shifted with it).
- The off-airport strip now reads 'All AI Models supported'.
- 'Compatibility, not endorsement' and 'Everything on the right is yours'
  are removed.
- The briefing titles swap: the eyebrow carries the problem, the h2 carries
  the offer. '· free' leaves the eyebrow meta because the headline now
  opens with 'Free'.

Two guards changed rather than deleted. Compatibility.spec kept its
negative half -- nothing may read as an endorsement, and 'never sees' must
still appear nowhere, that being the overclaim #1067 corrected -- while
losing the positive never-TALKS-TO assertion, since that claim leaves the
homepage with the old strip copy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(website): the architecture diagram scales instead of scrolling

It was never scaling at all. The docs kit floors every figure at a render
width so shrinking the SVG cannot shrink its text into illegibility, and the
marketing scale caps it at 860 -- but min-width beats max-width, so the two
together pinned this diagram at exactly 1024px: ~96px of the container went
unused on desktop, and between 768 and 1024 the figure scrolled sideways
until the phone stack snapped in.

Both constraints are dropped so width:100% governs. The max-width override
needs .arch-figure .tp-diagram-figure[data-scale] .tp-diagram-svg -- the
marketing cap is (0,3,0) and a plain .arch-figure descendant selector loses
to it, which is how the first attempt at this silently stayed at 860px.

Legibility now comes from the breakpoint rather than a floor: the phone
stack takes over below 1024px, so the SVG never renders under ~944px and
its 13.5px type never drops under ~10px. Measured at 1440px: 1120px wide,
11.8px type, no scroll. At 900px: stack, no page overflow.

Also removes the toast's standalone 'or download directly' link and its
now-dead .toast-download-link rule, and updates the airport e2e, which
pinned the three taxiways this branch removed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(website): the toast's failure block no longer hands over the PDF

Aligns it with WhitePaperForm, whose failure block was changed the same way
earlier on this branch: the guide is reachable only through a successful
submission, so a failed send says to retry rather than releasing the file.

trackWhitepaperDownloadClick and the toast_direct_download cta id go with
it -- nothing in the toast can emit either any more.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(website): the e2e follows the policy bump and the PDF gate

Both surfaced in CI, both real consequences of this branch.

website.spec.ts hardcoded growth_v1.2026-09-01 rather than importing it
(form-policy.ts is server-only and cannot load in a Playwright process), so
bumping the policy version made the running app post a value the suite did
not expect. Updated, with a comment saying it has to move with the constant.

'marketing pages link to downloadable whitepaper PDFs' failed because there
are no such links any more: removing every direct-download escape from
WhitePaperForm took the library pages' links with it. The test now asserts
the gate instead -- the PDFs stay served, they are just not linked -- so
re-adding a link is a deliberate act rather than a silent regression.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant