Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions public/specimen.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,10 @@
/* extracted from inline style attributes — CSP style-src 'self' blocks those */
.xs1{padding-top:44px}
.xs2{font-size:56px}

/* in-content conversion CTA on the dark band — pill link, >=44px hit area */
.band{margin-top:84px}
.band .cta{display:inline-block;margin-top:26px;border:1px solid rgba(242,234,220,.4);border-radius:999px;
padding:16px 24px;font-size:10px;letter-spacing:.14em;text-transform:uppercase;font-weight:600;
color:#F2EADC;text-decoration:none;transition:border-color var(--mid) var(--ease),background var(--mid) var(--ease)}
.band .cta:hover,.band .cta:focus-visible{border-color:var(--brass-lt);background:rgba(201,165,102,.14)}
7 changes: 7 additions & 0 deletions public/specimen.html
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,13 @@ <h2>Confidentiality</h2>
</section>
</div>

<div class="band">
<h2>That was a real one. Yours is read the same way.</h2>
<p>Four passes, by hand, and a plain document with each fault named in order of what it costs you — the fix beside it. Thirty seconds to ask, findings inside five working days, yours to keep either way.</p>
<a class="cta" href="/#start">Request the appraisal</a>
<div class="note">No revenue, ranking, ROAS, conversion, booked-call or sales-volume guarantees. Only the work.</div>
</div>

<footer>
<span class="sc">TinyStudio · tinystudio.io</span>
<span class="sc"><a href="/audit">The appraisal</a> · <a href="/pricing">Pricing</a></span>
Expand Down
2 changes: 1 addition & 1 deletion public/specimen.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(function(){var S='.phead h1,.phead .sub,.f,.notrun,section h2,section .lede';
(function(){var S='.phead h1,.phead .sub,.f,.notrun,section h2,section .lede,.band';
function r(){var e=[].slice.call(document.querySelectorAll(S));e.forEach(function(x){x.setAttribute('data-r','')});
var io=new IntersectionObserver(function(en){en.forEach(function(v){if(!v.isIntersecting)return;
var s=[].slice.call(v.target.parentNode.children).filter(function(n){return n.hasAttribute&&n.hasAttribute('data-r')});
Expand Down
29 changes: 29 additions & 0 deletions scripts/check-site.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1547,6 +1547,35 @@ for (const [pageName, pageHtml, expected] of canonicalPages) {
}
}

// ---- Specimen in-content conversion CTA ------------------------------------
// The /specimen proof page is where the homepage routes its "Read the
// specimen" call-out, so the reader who finishes the sample needs an
// in-content conversion CTA — not just the nav link — to request their own
// appraisal. The page must keep a .band block carrying an explicit CTA link
// to the request surface (/#start, same target as the nav CTA), and the
// band CTA must keep a >=44px hit area to stay within the site's own
// tap-target standard. These are STATIC SOURCE GUARDS (regex over the served
// HTML/CSS), not behavioral tests: CI has no browser.
const specimenCtaHtml = read("public/specimen.html");
const specimenCtaBand = specimenCtaHtml.match(/<div class="band">([\s\S]*?)<\/div>\s*<footer>/);
if (!specimenCtaBand) {
failures.push("Specimen page must keep an in-content conversion CTA band between the report and the footer.");
} else {
if (!/<a\b[^>]*class="cta"[^>]*href="\/#start"[^>]*>Request the appraisal<\/a>/.test(specimenCtaBand[1])) {
failures.push("Specimen conversion band must carry a .cta link to /#start labelled \"Request the appraisal\".");
}
if (!/No revenue, ranking, ROAS, conversion, booked-call or sales-volume guarantees\. Only the work\./.test(specimenCtaBand[1])) {
failures.push("Specimen conversion band must keep the no-guarantees note.");
}
}
const specimenCtaCss = read("public/specimen.css");
if (!specimenCtaCss.includes(".band .cta")) {
failures.push("specimen.css must style the band conversion CTA (.band .cta).");
}
if (!/\.band \.cta\{[^}]*padding:16px 24px/.test(specimenCtaCss)) {
failures.push("Specimen band CTA must keep a >=44px tap target (padding:16px 24px).");
}

for (const migration of ["migrations/0002_agent_runs.sql", "migrations/0003_agent_usage_limits.sql"]) { if (!existsSync(new URL(`../${migration}`, import.meta.url))) {
failures.push(`Missing migration: ${migration}`);
continue;
Expand Down
2 changes: 1 addition & 1 deletion scripts/test-heading-hierarchy.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const EXPECTED_OUTLINES = {
"public/audit.html": [1, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2],
"public/agents.html": [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
"public/pricing.html": [1, 2, 2, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, 2, 2],
"public/specimen.html": [1, 2, 2, 2, 2, 3, 2],
"public/specimen.html": [1, 2, 2, 2, 2, 3, 2, 2],
"public/brief-requested.html": [1, 2, 2, 2]
};

Expand Down
Loading