"Book Enterprise Demo" resolves to the scheduler control, not to the page containing it
Decided
PRIMARY_CTA.href is /contact#book, and #book is the id on the BookDemoTrigger row. The homepage hero link carries the same fragment.
Affects: lib/constants.ts, app/contact/page.tsx, app/page.tsx
What went wrong. The href was a bare /contact. The scheduler is real — Cal.com is configured, schedulingLink() returns kind: "live", and BookDemoTrigger renders a link to cal.com/novelsystems/demo — but it sits mid-page, below a hero and above a nine-step brief. So the highest-intent click on the site, offered from the header, three pricing cards, the footer and the homepage hero, all of them reading the word "Book", landed the reader at the top of a form. The promise and the delivery were different actions. That is the same defect as a wrong number — what the page says and what the page does disagree — except the reader finds out after committing rather than before.
Why a fragment rather than embedding the scheduler on `/pricing`. An iframe per pricing card would put three copies of a third-party booking widget on a page whose job is to be read, and would make a vendor's uptime a dependency of the pricing page rendering. The fragment costs nothing, keeps one booking surface, and is auditable.
Why this cannot rot. scripts/check-links.mjs resolves fragments against the ids it finds in the source, so renaming or deleting id="book" fails npm run verify and CI rather than producing a link that silently scrolls nowhere. Verified by breaking it deliberately: /contact#bookX → no id "bookX" anywhere in the source.
What would make this wrong: if the brief became the intended path for everyone and the scheduler were retired, the fragment would go with it — but so would the word "Book" in the label, which is the change that actually matters.